diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 0c62f08..d32f298 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -35,7 +35,7 @@ body: attributes: label: Contract versions description: Include scenario, journal, diagnostic, and strategy versions that apply. - placeholder: scenario v4, journal v4, strategy v3 + placeholder: scenario v1, journal v1, strategy v1 validations: required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/contract-change.yml b/.github/ISSUE_TEMPLATE/contract-change.yml index c195f1b..df7e56f 100644 --- a/.github/ISSUE_TEMPLATE/contract-change.yml +++ b/.github/ISSUE_TEMPLATE/contract-change.yml @@ -20,7 +20,7 @@ body: id: versions attributes: label: Affected versions - placeholder: current v4; frozen v1-v3 unchanged + placeholder: current v1 and proposed change validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/cross-repository.yml b/.github/ISSUE_TEMPLATE/cross-repository.yml index 5660287..bc1e628 100644 --- a/.github/ISSUE_TEMPLATE/cross-repository.yml +++ b/.github/ISSUE_TEMPLATE/cross-repository.yml @@ -22,7 +22,7 @@ body: id: contracts attributes: label: Contract versions - placeholder: scenario v3, journal v3, strategy v3 + placeholder: scenario v1, journal v1, strategy v1 validations: required: true - type: dropdown diff --git a/.github/labels.json b/.github/labels.json index 5a62bca..a1e11d1 100644 --- a/.github/labels.json +++ b/.github/labels.json @@ -19,13 +19,8 @@ {"category": "effort", "name": "effort: medium", "color": "fef2c0", "description": "Multi-file change with moderate design or testing work"}, {"category": "effort", "name": "effort: large", "color": "f9d0c4", "description": "Broad change that should be split into reviewed increments"}, - {"category": "contract", "name": "contract: scenario-v1", "color": "5319e7", "description": "Frozen scenario and journal contract version 1"}, - {"category": "contract", "name": "contract: scenario-v2", "color": "5319e7", "description": "Frozen scenario and journal contract version 2"}, - {"category": "contract", "name": "contract: scenario-v3", "color": "5319e7", "description": "Transitional scenario and journal contract version 3"}, - {"category": "contract", "name": "contract: scenario-v4", "color": "5319e7", "description": "Current scenario and journal contract version 4"}, - {"category": "contract", "name": "contract: strategy-v1", "color": "7057ff", "description": "Historical external strategy protocol version 1"}, - {"category": "contract", "name": "contract: strategy-v2", "color": "7057ff", "description": "Historical external strategy protocol version 2"}, - {"category": "contract", "name": "contract: strategy-v3", "color": "7057ff", "description": "Current external strategy protocol version 3"}, + {"category": "contract", "name": "contract: scenario-v1", "color": "5319e7", "description": "Current scenario and journal contract"}, + {"category": "contract", "name": "contract: strategy-v1", "color": "7057ff", "description": "Current external strategy protocol"}, {"category": "dependency", "name": "dependency: persistra", "color": "006b75", "description": "Requires coordinated behavior or validation in Persistra"}, {"category": "dependency", "name": "dependency: upstream", "color": "006b75", "description": "Depends on an external project or toolchain"}, diff --git a/.github/repository.json b/.github/repository.json index b6b6ac1..0498cd5 100644 --- a/.github/repository.json +++ b/.github/repository.json @@ -1,5 +1,5 @@ { - "description": "Deterministic event-driven OCaml execution engine with versioned replay contracts and causal audit journals", + "description": "Deterministic OCaml trading replay engine", "homepage": "https://fallblu.github.io/trading-engine/", "topics": [ "backtesting", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e48c83..5dea87b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,7 +108,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 env: - PERSISTRA_COMPAT_REVISION: ade8c05e435c56d8df8eba88fed1284652fd731b + PERSISTRA_COMPAT_REVISION: 6874e175098519eef9904edf0bb9f27b244982e4 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -142,7 +142,7 @@ jobs: - working-directory: persistra env: PERSISTRA_TRADING_ENGINE_BINARY: ${{ github.workspace }}/trading-engine/_build/default/bin/main.exe - PERSISTRA_TRADING_ENGINE_CONTRACT_DIR: ${{ github.workspace }}/trading-engine/contracts/v3 + PERSISTRA_TRADING_ENGINE_CONTRACT_DIR: ${{ github.workspace }}/trading-engine/contracts/v1 run: uv run pytest --no-cov tests/integration/test_trading_engine.py persistra-latest-head: @@ -182,5 +182,5 @@ jobs: - working-directory: persistra env: PERSISTRA_TRADING_ENGINE_BINARY: ${{ github.workspace }}/trading-engine/_build/default/bin/main.exe - PERSISTRA_TRADING_ENGINE_CONTRACT_DIR: ${{ github.workspace }}/trading-engine/contracts/v3 + PERSISTRA_TRADING_ENGINE_CONTRACT_DIR: ${{ github.workspace }}/trading-engine/contracts/v1 run: uv run pytest --no-cov tests/integration/test_trading_engine.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 902e9ec..45ff8dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,87 +1,11 @@ # Changelog -## Unreleased - -- Add versioned machine-readable CLI success results and JSON failure diagnostics, plus bounded - JSON Lines standard-input spooling and unambiguous completed-journal standard-output pipelines. -- Publish scenario/journal contract v16 and strategy protocol v14 with typed, dimensioned strategy - metrics while retaining string-only metric compatibility through v15 and protocol v13. - -- Add bounded level-two order-book replay with fresh snapshots, contiguous absolute updates, - multi-level marketable depth, deterministic passive queue position, and locked-book support. -- Publish scenario/journal contract v15 and external strategy protocol v13 while preserving v14 - and protocol v12 as frozen compatibility contracts. -- Add causal quote/trade replay with displayed-liquidity capacity, aggressor-qualified passive - fills, maker/taker fee attribution, and economic event timestamps. -- Publish scenario/journal contract v14 and external strategy protocol v12 while preserving v13 - and protocol v11 as frozen compatibility contracts. -- Add conservative next-open and adverse-touch completed-bar execution models with strict fixed - spread and linear participation-impact configuration, explicit missing-volume policy, - tick-aligned prices, and separate price-component audit attribution. -- Publish scenario/journal contract v13 and external strategy protocol v11 while preserving v12 - and protocol v10 as frozen compatibility contracts. - -- Add exact stock-dividend, rights, and spin-off distributions with explicit basis allocation, - fractional rejection or cash-in-lieu policy, destination currency validation, target adjustment, - and complete journal attribution. -- Add stable-identity instrument lifecycle state for halt, resume, identifier/provider remapping, - expiration, and delisting with deterministic order cancellation and explicit terminal hold or - cash-out policy. -- Publish scenario/journal contract v12 and external strategy protocol v10 while preserving v11 - and protocol v9 as frozen compatibility contracts. -- Add deterministic trade-date and settlement-date accounting, versioned business-date settlement - calendars, settled and unsettled cash and position attribution, explicit settlement buying-power - policies, and auditable settlement completion and failure events. -- Publish scenario/journal contract v11 and external strategy protocol v9 while preserving v10 and - protocol v8 as frozen compatibility contracts. -- Add effective-time borrow availability, signed rates, locate clipping or rejection, recalls, - deterministic close-outs, and explicit missing-data behavior. -- Add effective-time currency credit/debit rates with Actual/365 or Actual/360 day count, simple or - daily compounding, deterministic cash-ledger entries, and realized P&L attribution. -- Publish scenario/journal contract v10 and external strategy protocol v8 while preserving v9 and - protocol v7 as frozen compatibility contracts. -- Added instrument-aware, composable fee schedules with named fixed, notional, and per-unit - components; explicit rounding; maker/taker applicability; per-fill minimums and caps; rebates; - and deterministic multi-currency conversion. -- Added signed fee-component attribution to fills, positions, valuations, journals, and external - strategy events in scenario/journal contract v9 and strategy protocol v7. -- Preserved completed-bar configuration v1, scenario/journal v8, and strategy protocol v6 as - compatibility contracts. - -- Add explicit GTC, IOC, FOK, DAY, and GTD order lifetimes plus completed-bar stop and stop-limit - activation in scenario contract v8 and external strategy protocol v6. - -- Add contract v7 exact per-instrument risk policies, versioned overlapping exposure groups, - reservation-aware admission and fill clipping, group diagnostics, and strategy protocol v5. - -- Add contract v6 explicit initial portfolio snapshots with signed cash and positions, accounting - history, initial marks and FX, strict risk validation, initial-state auditing, and strategy - protocol v4 initialization. -- Publish strict versioned configuration and machine-readable capabilities for each compiled - execution model. -- Add contract v5 venue calendars with explicit venue and calendar identities, regular and - extended trading phases, holidays, early closes, and reducer-independent clock resolution. -- Protect `main` with required integration checks and a no-bypass review policy, and make rebase - merging the only supported repository merge mode. -- Establish a security baseline with private reporting guidance, grouped dependency proposals, - dependency review, and CodeQL analysis for workflows and Python tooling. -- Add structured issue and pull-request intake, reviewed planning-label and repository metadata, - explicit compatibility guarantees, a pinned required Persistra baseline, and a manual - nonrequired latest-head signal. -- Verify exact canonical journal bytes across locked, dependency-bound, and operating-system CI - cells, with safe concurrency cancellation and documented required versus informational gates. -- Publish one strict documentation site for architecture, versioned contracts, and generated OCaml - APIs, with offline topology checks and bounded external-link validation. -- Define a reproducible release-candidate artifact set with install verification, checksums, SPDX - inventory, SLSA provenance, and a manual tag-only signing boundary. - -## 1.0.0 — 2026-08-21 - -- Release the deterministic completed-bar execution engine with exact checked arithmetic, - causal audit journals, and versioned JSON and JSON Lines contracts. -- Support portfolio targets, direct orders, partial fills, fees, multi-currency accounting, - corporate actions, borrow costs, margin controls, and deterministic liquidation. -- Add synchronous external strategies through protocol v3 with current-slice callback state and - strategy responses applied before matching continues. -- Provide strict schemas, conformance fixtures, replay validation, and Persistra compatibility - checks. +## [1.1.0] - 2026-08-26 + +- Reset the scenario, journal, strategy, execution-configuration, CLI, and diagnostic contracts to + one authoritative v1 surface. +- Remove historical schemas, compatibility dispatch, deprecated constructors, frozen fixtures, + and obsolete compatibility tests. +- Require explicit initial portfolios, current risk and fee policies, complete market slices, and + current strategy initialization. +- Simplify repository and contract documentation around the current engine boundary. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 151fd04..14bca8f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,4 +81,4 @@ position. Do not encode delivery commitments in labels. The reviewed label defin repository metadata live under `.github/` and must agree with the GitHub settings. For reciprocal Persistra compatibility guarantees and the pin-advancement procedure, read -[Persistra integration](docs/persistra.md#compatibility-guarantees). +[Persistra integration](docs/persistra.md#compatibility-gate). diff --git a/README.md b/README.md index e93feda..951f565 100644 --- a/README.md +++ b/README.md @@ -1,287 +1,76 @@ # Trading Engine -Trading Engine is a deterministic, event-driven OCaml execution engine. It runs a typed strategy -through pre-trade risk, order management, synchronized completed-bar execution, exact accounting, -valuation, and a hash-bound JSON Lines audit journal. +Trading Engine is a deterministic OCaml engine for replaying trading strategies. -The [documentation site](docs/documentation-platform.md) connects the architecture, execution and -scenario contracts, stable versioned artifacts, and generated OCaml API reference. +It accepts a strict scenario, runs strategy decisions through risk, order management, execution, +financing, settlement, and accounting, then writes a hash-bound JSON Lines audit journal. The same +reducer supports scheduled intents and supervised external strategy processes. -The engine is replay-first. Its pure kernel and explicit source, strategy, execution, and journal -layers keep networking, files, and wall-clock state outside the reducer. +## Highlights -```text -scenario slices and scheduled or external intents - │ - ▼ - deterministic reducer - │ - ┌──────────┼──────────┐ - ▼ ▼ ▼ - strategy risk + OMS slice simulator - │ │ │ - └──────────┴──── fills┘ - │ - ▼ - accounting + valuation - │ - ▼ - JSON Lines journal -``` - -## Implemented scope - -- OCaml 5.5 and Dune 3.24 with a repository-local opam switch -- Opaque IDs and canonical checked fixed-point prices, weights, money, and quantities -- Synchronized market slices with one bar per configured instrument -- Separate market event, availability, receipt, slice, and engine ordering -- Pure strategy callbacks with causal, immutable context snapshots -- Pure suspend/resume strategy requests with equivalent scripted and external reducers -- Explicit immutable reducer phases behind one internal transition contract -- Portfolio weight and quantity targets covering the complete instrument catalog -- Current-equity weight sizing at synchronized closing marks with lot rounding -- Persistent target reconciliation through bounded market-order attempts -- Direct market and limit orders, cancellations, and metrics -- Typed strategy metrics with exact numeric, string, and boolean values, bounded dimensions, - units, and aggregation metadata -- Signed long/short position, order, lot, tick, gross-exposure, leverage, and margin risk -- Deterministic liquidation-first matching, then sell-before-buy and FIFO priority -- Shared per-instrument volume participation, partial fills, and GTC limits -- One-slice IOC market orders -- Risk-aware fractional-lot clipping with structured `fill_clipped` reasons and thresholds -- Instrument-aware fixed, notional, and per-unit fee schedules with explicit rounding, - maker/taker applicability, minimums, caps, rebates, and deterministic FX conversion -- Explicit multi-currency cash ledgers and complete per-slice FX marks in a base currency -- Explicit signed initial portfolios with cost basis, P&L and fee history, marks, and FX state -- Splits, dividends, rights, spin-offs, fractional cash-in-lieu, and exact basis allocation -- Stable instrument identity with halt/resume, identifier changes, expiration, and delisting -- Effective-time short locates, availability clipping, borrow-rate accrual, recalls, and - deterministic close-out orders -- Per-currency credit/debit cash rates with explicit day-count and compounding policies -- Signed average-cost accounting, realized and unrealized P&L, and equity reconciliation -- Per-currency cash and per-instrument quantity, mark, value, basis, P&L, aggregate fee, and named - fee-component attribution -- Deterministic event IDs, ordered causal references, and order-creation attribution -- Contract-selected compiled execution modules with versioned model-owned configuration and - capability descriptors; v13 adds conservative bar models, v14 adds causal quote/trade replay, - and v15 adds bounded level-two order-book replay while freezing `completed_bar_v1` -- Tick-aligned fixed-spread and participation-impact execution costs with separate reference, - spread, impact, and final-price audit attribution -- Causally ordered quotes and aggressor-classified trades with displayed-liquidity limits, - maker/taker attribution, and event-time fills -- Bounded order-book snapshots and contiguous updates with price-time queue simulation, - multi-level depth consumption, partial fills, and locked-book support -- Strict batch JSON and bounded-memory JSON Lines scenario parsing with JSON Schemas -- Versioned synchronous JSON Lines strategy processes with per-request timeouts and strict - lifecycle supervision -- Complete bidirectional strategy transcripts with coordinated no-replace journal publication -- Scenario SHA-256 binding in `run_started` and `run_completed` -- Exclusive partial artifact creation with optional file and directory synchronization -- Unit, schema-conformance, scenario, golden-contract, reducer model-property, and protocol-fuzz tests +- Exact fixed-point prices, quantities, money, weights, and FX rates +- Completed-bar, conservative-bar, quote/trade, and order-book execution models +- Market, limit, stop, stop-limit, IOC, GTC, GTD, DAY, and FOK orders +- Instrument and portfolio risk, margin, short locates, recalls, and liquidation +- Multi-currency accounting, financing, settlement, fees, and corporate actions +- Deterministic event IDs, causal references, transcripts, and durable artifact publication +- Strict v1 JSON Schemas for scenarios, journals, strategy messages, diagnostics, and CLI results ## Quick start -The project uses a local switch and does not modify the default switch. The complete check also -uses Python's `jsonschema` package to validate every committed schema and canonical fixture. It -checks the frozen-artifact hashes and runs the current differential corpus against the OCaml -parsers. +The repository uses a local opam switch. ```sh -cd ~/trading-engine make bootstrap make check ``` -Run the advisory batch, stream, dense-OMS, and external-strategy performance matrix with -`make benchmark`. See [Performance](docs/performance.md) for workload definitions, reported -metrics, and the baseline tolerance policy. - -Validate the included scenario with an in-memory replay: +Validate the canonical scenario: ```sh opam exec -- dune exec trading-engine -- \ - --input contracts/v16/fixtures/demo.scenario.json \ + --input contracts/v1/fixtures/demo.scenario.json \ --validate-only ``` -Run it and create a journal: +Replay it to a journal: ```sh opam exec -- dune exec trading-engine -- \ - --input contracts/v16/fixtures/demo.scenario.json \ + --input contracts/v1/fixtures/demo.scenario.json \ --journal demo.journal.jsonl ``` -For larger histories, validate and replay the equivalent stream one slice at a time: +Use `--input-format jsonl` for bounded-memory stream input. Use `--capabilities` for the +machine-readable runtime surface and `--output-format json` for structured success and failure +output. -```sh -opam exec -- dune exec trading-engine -- \ - --input contracts/v16/fixtures/demo.scenario.jsonl \ - --input-format jsonl \ - --journal demo.journal.jsonl -``` +## External strategies -Compose a JSON Lines producer and journal consumer without mixing streams: - -```sh -produce-scenario | trading-engine --input - --input-format jsonl --journal - | consume-journal -``` - -Standard input is spooled to a private temporary file, limited to 1 GiB, then hashed and validated -before replay. Standard output contains only journal records. The engine stages and verifies the -complete journal before copying it to the pipe; its final `run_completed` record and a zero exit -status signal completion. Pipe output cannot provide exclusive no-replace publication, atomic -linking, retained partial files, directory synchronization, or restart-durability guarantees. -`--durable-artifacts` is therefore invalid with `--journal -`. - -Run an external strategy against an empty-schedule scenario: +External strategies exchange one synchronous JSON Lines message at a time: ```sh opam exec -- dune exec trading-engine -- \ - --input contracts/strategy/v14/fixtures/external.scenario.json \ + --input contracts/strategy/v1/fixtures/external.scenario.json \ --journal external.journal.jsonl \ --strategy-executable ./my-strategy \ - --strategy-arg=config.toml \ - --strategy-timeout 30 \ --strategy-transcript external.strategy.jsonl ``` -The engine launches the program directly without a shell. This supervises the child but does not -sandbox it; run strategy code with the same trust you give the invoking user. Protocol messages -own the child's standard input and output; strategy diagnostics belong on standard error. Only -one request is outstanding. Initialization must return `ready`, each event must return `intents`, -and shutdown must return `stopped`. Wrong versions or sequences, unknown or malformed fields, -oversized responses, EOF, timeout, extra output, and nonzero exit all fail the replay. The journal -and transcript remain partial until both are complete. The engine then closes both, publishes the -complete set without replacement, and removes the partial names. A close or publication failure -rolls back final names created by the transaction. A cleanup failure leaves the complete final set -and restores every partial name for diagnosis. The strategy runs in a dedicated process group. -Failure and cancellation send `SIGTERM` to the complete group, allow one second for graceful exit, -then send `SIGKILL` and allow five seconds to reap the process tree. - -Discover the executable version and machine-readable compatibility surface: - -```sh -opam exec -- dune exec trading-engine -- --version -opam exec -- dune exec trading-engine -- --capabilities -``` +The child process is supervised but not sandboxed. Protocol output belongs on standard output; +strategy logs belong on standard error. -Clients must confirm that both `scenario_contract_versions` and `journal_contract_versions` -contain the scenario's `contract_version` before starting a replay. External clients must also -require their version in `strategy_protocol_versions`. The versioned `resource_limits` object -publishes inclusive limits for scenario records, strategy messages, reducer feedback, catalogs, -intent batches, and artifact records. Runtime failures can use the structured -diagnostic contract identified by each diagnostic's `diagnostic_version`. Human diagnostics remain -the default. Use `--diagnostic-format json` to receive one JSON diagnostic on standard error with a -stable code, phase, typed context, and sanitized underlying cause. +## Documentation -Use `--output-format json` for the versioned -[CLI result contract](contracts/cli/v1/README.md). A success document includes the run identity, -scenario and artifact hashes, replay counts, normalized current valuation, and artifact locations. -This option also selects JSON failure diagnostics. For file journals the success document is written -to standard output. With `--journal -`, the journal owns standard output and the success document -moves to standard error. - -The final and `.partial` journal paths must not already exist. Batch JSON hashes the same complete -document it parses. JSON Lines input is hashed and validated in a bounded-memory pass before the -journal is created, then replayed from the same open file and hashed again before publication. The -CLI binds that exact-byte hash into the journal. It writes to the partial path and publishes the -requested path only after `run_completed` is fully written and the partial file is closed. An -error preserves the partial artifact for diagnosis. - -A protocol-invalid strategy response is not stored as an accepted transcript exchange. The partial -transcript instead ends with a versioned rejection record containing its structured diagnostic and -a hexadecimal prefix of at most 256 raw response bytes. This covers malformed fields and JSON, -wrong versions or sequences, EOF, and oversized output without retaining the complete rejected -payload. - -Journal and transcript records are limited to 2 MiB each, including the terminating line feed. -Limit failures use the stable `resource.limit` diagnostic code. - -Pass `--durable-artifacts` to synchronize each staged file before publication and synchronize each -containing directory after final links and partial cleanup. The default buffered mode flushes every -record but does not make a restart-durability claim. - -## Execution summary - -An order emitted after slice `n` cannot execute on slice `n`. It first becomes eligible on a later -slice whose start is not earlier than its creation time. - -- Market orders attempt the next eligible open and cancel any remainder after that slice. -- Persistent portfolio targets submit a new bounded attempt after each miss until reached or - superseded. -- Limit orders use deterministic gap improvement and optimistic intrabar touch rules. -- Eligible liquidation orders consume capacity before other orders. Within each origin class, - sells precede buys and FIFO creation order breaks ties within a side. -- Corporate actions are applied before matching. Splits adjust positions, persistent targets, and - active orders; distributions allocate basis and fractional cash exactly; cash dividends credit - longs and debit shorts in the quote-currency ledger. -- Lifecycle events update symbols and provider mappings without changing instrument identity. - Halts and terminal events cancel orders; expiration and delisting follow an explicit hold or - cash-out policy. -- Effective-time borrow observations control short availability and rates. New shorts are rejected - or clipped to their locate, recalls reject new shorts or create deterministic close-out orders, - and observed borrow charges accrue before matching. -- Effective-time currency observations credit positive cash and debit negative cash for the slice - interval under the configured day-count, compounding, and missing-data policies. -- Proposed fills are clipped to the largest permitted fractional-lot quantity at the actual fill - price and never exceed the maximum order quantity. Increasing exposure must satisfy position, - gross-exposure, leverage, and initial-margin limits; exposure-reducing fills remain available. -- A maintenance-margin breach cancels active orders, clears portfolio targets, and creates - deterministic market orders that flatten positions in bounded lots across later slices. -- The engine emits exactly one valuation after each complete synchronized slice. - -Read [Execution model](docs/execution-model.md) for the full phase, price, fee, cash, and accounting -rules. - -## Project boundaries - -The current scope omits: - -- Broker and streaming-market-data connectors -- External execution-report ingestion -- Exchange calendars and time-zone databases -- Durable reducer snapshots and broker reconciliation -- Tick, trade, and order-book replay - -Artifact publication requires a filesystem that supports exclusive file creation, hard links, and -atomic unlink. Durable mode additionally requires file and directory synchronization. An -unsupported synchronization operation returns `artifact.io`, never reports success, and preserves -or restores partial names for diagnosis. Durable artifacts strengthen publication persistence; they -do not provide reducer snapshots or restart recovery. - -## Architecture and contracts - -- [Support and issue guidance](.github/SUPPORT.md) -- [Security policy](.github/SECURITY.md) -- [Security maintenance](docs/security-maintenance.md) -- [Contributing](CONTRIBUTING.md) - [Architecture](docs/architecture.md) -- [Diagnostic contract](docs/diagnostics.md) -- [CLI result contract](contracts/cli/v1/README.md) -- [Scenario contract](docs/scenario.md) -- [Contract conformance corpus](contracts/conformance/README.md) -- [Current contract v16 and conformance fixtures](contracts/v16/README.md) -- [Frozen contract v2](contracts/v2/README.md) -- [Historical contract v1](contracts/v1/README.md) -- [Scenario JSON Schema](contracts/v16/scenario.schema.json) -- [Scenario stream record JSON Schema](contracts/v16/scenario-stream.schema.json) -- [Journal record JSON Schema](contracts/v16/journal.schema.json) -- [CLI result JSON Schema](contracts/cli/v1/result.schema.json) -- [External strategy protocol v14](contracts/strategy/v14/README.md) -- [Historical strategy protocol v3](contracts/strategy/v3/README.md) -- [Historical strategy protocol v2](contracts/strategy/v2/README.md) -- [Historical strategy protocol v1](contracts/strategy/v1/README.md) -- [Persistra compatibility](docs/persistra.md) -- [Strategy message JSON Schema](contracts/strategy/v14/message.schema.json) -- [Strategy transcript JSON Schema](contracts/strategy/v14/transcript.schema.json) - [Execution model](docs/execution-model.md) -- [OCaml coverage](docs/coverage.md) -- [Continuous integration and portability matrix](docs/continuous-integration.md) -- [Documentation platform and generated API](docs/documentation-platform.md) -- [Release artifacts and provenance](docs/release-artifacts.md) -- [Performance](docs/performance.md) -- [Reducer property testing](docs/reducer-property-testing.md) -- [Protocol fuzzing](docs/fuzzing.md) +- [Scenario and journal](docs/scenario.md) +- [Replay contract v1](contracts/v1/README.md) +- [Strategy protocol v1](contracts/strategy/v1/README.md) +- [Diagnostics](docs/diagnostics.md) - [Persistra integration](docs/persistra.md) - [Contributing](CONTRIBUTING.md) +- [Security](.github/SECURITY.md) + +The complete documentation site is published at +[fallblu.github.io/trading-engine](https://fallblu.github.io/trading-engine/). diff --git a/bench/benchmark_batch_schedule.py b/bench/benchmark_batch_schedule.py index 0d30361..14d62b6 100644 --- a/bench/benchmark_batch_schedule.py +++ b/bench/benchmark_batch_schedule.py @@ -16,7 +16,7 @@ ROOT = Path(__file__).resolve().parents[1] DEFAULT_EXECUTABLE = ROOT / "_build/default/bin/main.exe" -FIXTURE = ROOT / "contracts/v5/fixtures/demo.scenario.json" +FIXTURE = ROOT / "contracts/v1/fixtures/demo.scenario.json" def timestamp(value: datetime) -> str: @@ -51,7 +51,10 @@ def dense_scenario(size: int) -> dict[str, object]: { "type": "emit_metric", "name": "dense_schedule", - "value": str(sequence), + "value": {"type": "numeric", "value": str(sequence)}, + "unit": None, + "dimensions": {}, + "aggregation": "last", } ], } diff --git a/bench/benchmark_replay.py b/bench/benchmark_replay.py index 899f4b3..8b73970 100644 --- a/bench/benchmark_replay.py +++ b/bench/benchmark_replay.py @@ -23,7 +23,7 @@ ROOT = Path(__file__).resolve().parents[1] DEFAULT_EXECUTABLE = ROOT / "_build/default/bin/main.exe" DEFAULT_BASELINE = ROOT / "bench/baselines/linux-x86_64.json" -FIXTURE = ROOT / "contracts/v10/fixtures/demo.scenario.json" +FIXTURE = ROOT / "contracts/v1/fixtures/demo.scenario.json" STRATEGY = ROOT / "bench/latency_strategy.py" SUMMARY_PATTERN = re.compile( r"\baudits=(?P[0-9]+).*\bactive=(?P[0-9]+)" @@ -219,7 +219,6 @@ def build_scenario(case: BenchmarkCase) -> dict[str, object]: "risk": { "max_gross_exposure": "1000000000", "max_leverage": "1000000", - "short_borrow_bps": 0, "instrument_policies": [ { "instrument_id": instrument["instrument_id"], @@ -240,8 +239,26 @@ def build_scenario(case: BenchmarkCase) -> dict[str, object]: "configuration": { "version": "1", "participation_bps": 10000, - "fixed_fee": "0", - "fee_bps": 0, + "fee_schedules": [ + { + "schedule_id": f"{instrument['instrument_id']}-fees-v1", + "instrument_id": instrument["instrument_id"], + "settlement_currency": "USD", + "minimum": None, + "maximum": None, + "components": [ + { + "name": "benchmark", + "currency": "USD", + "kind": "fixed", + "value": "0", + "rounding": "nearest", + "applies_to": "any", + } + ], + } + for instrument in instruments + ], }, }, "max_internal_events": max(1000, case.active_order_count * 4 + 16), @@ -268,6 +285,7 @@ def stream_records(document: dict[str, object]) -> list[dict[str, object]]: "risk", "execution", "financing", + "settlement", "max_internal_events", ) records = [ diff --git a/bin/main.ml b/bin/main.ml index 14e0fbb..53f83b7 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -80,8 +80,7 @@ let success_to_yojson success = ("rejected_orders", int64 counts.rejected_orders); ] ); ( "valuation", - Trading_engine.Codec.account_valuation_to_yojson ~contract_version:"16" - success.valuation ); + Trading_engine.Codec.account_valuation_to_yojson success.valuation ); ( "artifacts", `Assoc [ diff --git a/contracts/cli/v1/README.md b/contracts/cli/v1/README.md index 82a47e4..110df86 100644 --- a/contracts/cli/v1/README.md +++ b/contracts/cli/v1/README.md @@ -15,6 +15,4 @@ success document moves to standard error. Its journal artifact is named `stdout` `run_completed` record signals successful completion. A consumer must also require a zero process exit status. Strategy protocol messages remain confined to the supervised child process. -This result contract is independent of the scenario contract version. Its `valuation` uses the -current v16 valuation shape so consumers receive one stable automation model for older accepted -scenarios. +The result contract reports the normalized replay contract v1 valuation. diff --git a/contracts/cli/v1/result.schema.json b/contracts/cli/v1/result.schema.json index 2aea165..504489c 100644 --- a/contracts/cli/v1/result.schema.json +++ b/contracts/cli/v1/result.schema.json @@ -18,7 +18,7 @@ "result_version": { "const": "1" }, "status": { "const": "success" }, "operation": { "enum": ["validate", "replay"] }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/identifier" }, + "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/identifier" }, "hashes": { "type": "object", "additionalProperties": false, @@ -104,26 +104,26 @@ "execution_fee_components" ], "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "settled_cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "unsettled_cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/unsignedDecimal" }, - "cost_basis": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "unrealized_pnl": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "borrow_fees": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "cash_interest": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "total_fees": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/signedDecimal" }, - "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/cashAttribution" } }, - "positions": { "type": "array", "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/positionAttribution" } }, - "execution_fee_components": { "type": "array", "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/feeComponentAttribution" } } + "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/identifier" }, + "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "settled_cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "unsettled_cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/unsignedDecimal" }, + "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/unsignedDecimal" }, + "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/unsignedDecimal" }, + "cost_basis": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "realized_pnl": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "unrealized_pnl": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "dividend_pnl": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "execution_fees": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "borrow_fees": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "cash_interest": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "total_fees": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/signedDecimal" }, + "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/cashAttribution" } }, + "positions": { "type": "array", "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/positionAttribution" } }, + "execution_fee_components": { "type": "array", "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/feeComponentAttribution" } } } } } diff --git a/contracts/conformance/README.md b/contracts/conformance/README.md index fce76c8..c6efdcf 100644 --- a/contracts/conformance/README.md +++ b/contracts/conformance/README.md @@ -2,34 +2,11 @@ This directory is the machine-readable entry point for contract consumers. -- `manifest.json` maps every versioned schema branch to its canonical fixtures. -- `cases.json` records deterministic schema/runtime differential cases for the - versions accepted by the current OCaml runtime. -- `frozen.sha256` protects the schema and fixture bytes for archived scenario - contract v1 and v2 and strategy protocol v1 and v2. +- `manifest.json` maps each current v1 schema to canonical fixtures. +- `cases.json` defines structural and semantic differential cases. -The artifact manifest treats each schema at each version as a separate branch. -Every branch has positive canonical inputs and generated negative cases for a -missing version, an unsupported version, and an unknown field. Frozen branches -are schema-only: they are never passed to current runtime parsers. +Structural cases must agree between JSON Schema and the OCaml runtime. Semantic cases document +rules that JSON Schema cannot express, such as ordering, uniqueness, and cross-record invariants. -Every top-level `oneOf` alternative also has a positive witness and a derived -unknown-field rejection. `schema_only_cases` supplies variants that do not occur -in a successful canonical run, such as strategy `error` messages and rejected -response transcript records. - -Differential cases label rules as `structural` or `semantic`. Structural cases -must produce the same result from JSON Schema and the OCaml parser. Semantic -cases explicitly document invariants that JSON Schema cannot express, so an -accepted schema result and a rejected runtime result is intentional. - -Run the complete corpus through the repository gate: - -```sh -make check -``` - -When intentionally changing an archived contract, update `frozen.sha256` in the -same review. Adding a contract version requires a manifest branch, canonical -fixtures, positive and negative validation, and current-runtime differential -cases when the new version is advertised by the engine. +Run `make check` to validate the complete corpus. A contract change must update its schema, +fixtures, manifest entries, differential cases, and runtime checks together. diff --git a/contracts/conformance/cases.json b/contracts/conformance/cases.json index ded2c74..ae344ed 100644 --- a/contracts/conformance/cases.json +++ b/contracts/conformance/cases.json @@ -2,50 +2,10 @@ "format_version": "1", "cases": [ { - "name": "scenario-v7-valid", - "artifact": "scenario-v7", + "name": "scenario-v1-valid", + "artifact": "scenario-v1", "kind": "scenario", - "source": "v7/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v7-valid", - "artifact": "scenario-stream-v7", - "kind": "scenario_stream", - "source": "v7/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v6-valid", - "artifact": "scenario-v6", - "kind": "scenario", - "source": "v6/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v5-valid", - "artifact": "scenario-v5", - "kind": "scenario", - "source": "v5/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v3-valid", - "artifact": "scenario-v3", - "kind": "scenario", - "source": "v3/fixtures/demo.scenario.json", + "source": "v1/fixtures/demo.scenario.json", "mutations": [], "schema_expectation": "accept", "runtime_expectation": "accept", @@ -53,16 +13,11 @@ }, { "name": "scenario-missing-version", - "artifact": "scenario-v5", + "artifact": "scenario-v1", "kind": "scenario", - "source": "v5/fixtures/demo.scenario.json", + "source": "v1/fixtures/demo.scenario.json", "mutations": [ - { - "op": "remove", - "path": [ - "contract_version" - ] - } + { "op": "remove", "path": ["contract_version"] } ], "schema_expectation": "reject", "runtime_expectation": "reject", @@ -70,37 +25,11 @@ }, { "name": "scenario-unknown-field", - "artifact": "scenario-v5", - "kind": "scenario", - "source": "v5/fixtures/demo.scenario.json", - "mutations": [ - { - "op": "add", - "path": [ - "unexpected_contract_field" - ], - "value": true - } - ], - "schema_expectation": "reject", - "runtime_expectation": "reject", - "rule": "structural" - }, - { - "name": "scenario-invalid-scalar-type", - "artifact": "scenario-v5", + "artifact": "scenario-v1", "kind": "scenario", - "source": "v5/fixtures/demo.scenario.json", + "source": "v1/fixtures/demo.scenario.json", "mutations": [ - { - "op": "replace", - "path": [ - "initial_cash", - 0, - "amount" - ], - "value": 10000 - } + { "op": "add", "path": ["unexpected_contract_field"], "value": true } ], "schema_expectation": "reject", "runtime_expectation": "reject", @@ -108,18 +37,14 @@ }, { "name": "scenario-unsupported-execution-configuration", - "artifact": "scenario-v5", + "artifact": "scenario-v1", "kind": "scenario", - "source": "v5/fixtures/demo.scenario.json", + "source": "v1/fixtures/demo.scenario.json", "mutations": [ { "op": "replace", - "path": [ - "execution", - "configuration", - "version" - ], - "value": "2" + "path": ["execution", "configuration", "version"], + "value": "unsupported" } ], "schema_expectation": "reject", @@ -128,17 +53,11 @@ }, { "name": "scenario-duplicate-instrument", - "artifact": "scenario-v5", + "artifact": "scenario-v1", "kind": "scenario", - "source": "v5/fixtures/demo.scenario.json", + "source": "v1/fixtures/demo.scenario.json", "mutations": [ - { - "op": "append_copy", - "path": [ - "instruments" - ], - "index": 0 - } + { "op": "append_copy", "path": ["instruments"], "index": 0 } ], "schema_expectation": "accept", "runtime_expectation": "reject", @@ -146,17 +65,13 @@ }, { "name": "scenario-overlapping-slices", - "artifact": "scenario-v5", + "artifact": "scenario-v1", "kind": "scenario", - "source": "v5/fixtures/demo.scenario.json", + "source": "v1/fixtures/demo.scenario.json", "mutations": [ { "op": "replace", - "path": [ - "slices", - 1, - "start_at" - ], + "path": ["slices", 1, "start_at"], "value": "2026-01-02T20:00:00Z" } ], @@ -165,30 +80,10 @@ "rule": "semantic" }, { - "name": "scenario-stream-v5-valid", - "artifact": "scenario-stream-v5", - "kind": "scenario_stream", - "source": "v5/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v6-valid", - "artifact": "scenario-stream-v6", - "kind": "scenario_stream", - "source": "v6/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v3-valid", - "artifact": "scenario-stream-v3", + "name": "scenario-stream-v1-valid", + "artifact": "scenario-stream-v1", "kind": "scenario_stream", - "source": "v3/fixtures/demo.scenario.jsonl", + "source": "v1/fixtures/demo.scenario.jsonl", "mutations": [], "schema_expectation": "accept", "runtime_expectation": "accept", @@ -196,36 +91,12 @@ }, { "name": "scenario-stream-missing-version", - "artifact": "scenario-stream-v5", + "artifact": "scenario-stream-v1", "kind": "scenario_stream", - "source": "v5/fixtures/demo.scenario.jsonl", + "source": "v1/fixtures/demo.scenario.jsonl", "record": 1, "mutations": [ - { - "op": "remove", - "path": [ - "contract_version" - ] - } - ], - "schema_expectation": "reject", - "runtime_expectation": "reject", - "rule": "structural" - }, - { - "name": "scenario-stream-unknown-field", - "artifact": "scenario-stream-v5", - "kind": "scenario_stream", - "source": "v5/fixtures/demo.scenario.jsonl", - "record": 2, - "mutations": [ - { - "op": "add", - "path": [ - "unexpected_contract_field" - ], - "value": true - } + { "op": "remove", "path": ["contract_version"] } ], "schema_expectation": "reject", "runtime_expectation": "reject", @@ -233,18 +104,12 @@ }, { "name": "scenario-stream-out-of-order-sequence", - "artifact": "scenario-stream-v5", + "artifact": "scenario-stream-v1", "kind": "scenario_stream", - "source": "v5/fixtures/demo.scenario.jsonl", + "source": "v1/fixtures/demo.scenario.jsonl", "record": 2, "mutations": [ - { - "op": "replace", - "path": [ - "scenario_sequence" - ], - "value": "3" - } + { "op": "replace", "path": ["scenario_sequence"], "value": "99" } ], "schema_expectation": "accept", "runtime_expectation": "reject", @@ -252,1498 +117,116 @@ }, { "name": "strategy-ready-valid", - "artifact": "strategy-message-v6", + "artifact": "strategy-message-v1", "kind": "strategy_response", - "source": "strategy/v6/fixtures/external.strategy.jsonl", + "source": "strategy/v1/fixtures/external.strategy.jsonl", "record": 2, - "extract": [ - "message" - ], + "extract": ["message"], "expected_sequence": "1", "mutations": [], "schema_expectation": "accept", "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "6" + "rule": "structural" }, { "name": "strategy-intents-valid", - "artifact": "strategy-message-v6", + "artifact": "strategy-message-v1", "kind": "strategy_response", - "source": "strategy/v6/fixtures/external.strategy.jsonl", + "source": "strategy/v1/fixtures/external.strategy.jsonl", "record": 4, - "extract": [ - "message" - ], + "extract": ["message"], "expected_sequence": "2", "mutations": [], "schema_expectation": "accept", "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "6" + "rule": "structural" }, { "name": "strategy-stopped-valid", - "artifact": "strategy-message-v6", + "artifact": "strategy-message-v1", "kind": "strategy_response", - "source": "strategy/v6/fixtures/external.strategy.jsonl", + "source": "strategy/v1/fixtures/external.strategy.jsonl", "record": 14, - "extract": [ - "message" - ], + "extract": ["message"], "expected_sequence": "7", "mutations": [], "schema_expectation": "accept", "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "6" - }, - { - "name": "strategy-error-valid", - "artifact": "strategy-message-v6", - "kind": "strategy_response", - "source": "strategy/v6/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "intentional conformance error" - } - } - ], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "6" + "rule": "structural" }, { "name": "strategy-missing-version", - "artifact": "strategy-message-v6", + "artifact": "strategy-message-v1", "kind": "strategy_response", - "source": "strategy/v6/fixtures/external.strategy.jsonl", + "source": "strategy/v1/fixtures/external.strategy.jsonl", "record": 2, - "extract": [ - "message" - ], + "extract": ["message"], "expected_sequence": "1", "mutations": [ - { - "op": "remove", - "path": [ - "strategy_protocol_version" - ] - } + { "op": "remove", "path": ["strategy_protocol_version"] } ], "schema_expectation": "reject", "runtime_expectation": "reject", - "rule": "structural", - "protocol_version": "6" + "rule": "structural" }, { - "name": "strategy-unknown-field", - "artifact": "strategy-message-v6", + "name": "strategy-wrong-sequence", + "artifact": "strategy-message-v1", "kind": "strategy_response", - "source": "strategy/v6/fixtures/external.strategy.jsonl", + "source": "strategy/v1/fixtures/external.strategy.jsonl", "record": 2, - "extract": [ - "message" - ], + "extract": ["message"], "expected_sequence": "1", "mutations": [ - { - "op": "add", - "path": [ - "unexpected_contract_field" - ], - "value": true - } - ], - "schema_expectation": "reject", - "runtime_expectation": "reject", - "rule": "structural", - "protocol_version": "6" - }, - { - "name": "strategy-wrong-sequence", - "artifact": "strategy-message-v6", - "kind": "strategy_response", - "source": "strategy/v6/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" + { "op": "replace", "path": ["strategy_sequence"], "value": "99" } ], - "expected_sequence": "2", - "mutations": [], "schema_expectation": "accept", "runtime_expectation": "reject", - "rule": "semantic", - "protocol_version": "6" - }, - { - "name": "strategy-ready-valid-v5", - "artifact": "strategy-message-v5", - "kind": "strategy_response", - "source": "strategy/v5/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "5" - }, - { - "name": "strategy-intents-valid-v5", - "artifact": "strategy-message-v5", - "kind": "strategy_response", - "source": "strategy/v5/fixtures/external.strategy.jsonl", - "record": 4, - "extract": [ - "message" - ], - "expected_sequence": "2", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "5" - }, + "rule": "semantic" + } + ], + "schema_only_cases": [ { - "name": "strategy-stopped-valid-v5", - "artifact": "strategy-message-v5", - "kind": "strategy_response", - "source": "strategy/v5/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", + "name": "strategy-error-valid", + "artifact": "strategy-message-v1", + "instance": { + "strategy_protocol_version": "1", + "strategy_sequence": "1", + "message_type": "error", + "payload": { "message": "fixture failure" } + }, "mutations": [], "schema_expectation": "accept", "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "5" + "rule": "structural" }, { - "name": "strategy-error-valid-v5", - "artifact": "strategy-message-v5", - "kind": "strategy_response", - "source": "strategy/v5/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" + "name": "strategy-rejected-response-valid", + "artifact": "strategy-transcript-v1", + "instance": { + "strategy_diagnostic_version": "1", + "transcript_sequence": "2", + "record_type": "rejected_strategy_response", + "expected_strategy_sequence": "1", + "diagnostic": { + "diagnostic_version": "1", + "code": "strategy.protocol", + "phase": "strategy", + "message": "invalid strategy response", + "context": { "json_path": "$", "sequence": "1" }, + "cause": null }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "intentional conformance error" - } + "evidence": { + "encoding": "hex", + "prefix": "7b", + "observed_bytes": 1, + "truncated": false } - ], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "5" - }, - { - "name": "strategy-ready-valid-v4", - "artifact": "strategy-message-v4", - "kind": "strategy_response", - "source": "strategy/v4/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "4" - }, - { - "name": "strategy-intents-valid-v4", - "artifact": "strategy-message-v4", - "kind": "strategy_response", - "source": "strategy/v4/fixtures/external.strategy.jsonl", - "record": 4, - "extract": [ - "message" - ], - "expected_sequence": "2", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "4" - }, - { - "name": "strategy-stopped-valid-v4", - "artifact": "strategy-message-v4", - "kind": "strategy_response", - "source": "strategy/v4/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "4" - }, - { - "name": "strategy-error-valid-v4", - "artifact": "strategy-message-v4", - "kind": "strategy_response", - "source": "strategy/v4/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "intentional conformance error" - } - } - ], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural", - "protocol_version": "4" - }, - { - "name": "strategy-missing-version-v4", - "artifact": "strategy-message-v4", - "kind": "strategy_response", - "source": "strategy/v4/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "mutations": [ - { - "op": "remove", - "path": [ - "strategy_protocol_version" - ] - } - ], - "schema_expectation": "reject", - "runtime_expectation": "reject", - "rule": "structural", - "protocol_version": "4" - }, - { - "name": "strategy-unknown-field-v4", - "artifact": "strategy-message-v4", - "kind": "strategy_response", - "source": "strategy/v4/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "mutations": [ - { - "op": "add", - "path": [ - "unexpected_contract_field" - ], - "value": true - } - ], - "schema_expectation": "reject", - "runtime_expectation": "reject", - "rule": "structural", - "protocol_version": "4" - }, - { - "name": "strategy-wrong-sequence-v4", - "artifact": "strategy-message-v4", - "kind": "strategy_response", - "source": "strategy/v4/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "2", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "reject", - "rule": "semantic", - "protocol_version": "4" - }, - { - "name": "scenario-v9-valid", - "artifact": "scenario-v9", - "kind": "scenario", - "source": "v9/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v9-valid", - "artifact": "scenario-stream-v9", - "kind": "scenario_stream", - "source": "v9/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-ready-valid-v7", - "artifact": "strategy-message-v7", - "kind": "strategy_response", - "source": "strategy/v7/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "protocol_version": "7", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-intents-valid-v7", - "artifact": "strategy-message-v7", - "kind": "strategy_response", - "source": "strategy/v7/fixtures/external.strategy.jsonl", - "record": 4, - "extract": [ - "message" - ], - "expected_sequence": "2", - "protocol_version": "7", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-stopped-valid-v7", - "artifact": "strategy-message-v7", - "kind": "strategy_response", - "source": "strategy/v7/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "protocol_version": "7", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-error-valid-v7", - "artifact": "strategy-message-v7", - "kind": "strategy_response", - "source": "strategy/v7/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "protocol_version": "7", - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "fixture failure" - } - } - ], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v10-valid", - "artifact": "scenario-v10", - "kind": "scenario", - "source": "v10/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v10-valid", - "artifact": "scenario-stream-v10", - "kind": "scenario_stream", - "source": "v10/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-ready-valid-v8", - "artifact": "strategy-message-v8", - "kind": "strategy_response", - "source": "strategy/v8/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "protocol_version": "8", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-intents-valid-v8", - "artifact": "strategy-message-v8", - "kind": "strategy_response", - "source": "strategy/v8/fixtures/external.strategy.jsonl", - "record": 4, - "extract": [ - "message" - ], - "expected_sequence": "2", - "protocol_version": "8", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-stopped-valid-v8", - "artifact": "strategy-message-v8", - "kind": "strategy_response", - "source": "strategy/v8/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "protocol_version": "8", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-error-valid-v8", - "artifact": "strategy-message-v8", - "kind": "strategy_response", - "source": "strategy/v8/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "protocol_version": "8", - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "fixture failure" - } - } - ], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v11-valid", - "artifact": "scenario-v11", - "kind": "scenario", - "source": "v11/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v11-valid", - "artifact": "scenario-stream-v11", - "kind": "scenario_stream", - "source": "v11/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-ready-valid-v9", - "artifact": "strategy-message-v9", - "kind": "strategy_response", - "source": "strategy/v9/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "protocol_version": "9", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-intents-valid-v9", - "artifact": "strategy-message-v9", - "kind": "strategy_response", - "source": "strategy/v9/fixtures/external.strategy.jsonl", - "record": 4, - "extract": [ - "message" - ], - "expected_sequence": "2", - "protocol_version": "9", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-stopped-valid-v9", - "artifact": "strategy-message-v9", - "kind": "strategy_response", - "source": "strategy/v9/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "protocol_version": "9", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-error-valid-v9", - "artifact": "strategy-message-v9", - "kind": "strategy_response", - "source": "strategy/v9/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "expected_sequence": "7", - "protocol_version": "9", - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "fixture failure" - } - } - ], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v15-valid", - "artifact": "scenario-v15", - "kind": "scenario", - "source": "v15/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v15-order-book-valid", - "artifact": "scenario-v15", - "kind": "scenario", - "source": "v15/fixtures/order-book.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v15-valid", - "artifact": "scenario-stream-v15", - "kind": "scenario_stream", - "source": "v15/fixtures/order-book.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-ready-valid-v13", - "artifact": "strategy-message-v13", - "kind": "strategy_response", - "source": "strategy/v13/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "protocol_version": "13", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-intents-valid-v13", - "artifact": "strategy-message-v13", - "kind": "strategy_response", - "source": "strategy/v13/fixtures/external.strategy.jsonl", - "record": 4, - "extract": [ - "message" - ], - "expected_sequence": "2", - "protocol_version": "13", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v16-valid", - "artifact": "scenario-v16", - "kind": "scenario", - "source": "v16/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-v16-order-book-valid", - "artifact": "scenario-v16", - "kind": "scenario", - "source": "v16/fixtures/order-book.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "scenario-stream-v16-valid", - "artifact": "scenario-stream-v16", - "kind": "scenario_stream", - "source": "v16/fixtures/order-book.scenario.jsonl", + }, "mutations": [], "schema_expectation": "accept", "runtime_expectation": "accept", "rule": "structural" - }, - { - "name": "strategy-ready-valid-v14", - "artifact": "strategy-message-v14", - "kind": "strategy_response", - "source": "strategy/v14/fixtures/external.strategy.jsonl", - "record": 2, - "extract": [ - "message" - ], - "expected_sequence": "1", - "protocol_version": "14", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - }, - { - "name": "strategy-intents-valid-v14", - "artifact": "strategy-message-v14", - "kind": "strategy_response", - "source": "strategy/v14/fixtures/external.strategy.jsonl", - "record": 4, - "extract": [ - "message" - ], - "expected_sequence": "2", - "protocol_version": "14", - "mutations": [], - "schema_expectation": "accept", - "runtime_expectation": "accept", - "rule": "structural" - } - ], - "schema_only_cases": [ - { - "name": "strategy-v1-error-branch", - "artifact": "strategy-message-v1", - "source": "strategy/v1/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "intentional conformance error" - } - } - ], - "schema_expectation": "accept" - }, - { - "name": "strategy-v2-error-branch", - "artifact": "strategy-message-v2", - "source": "strategy/v2/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "intentional conformance error" - } - } - ], - "schema_expectation": "accept" - }, - { - "name": "strategy-v3-error-branch", - "artifact": "strategy-message-v3", - "source": "strategy/v3/fixtures/external.strategy.jsonl", - "record": 14, - "extract": [ - "message" - ], - "mutations": [ - { - "op": "replace", - "path": [ - "message_type" - ], - "value": "error" - }, - { - "op": "replace", - "path": [ - "payload" - ], - "value": { - "message": "intentional conformance error" - } - } - ], - "schema_expectation": "accept" - }, - { - "name": "strategy-v3-rejected-response-branch", - "artifact": "strategy-transcript-v3", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-v4-rejected-response-branch", - "artifact": "strategy-transcript-v4", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-v5-rejected-response-branch", - "artifact": "strategy-transcript-v5", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept", - "source": "strategy/v5/fixtures/external.strategy.jsonl" - }, - { - "name": "strategy-v6-rejected-response-branch", - "artifact": "strategy-transcript-v6", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept", - "source": "strategy/v6/fixtures/external.strategy.jsonl" - }, - { - "name": "strategy-v7-rejected-response-branch", - "artifact": "strategy-transcript-v7", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept", - "source": "strategy/v7/fixtures/external.strategy.jsonl" - }, - { - "name": "strategy-v8-rejected-response-branch", - "artifact": "strategy-transcript-v8", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept", - "source": "strategy/v8/fixtures/external.strategy.jsonl" - }, - { - "name": "strategy-v9-rejected-response-branch", - "artifact": "strategy-transcript-v9", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept", - "source": "strategy/v9/fixtures/external.strategy.jsonl" - }, - { - "name": "scenario-v12-valid", - "artifact": "scenario-v12", - "kind": "scenario", - "source": "v12/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept" - }, - { - "name": "scenario-stream-v12-valid", - "artifact": "scenario-stream-v12", - "kind": "scenario_stream", - "source": "v12/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept" - }, - { - "name": "strategy-ready-valid-v10", - "artifact": "strategy-message-v10", - "instance": { - "strategy_protocol_version": "10", - "strategy_sequence": "1", - "message_type": "ready", - "payload": { - "strategy_name": "conformance", - "strategy_version": null - } - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "ready" - }, - { - "name": "strategy-intents-valid-v10", - "artifact": "strategy-message-v10", - "instance": { - "strategy_protocol_version": "10", - "strategy_sequence": "2", - "message_type": "intents", - "payload": { - "intents": [] - } - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "intents" - }, - { - "name": "strategy-error-valid-v10", - "artifact": "strategy-message-v10", - "instance": { - "strategy_protocol_version": "10", - "strategy_sequence": "7", - "message_type": "error", - "payload": { - "message": "fixture failure" - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-v10-rejected-response-branch", - "artifact": "strategy-transcript-v10", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "scenario-v13-valid", - "artifact": "scenario-v13", - "kind": "scenario", - "source": "v13/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept" - }, - { - "name": "scenario-stream-v13-valid", - "artifact": "scenario-stream-v13", - "kind": "scenario_stream", - "source": "v13/fixtures/demo.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept" - }, - { - "name": "strategy-ready-valid-v11", - "artifact": "strategy-message-v11", - "instance": { - "strategy_protocol_version": "11", - "strategy_sequence": "1", - "message_type": "ready", - "payload": { - "strategy_name": "conformance", - "strategy_version": null - } - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "ready" - }, - { - "name": "strategy-intents-valid-v11", - "artifact": "strategy-message-v11", - "instance": { - "strategy_protocol_version": "11", - "strategy_sequence": "2", - "message_type": "intents", - "payload": { - "intents": [] - } - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "intents" - }, - { - "name": "strategy-error-valid-v11", - "artifact": "strategy-message-v11", - "instance": { - "strategy_protocol_version": "11", - "strategy_sequence": "7", - "message_type": "error", - "payload": { - "message": "fixture failure" - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-v11-rejected-response-branch", - "artifact": "strategy-transcript-v11", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "scenario-v14-valid", - "artifact": "scenario-v14", - "kind": "scenario", - "source": "v14/fixtures/demo.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept" - }, - { - "name": "scenario-v14-quote-trade-valid", - "artifact": "scenario-v14", - "kind": "scenario", - "source": "v14/fixtures/quote-trade.scenario.json", - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept" - }, - { - "name": "scenario-stream-v14-valid", - "artifact": "scenario-stream-v14", - "kind": "scenario_stream", - "source": "v14/fixtures/quote-trade.scenario.jsonl", - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept" - }, - { - "name": "strategy-ready-valid-v12", - "artifact": "strategy-message-v12", - "instance": { - "strategy_protocol_version": "12", - "strategy_sequence": "1", - "message_type": "ready", - "payload": { - "strategy_name": "conformance", - "strategy_version": null - } - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "ready" - }, - { - "name": "strategy-intents-valid-v12", - "artifact": "strategy-message-v12", - "instance": { - "strategy_protocol_version": "12", - "strategy_sequence": "2", - "message_type": "intents", - "payload": { - "intents": [] - } - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "intents" - }, - { - "name": "strategy-error-valid-v12", - "artifact": "strategy-message-v12", - "instance": { - "strategy_protocol_version": "12", - "strategy_sequence": "7", - "message_type": "error", - "payload": { - "message": "fixture failure" - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-v12-rejected-response-branch", - "artifact": "strategy-transcript-v12", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-stopped-valid-v13", - "artifact": "strategy-message-v13", - "instance": { - "strategy_protocol_version": "13", - "strategy_sequence": "7", - "message_type": "stopped", - "payload": {} - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "stopped" - }, - { - "name": "strategy-error-valid-v13", - "artifact": "strategy-message-v13", - "instance": { - "strategy_protocol_version": "13", - "strategy_sequence": "7", - "message_type": "error", - "payload": { - "message": "fixture failure" - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-v13-rejected-response-branch", - "artifact": "strategy-transcript-v13", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-stopped-valid-v14", - "artifact": "strategy-message-v14", - "instance": { - "strategy_protocol_version": "14", - "strategy_sequence": "7", - "message_type": "stopped", - "payload": {} - }, - "mutations": [], - "schema_expectation": "accept", - "parser_expectation": "accept", - "parser_expected": "stopped" - }, - { - "name": "strategy-error-valid-v14", - "artifact": "strategy-message-v14", - "instance": { - "strategy_protocol_version": "14", - "strategy_sequence": "7", - "message_type": "error", - "payload": { - "message": "fixture failure" - } - }, - "mutations": [], - "schema_expectation": "accept" - }, - { - "name": "strategy-v14-rejected-response-branch", - "artifact": "strategy-transcript-v14", - "instance": { - "strategy_diagnostic_version": "1", - "transcript_sequence": "2", - "record_type": "rejected_strategy_response", - "expected_strategy_sequence": "1", - "diagnostic": { - "diagnostic_version": "1", - "code": "strategy.protocol", - "phase": "strategy", - "message": "strategy initialization: invalid strategy response JSON", - "context": { - "json_path": "$", - "sequence": "1" - }, - "cause": null - }, - "evidence": { - "encoding": "hex", - "prefix": "7b", - "observed_bytes": 1, - "truncated": false - } - }, - "mutations": [], - "schema_expectation": "accept" } ] } diff --git a/contracts/conformance/dune b/contracts/conformance/dune index d1eb67f..7a4e1fa 100644 --- a/contracts/conformance/dune +++ b/contracts/conformance/dune @@ -4,5 +4,4 @@ (files (README.md as contracts/conformance/README.md) (cases.json as contracts/conformance/cases.json) - (frozen.sha256 as contracts/conformance/frozen.sha256) (manifest.json as contracts/conformance/manifest.json))) diff --git a/contracts/conformance/frozen.sha256 b/contracts/conformance/frozen.sha256 deleted file mode 100644 index a17e5ab..0000000 --- a/contracts/conformance/frozen.sha256 +++ /dev/null @@ -1,22 +0,0 @@ -78df448f65b0d784d51951108cacb1db247d9d2dd03d93886f43e4acc0e83e1d contracts/strategy/v1/fixtures/external.scenario.json -135cc392abcf1f9dae9e2f190bb96c68ef9b39c44e23ac9250482d93912e326d contracts/strategy/v1/fixtures/external.scenario.jsonl -c93f085b131c1af6aadd84a8fda6bebe9520e5e11c03945b47577846bca7cced contracts/strategy/v1/fixtures/external.strategy.jsonl -9bba3babb59ec025bbcc159b24b99b2f260341456e12caafc1ea05d95a4c9742 contracts/strategy/v1/message.schema.json -64aedf3ea18319c65ad8c3d5a7775e5acff9712170e9ce2211839573f84ddbfb contracts/strategy/v1/transcript.schema.json -78df448f65b0d784d51951108cacb1db247d9d2dd03d93886f43e4acc0e83e1d contracts/strategy/v2/fixtures/external.scenario.json -135cc392abcf1f9dae9e2f190bb96c68ef9b39c44e23ac9250482d93912e326d contracts/strategy/v2/fixtures/external.scenario.jsonl -c35b69d323a35d1637955034b357d83215a67eb0f89513686e271d61af6a8cb4 contracts/strategy/v2/fixtures/external.strategy.jsonl -4666cc7ee98a1420a4003150f080a3f3a538e4366dfa1b7d80b0595518af97a7 contracts/strategy/v2/message.schema.json -c0c974c7aa57e16179462a5ef2a34924b8593d6823b928b2c2f51ce2817c7db5 contracts/strategy/v2/transcript.schema.json -2b4c0b2608fff14fe32cc1366a307e181993f81e14eaf16632ec72ca4eef8bda contracts/v1/fixtures/demo.journal.jsonl -a782fbbee8b89332ee6491d9d9be36bf7f2aaacbd440d30c20ed033fd7566d19 contracts/v1/fixtures/demo.scenario.json -d83b7c23d5e44793f9b71c542738cf4fed0612117e8399a61059677974f3382c contracts/v1/fixtures/demo.scenario.jsonl -9dd286602774f360b149f28828b56ccb1a8676dad8c5e2843d9df5499697fddf contracts/v1/journal.schema.json -9ee2f673c15c410e7cf9943a93526761a2eead592e5ac6948c9abc9d005d3c4e contracts/v1/scenario-stream.schema.json -cdd3102b873206c882f80496bc50f013b82ae62411025c5aa06fffafc692cb07 contracts/v1/scenario.schema.json -7c04bdff8488de02bf6e95238b91b348b0a36eecbb808030ac9e346552790f62 contracts/v2/fixtures/demo.journal.jsonl -21834e964dd6daab292e6285924384970b3341f7166ead1d38f8edb284541e44 contracts/v2/fixtures/demo.scenario.json -576573a119da2fecb9188cdf309bd21888b34d594c416c69e5d69c55255e1765 contracts/v2/fixtures/demo.scenario.jsonl -e222fb136b636b6281186512078bc781d234cefe3c2ede82b1c792daf66231cf contracts/v2/journal.schema.json -fb7e5c459977d6351f4b40938ce898441b0afc268b048b4e48bb094954186f46 contracts/v2/scenario-stream.schema.json -0340a0f5305810acd102894cf8557e312534bbad6eafcf5c27ae88b1dfaca147 contracts/v2/scenario.schema.json diff --git a/contracts/conformance/manifest.json b/contracts/conformance/manifest.json index fe01d3c..20721a2 100644 --- a/contracts/conformance/manifest.json +++ b/contracts/conformance/manifest.json @@ -7,10 +7,11 @@ "version_field": "contract_version", "version": "1", "sources": [ - { - "path": "v1/fixtures/demo.scenario.json", - "format": "json" - } + { "path": "v1/fixtures/demo.scenario.json", "format": "json" }, + { "path": "v1/fixtures/fill-clipped.scenario.json", "format": "json" }, + { "path": "v1/fixtures/quote-trade.scenario.json", "format": "json" }, + { "path": "v1/fixtures/order-book.scenario.json", "format": "json" }, + { "path": "strategy/v1/fixtures/external.scenario.json", "format": "json" } ] }, { @@ -19,10 +20,10 @@ "version_field": "contract_version", "version": "1", "sources": [ - { - "path": "v1/fixtures/demo.scenario.jsonl", - "format": "jsonl" - } + { "path": "v1/fixtures/demo.scenario.jsonl", "format": "jsonl" }, + { "path": "v1/fixtures/quote-trade.scenario.jsonl", "format": "jsonl" }, + { "path": "v1/fixtures/order-book.scenario.jsonl", "format": "jsonl" }, + { "path": "strategy/v1/fixtures/external.scenario.jsonl", "format": "jsonl" } ] }, { @@ -31,258 +32,10 @@ "version_field": "contract_version", "version": "1", "sources": [ - { - "path": "v1/fixtures/demo.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v2", - "schema": "v2/scenario.schema.json", - "version_field": "contract_version", - "version": "2", - "sources": [ - { - "path": "v2/fixtures/demo.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v2", - "schema": "v2/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "2", - "sources": [ - { - "path": "v2/fixtures/demo.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v2", - "schema": "v2/journal.schema.json", - "version_field": "contract_version", - "version": "2", - "sources": [ - { - "path": "v2/fixtures/demo.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v3", - "schema": "v3/scenario.schema.json", - "version_field": "contract_version", - "version": "3", - "sources": [ - { - "path": "v3/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "strategy/v1/fixtures/external.scenario.json", - "format": "json" - }, - { - "path": "strategy/v2/fixtures/external.scenario.json", - "format": "json" - }, - { - "path": "strategy/v3/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v3", - "schema": "v3/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "3", - "sources": [ - { - "path": "v3/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v1/fixtures/external.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v2/fixtures/external.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v3/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v3", - "schema": "v3/journal.schema.json", - "version_field": "contract_version", - "version": "3", - "sources": [ - { - "path": "v3/fixtures/demo.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v4", - "schema": "v4/scenario.schema.json", - "version_field": "contract_version", - "version": "4", - "sources": [ - { - "path": "v4/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v4/fixtures/fill-clipped.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v4", - "schema": "v4/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "4", - "sources": [ - { - "path": "v4/fixtures/demo.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v4", - "schema": "v4/journal.schema.json", - "version_field": "contract_version", - "version": "4", - "sources": [ - { - "path": "v4/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v4/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v5", - "schema": "v5/scenario.schema.json", - "version_field": "contract_version", - "version": "5", - "sources": [ - { - "path": "v5/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v5/fixtures/fill-clipped.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v5", - "schema": "v5/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "5", - "sources": [ - { - "path": "v5/fixtures/demo.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v5", - "schema": "v5/journal.schema.json", - "version_field": "contract_version", - "version": "5", - "sources": [ - { - "path": "v5/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v5/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v6", - "schema": "v6/scenario.schema.json", - "version_field": "contract_version", - "version": "6", - "sources": [ - { - "path": "v6/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v6/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v4/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v6", - "schema": "v6/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "6", - "sources": [ - { - "path": "v6/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v4/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v6", - "schema": "v6/journal.schema.json", - "version_field": "contract_version", - "version": "6", - "sources": [ - { - "path": "v6/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v6/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "diagnostic-v1", - "schema": "diagnostic/v1/diagnostic.schema.json", - "version_field": "diagnostic_version", - "version": "1", - "sources": [ - { - "path": "diagnostic/v1/fixtures/strategy-protocol.json", - "format": "json" - } + { "path": "v1/fixtures/demo.journal.jsonl", "format": "jsonl" }, + { "path": "v1/fixtures/fill-clipped.journal.jsonl", "format": "jsonl" }, + { "path": "v1/fixtures/quote-trade.journal.jsonl", "format": "jsonl" }, + { "path": "v1/fixtures/order-book.journal.jsonl", "format": "jsonl" } ] }, { @@ -294,9 +47,7 @@ { "path": "strategy/v1/fixtures/external.strategy.jsonl", "format": "jsonl", - "extract": [ - "message" - ] + "extract": ["message"] } ] }, @@ -306,953 +57,25 @@ "version_field": "strategy_protocol_version", "version": "1", "sources": [ - { - "path": "strategy/v1/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v2", - "schema": "strategy/v2/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "2", - "sources": [ - { - "path": "strategy/v2/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v2", - "schema": "strategy/v2/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "2", - "sources": [ - { - "path": "strategy/v2/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v3", - "schema": "strategy/v3/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "3", - "sources": [ - { - "path": "strategy/v3/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v3", - "schema": "strategy/v3/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "3", - "sources": [ - { - "path": "strategy/v3/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v4", - "schema": "strategy/v4/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "4", - "sources": [ - { - "path": "strategy/v4/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v4", - "schema": "strategy/v4/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "4", - "sources": [ - { - "path": "strategy/v4/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v7", - "schema": "v7/scenario.schema.json", - "version_field": "contract_version", - "version": "7", - "sources": [ - { - "path": "v7/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v7/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v5/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v7", - "schema": "v7/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "7", - "sources": [ - { - "path": "v7/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v5/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v7", - "schema": "v7/journal.schema.json", - "version_field": "contract_version", - "version": "7", - "sources": [ - { - "path": "v7/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v7/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v5", - "schema": "strategy/v5/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "5", - "sources": [ - { - "path": "strategy/v5/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v5", - "schema": "strategy/v5/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "5", - "sources": [ - { - "path": "strategy/v5/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v8", - "schema": "v8/scenario.schema.json", - "version_field": "contract_version", - "version": "8", - "sources": [ - { - "path": "v8/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v8/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v6/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v8", - "schema": "v8/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "8", - "sources": [ - { - "path": "v8/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v6/fixtures/external.scenario.jsonl", - "format": "jsonl" - } + { "path": "strategy/v1/fixtures/external.strategy.jsonl", "format": "jsonl" } ] }, { - "name": "journal-v8", - "schema": "v8/journal.schema.json", - "version_field": "contract_version", - "version": "8", + "name": "diagnostic-v1", + "schema": "diagnostic/v1/diagnostic.schema.json", + "version_field": "diagnostic_version", + "version": "1", "sources": [ - { - "path": "v8/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v8/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } + { "path": "diagnostic/v1/fixtures/strategy-protocol.json", "format": "json" } ] }, { - "name": "strategy-message-v6", - "schema": "strategy/v6/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "6", + "name": "cli-result-v1", + "schema": "cli/v1/result.schema.json", + "version_field": "result_version", + "version": "1", "sources": [ - { - "path": "strategy/v6/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v6", - "schema": "strategy/v6/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "6", - "sources": [ - { - "path": "strategy/v6/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v9", - "schema": "v9/scenario.schema.json", - "version_field": "contract_version", - "version": "9", - "sources": [ - { - "path": "v9/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v9/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v7/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v9", - "schema": "v9/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "9", - "sources": [ - { - "path": "v9/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v7/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v9", - "schema": "v9/journal.schema.json", - "version_field": "contract_version", - "version": "9", - "sources": [ - { - "path": "v9/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v9/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v7", - "schema": "strategy/v7/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "7", - "sources": [ - { - "path": "strategy/v7/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v7", - "schema": "strategy/v7/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "7", - "sources": [ - { - "path": "strategy/v7/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v10", - "schema": "v10/scenario.schema.json", - "version_field": "contract_version", - "version": "10", - "sources": [ - { - "path": "v10/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v10/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v8/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v10", - "schema": "v10/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "10", - "sources": [ - { - "path": "v10/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v8/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v10", - "schema": "v10/journal.schema.json", - "version_field": "contract_version", - "version": "10", - "sources": [ - { - "path": "v10/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v10/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v8", - "schema": "strategy/v8/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "8", - "sources": [ - { - "path": "strategy/v8/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v8", - "schema": "strategy/v8/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "8", - "sources": [ - { - "path": "strategy/v8/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v11", - "schema": "v11/scenario.schema.json", - "version_field": "contract_version", - "version": "11", - "sources": [ - { - "path": "v11/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v11/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v9/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v11", - "schema": "v11/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "11", - "sources": [ - { - "path": "v11/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v9/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v11", - "schema": "v11/journal.schema.json", - "version_field": "contract_version", - "version": "11", - "sources": [ - { - "path": "v11/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v11/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v9", - "schema": "strategy/v9/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "9", - "sources": [ - { - "path": "strategy/v9/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v9", - "schema": "strategy/v9/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "9", - "sources": [ - { - "path": "strategy/v9/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v12", - "schema": "v12/scenario.schema.json", - "version_field": "contract_version", - "version": "12", - "sources": [ - { - "path": "v12/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v12/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v10/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v12", - "schema": "v12/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "12", - "sources": [ - { - "path": "v12/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v10/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v12", - "schema": "v12/journal.schema.json", - "version_field": "contract_version", - "version": "12", - "sources": [ - { - "path": "v12/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v12/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v10", - "schema": "strategy/v10/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "10", - "sources": [ - { - "path": "strategy/v10/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v10", - "schema": "strategy/v10/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "10", - "sources": [ - { - "path": "strategy/v10/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v13", - "schema": "v13/scenario.schema.json", - "version_field": "contract_version", - "version": "13", - "sources": [ - { - "path": "v13/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v13/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "strategy/v11/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v13", - "schema": "v13/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "13", - "sources": [ - { - "path": "v13/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v11/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v13", - "schema": "v13/journal.schema.json", - "version_field": "contract_version", - "version": "13", - "sources": [ - { - "path": "v13/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v13/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v11", - "schema": "strategy/v11/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "11", - "sources": [ - { - "path": "strategy/v11/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v11", - "schema": "strategy/v11/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "11", - "sources": [ - { - "path": "strategy/v11/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v14", - "schema": "v14/scenario.schema.json", - "version_field": "contract_version", - "version": "14", - "sources": [ - { - "path": "v14/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v14/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "v14/fixtures/quote-trade.scenario.json", - "format": "json" - }, - { - "path": "strategy/v12/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v14", - "schema": "v14/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "14", - "sources": [ - { - "path": "v14/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "v14/fixtures/quote-trade.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v12/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v14", - "schema": "v14/journal.schema.json", - "version_field": "contract_version", - "version": "14", - "sources": [ - { - "path": "v14/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v14/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v14/fixtures/quote-trade.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v12", - "schema": "strategy/v12/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "12", - "sources": [ - { - "path": "strategy/v12/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v12", - "schema": "strategy/v12/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "12", - "sources": [ - { - "path": "strategy/v12/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v15", - "schema": "v15/scenario.schema.json", - "version_field": "contract_version", - "version": "15", - "sources": [ - { - "path": "v15/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v15/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "v15/fixtures/quote-trade.scenario.json", - "format": "json" - }, - { - "path": "v15/fixtures/order-book.scenario.json", - "format": "json" - }, - { - "path": "strategy/v13/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v15", - "schema": "v15/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "15", - "sources": [ - { - "path": "v15/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "v15/fixtures/quote-trade.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "v15/fixtures/order-book.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v13/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v15", - "schema": "v15/journal.schema.json", - "version_field": "contract_version", - "version": "15", - "sources": [ - { - "path": "v15/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v15/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v15/fixtures/quote-trade.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v15/fixtures/order-book.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v13", - "schema": "strategy/v13/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "13", - "sources": [ - { - "path": "strategy/v13/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v13", - "schema": "strategy/v13/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "13", - "sources": [ - { - "path": "strategy/v13/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "scenario-v16", - "schema": "v16/scenario.schema.json", - "version_field": "contract_version", - "version": "16", - "sources": [ - { - "path": "v16/fixtures/demo.scenario.json", - "format": "json" - }, - { - "path": "v16/fixtures/fill-clipped.scenario.json", - "format": "json" - }, - { - "path": "v16/fixtures/quote-trade.scenario.json", - "format": "json" - }, - { - "path": "v16/fixtures/order-book.scenario.json", - "format": "json" - }, - { - "path": "strategy/v14/fixtures/external.scenario.json", - "format": "json" - } - ] - }, - { - "name": "scenario-stream-v16", - "schema": "v16/scenario-stream.schema.json", - "version_field": "contract_version", - "version": "16", - "sources": [ - { - "path": "v16/fixtures/demo.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "v16/fixtures/quote-trade.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "v16/fixtures/order-book.scenario.jsonl", - "format": "jsonl" - }, - { - "path": "strategy/v14/fixtures/external.scenario.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "journal-v16", - "schema": "v16/journal.schema.json", - "version_field": "contract_version", - "version": "16", - "sources": [ - { - "path": "v16/fixtures/demo.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v16/fixtures/fill-clipped.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v16/fixtures/quote-trade.journal.jsonl", - "format": "jsonl" - }, - { - "path": "v16/fixtures/order-book.journal.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "strategy-message-v14", - "schema": "strategy/v14/message.schema.json", - "version_field": "strategy_protocol_version", - "version": "14", - "sources": [ - { - "path": "strategy/v14/fixtures/external.strategy.jsonl", - "format": "jsonl", - "extract": [ - "message" - ] - } - ] - }, - { - "name": "strategy-transcript-v14", - "schema": "strategy/v14/transcript.schema.json", - "version_field": "strategy_protocol_version", - "version": "14", - "sources": [ - { - "path": "strategy/v14/fixtures/external.strategy.jsonl", - "format": "jsonl" - } - ] - }, - { - "name": "cli-result-v1", - "schema": "cli/v1/result.schema.json", - "version_field": "result_version", - "version": "1", - "sources": [ - { - "path": "cli/v1/fixtures/demo.result.json", - "format": "json" - } + { "path": "cli/v1/fixtures/demo.result.json", "format": "json" } ] } ] diff --git a/contracts/strategy/v1/README.md b/contracts/strategy/v1/README.md index 4fa306f..8f72849 100644 --- a/contracts/strategy/v1/README.md +++ b/contracts/strategy/v1/README.md @@ -1,26 +1,17 @@ # External strategy protocol v1 -Version 1 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. +Trading Engine supervises external strategies over synchronous JSON Lines on standard input and +output. `message.schema.json` defines protocol messages and `transcript.schema.json` defines the +durable exchange log. -Every message repeats `strategy_protocol_version: "1"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. +Every message carries `"strategy_protocol_version": "1"` and a positive decimal-string sequence. +The engine sends `initialize`, ordered `event` messages, and `shutdown`; the strategy replies with +`ready`, matching `intents`, and `stopped`. The runtime enforces direction, sequence pairing, +canonical values, message limits, and lifecycle order. -The event context contains the replay clock, every cash ledger and configured position, all -working orders, and the latest available bar for each instrument. Event payloads cover completed -market slices, fills, order updates, and rejected intents. Response intents use the scenario v3 -intent shapes. +Initialization binds the strategy to replay contract v1, the scenario hash, initial portfolio, +instruments, risk, execution, financing, settlement, venue calendars, and metadata. Event contexts +include the current portfolio, working orders, bars, and group exposures. -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records both directions in a deterministic transcript. The transcript and audit journal retain -partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates retained transcript records. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. +The fixtures contain a complete accepted session. Run `make check` to validate both schemas and +runtime behavior. diff --git a/contracts/strategy/v1/fixtures/external.scenario.json b/contracts/strategy/v1/fixtures/external.scenario.json index 5fe2d5a..04961cf 100644 --- a/contracts/strategy/v1/fixtures/external.scenario.json +++ b/contracts/strategy/v1/fixtures/external.scenario.json @@ -1,13 +1,26 @@ { - "contract_version": "3", + "contract_version": "1", "metadata": { "producer": "strategy-protocol-fixture" }, "run_id": "external-demo", "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "10000" } - ], + "initial_portfolio": { + "cash": [ + { + "currency": "USD", + "amount": "10000" + } + ], + "positions": [], + "marks": [], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } + ] + }, "instruments": [ { "instrument_id": "demo-equity-acme", @@ -17,21 +30,148 @@ "lot_size": "1" } ], + "venue_calendars": [ + { + "calendar_id": "demo-xnas-2026", + "calendar_version": "1", + "venue_id": "XNAS", + "instrument_ids": [ + "demo-equity-acme" + ], + "sessions": [ + { + "session_date": "2026-01-01", + "policy": "holiday", + "phases": [] + }, + { + "session_date": "2026-01-02", + "policy": "regular", + "phases": [ + { + "phase": "premarket", + "opens_at": "2026-01-02T09:00:00Z", + "closes_at": "2026-01-02T14:25:00Z" + }, + { + "phase": "opening_auction", + "opens_at": "2026-01-02T14:25:00Z", + "closes_at": "2026-01-02T14:30:00Z" + }, + { + "phase": "regular", + "opens_at": "2026-01-02T14:30:00Z", + "closes_at": "2026-01-02T20:55:00Z" + }, + { + "phase": "closing_auction", + "opens_at": "2026-01-02T20:55:00Z", + "closes_at": "2026-01-02T21:00:00Z" + }, + { + "phase": "postmarket", + "opens_at": "2026-01-02T21:00:00Z", + "closes_at": "2026-01-03T01:00:00Z" + } + ] + }, + { + "session_date": "2026-01-05", + "policy": "regular", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-05T14:30:00Z", + "closes_at": "2026-01-05T21:00:00Z" + } + ] + }, + { + "session_date": "2026-01-06", + "policy": "regular", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-06T14:30:00Z", + "closes_at": "2026-01-06T21:00:00Z" + } + ] + }, + { + "session_date": "2026-01-07", + "policy": "regular", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-07T14:30:00Z", + "closes_at": "2026-01-07T21:00:00Z" + } + ] + }, + { + "session_date": "2026-01-08", + "policy": "early_close", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-08T14:30:00Z", + "closes_at": "2026-01-08T18:00:00Z" + } + ] + } + ] + } + ], "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", "max_gross_exposure": "1000000", "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 0 + "instrument_policies": [ + { + "instrument_id": "demo-equity-acme", + "max_order_quantity": "1000", + "max_long_position": "1000", + "max_short_position": "1000", + "max_notional_exposure": "1000000", + "initial_margin_bps": 5000, + "maintenance_margin_bps": 2500, + "shorting_allowed": true + } + ], + "groups": [] }, "execution": { "model": "completed_bar_v1", - "participation_bps": 10000, - "fixed_fee": "0", - "fee_bps": 0 + "configuration": { + "version": "1", + "participation_bps": 5000, + "fee_schedules": [ + { + "schedule_id": "external-acme-fees-v1", + "instrument_id": "demo-equity-acme", + "settlement_currency": "USD", + "minimum": null, + "maximum": null, + "components": [ + { + "name": "broker", + "currency": "USD", + "kind": "fixed", + "value": "0.25", + "rounding": "up", + "applies_to": "any" + }, + { + "name": "exchange", + "currency": "USD", + "kind": "notional_bps", + "value": 10, + "rounding": "up", + "applies_to": "any" + } + ] + } + ] + } }, "max_internal_events": 1000, "schedule": [], @@ -43,10 +183,43 @@ "available_at": "2026-01-02T21:00:01Z", "received_at": "2026-01-02T21:00:02Z", "bars": [ - { "instrument_id": "demo-equity-acme", "open": "100", "high": "105", "low": "99", "close": "104", "volume": "100" } + { + "instrument_id": "demo-equity-acme", + "open": "100", + "high": "105", + "low": "99", + "close": "104", + "volume": "100" + } + ], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] + "corporate_actions": [], + "borrow_observations": [ + { + "instrument_id": "demo-equity-acme", + "effective_at": "2026-01-02T14:30:00Z", + "available_quantity": "1000", + "annual_rate_bps": 100, + "recalled": false + } + ], + "cash_rate_observations": [ + { + "currency": "USD", + "effective_at": "2026-01-02T14:30:00Z", + "credit_rate_bps": 0, + "debit_rate_bps": 0 + } + ], + "settlement_failures": [], + "lifecycle_events": [], + "market_events": [], + "order_book_events": [] }, { "slice_sequence": "2", @@ -55,10 +228,80 @@ "available_at": "2026-01-05T21:00:01Z", "received_at": "2026-01-05T21:00:02Z", "bars": [ - { "instrument_id": "demo-equity-acme", "open": "103", "high": "108", "low": "102", "close": "107", "volume": "100" } + { + "instrument_id": "demo-equity-acme", + "open": "103", + "high": "108", + "low": "102", + "close": "107", + "volume": "100" + } + ], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } + ], + "corporate_actions": [], + "borrow_observations": [ + { + "instrument_id": "demo-equity-acme", + "effective_at": "2026-01-05T14:30:00Z", + "available_quantity": "1000", + "annual_rate_bps": 100, + "recalled": false + } ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] + "cash_rate_observations": [ + { + "currency": "USD", + "effective_at": "2026-01-05T14:30:00Z", + "credit_rate_bps": 0, + "debit_rate_bps": 0 + } + ], + "settlement_failures": [], + "lifecycle_events": [], + "market_events": [], + "order_book_events": [] } - ] + ], + "financing": { + "day_count": "actual_365", + "compounding": "simple", + "borrow_missing_data": "reject", + "cash_missing_data": "reject", + "locate_policy": "clip_fill", + "recall_policy": "close_out" + }, + "settlement": { + "cash_buying_power": "total_cash", + "position_availability": "total_positions", + "calendars": [ + { + "calendar_id": "default-settlement", + "version": "1", + "business_dates": [ + "2026-01-02", + "2026-01-05", + "2026-01-06", + "2026-01-07", + "2026-01-08", + "2026-01-09", + "2026-02-02", + "2026-02-03", + "2026-02-04", + "2026-02-05" + ] + } + ], + "rules": [ + { + "instrument_id": "demo-equity-acme", + "calendar_id": "default-settlement", + "lag_business_days": 1 + } + ] + } } diff --git a/contracts/strategy/v1/fixtures/external.scenario.jsonl b/contracts/strategy/v1/fixtures/external.scenario.jsonl index 1e168bf..d0de398 100644 --- a/contracts/strategy/v1/fixtures/external.scenario.jsonl +++ b/contracts/strategy/v1/fixtures/external.scenario.jsonl @@ -1,4 +1,4 @@ -{"contract_version":"3","payload":{"base_currency":"USD","execution":{"fee_bps":0,"fixed_fee":"0","model":"completed_bar_v1","participation_bps":10000},"initial_cash":[{"amount":"10000","currency":"USD"}],"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"max_internal_events":1000,"metadata":{"producer":"strategy-protocol-fixture"},"risk":{"initial_margin_bps":5000,"maintenance_margin_bps":2500,"max_gross_exposure":"1000000","max_leverage":"2","max_long_position":"1000","max_order_quantity":"1000","max_short_position":"1000","short_borrow_bps":0},"run_id":"external-demo"},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"3","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} +{"contract_version":"1","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} +{"contract_version":"1","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} +{"contract_version":"1","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} +{"contract_version":"1","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v1/fixtures/external.strategy.jsonl b/contracts/strategy/v1/fixtures/external.strategy.jsonl index 46d40e5..a74e5d5 100644 --- a/contracts/strategy/v1/fixtures/external.strategy.jsonl +++ b/contracts/strategy/v1/fixtures/external.strategy.jsonl @@ -1,14 +1,14 @@ -{"strategy_protocol_version":"1","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"0.1.0-dev","scenario_contract_version":"3","scenario_sha256":"78df448f65b0d784d51951108cacb1db247d9d2dd03d93886f43e4acc0e83e1d","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_gross_exposure":"1000000","max_leverage":"2","initial_margin_bps":5000,"maintenance_margin_bps":2500,"short_borrow_bps":0},"execution":{"model":"completed_bar_v1","participation_bps":10000,"fixed_fee":"0","fee_bps":0},"metadata":{"producer":"strategy-protocol-fixture"}}}} +{"strategy_protocol_version":"1","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"1","scenario_sha256":"7c1991b8f4662c51faf8b3436999fdce8f0295ee6c0ef5d20a0658c960d04c4d","run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} {"strategy_protocol_version":"1","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"1","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","cash_balances":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0"}],"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"1","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"1","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","cash_balances":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0"}],"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} +{"strategy_protocol_version":"1","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}}}}} +{"strategy_protocol_version":"1","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":{"type":"numeric","value":"2"},"unit":"score","dimensions":{"source":"fixture"},"aggregation":"last"}]}}} +{"strategy_protocol_version":"1","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} {"strategy_protocol_version":"1","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"1","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","cash_balances":[{"currency":"USD","amount":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2"}],"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}}}}} +{"strategy_protocol_version":"1","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}],"executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}}}}} {"strategy_protocol_version":"1","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"1","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","cash_balances":[{"currency":"USD","amount":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2"}],"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} +{"strategy_protocol_version":"1","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} {"strategy_protocol_version":"1","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"1","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","cash_balances":[{"currency":"USD","amount":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2"}],"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} +{"strategy_protocol_version":"1","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}}}}} {"strategy_protocol_version":"1","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} {"strategy_protocol_version":"1","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"1","strategy_sequence":"7","message_type":"shutdown","payload":{}}} {"strategy_protocol_version":"1","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"1","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v1/message.schema.json b/contracts/strategy/v1/message.schema.json index 576c7a5..29ca3ff 100644 --- a/contracts/strategy/v1/message.schema.json +++ b/contracts/strategy/v1/message.schema.json @@ -42,25 +42,33 @@ "initializePayload": { "type": "object", "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "metadata"], + "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "metadata"], "properties": { "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "type": "string", "minLength": 1 }, + "scenario_contract_version": { "const": "1" }, "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/cashBalance" } + "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" }, + "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" }, + "initial_portfolio": { + "oneOf": [ + { "type": "null" }, + { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/initialPortfolio" } + ] }, "instruments": { "type": "array", "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/instrument" } + "maxItems": 4096, + "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/instrument" } + }, + "venue_calendars": { + "type": "array", + "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/execution" }, + "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/risk" }, + "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/execution" }, + "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/financing" }, + "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/settlement" }, "metadata": { "type": "object" } } }, @@ -80,7 +88,7 @@ "additionalProperties": false, "required": ["strategy_name", "strategy_version"], "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, + "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" }, "strategy_version": { "oneOf": [ { "type": "null" }, @@ -112,36 +120,68 @@ "context": { "type": "object", "additionalProperties": false, - "required": ["now", "cash_balances", "positions", "working_orders", "latest_bars"], + "required": ["now", "portfolio", "working_orders", "latest_bars"], "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/timestamp" }, + "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/timestamp" }, + "portfolio": { "$ref": "#/$defs/portfolio" }, + "working_orders": { + "type": "array", + "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/order" } + }, + "latest_bars": { + "type": "array", + "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/bar" } + } + } + }, + "portfolio": { + "type": "object", + "additionalProperties": false, + "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], + "properties": { + "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" }, + "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" }, + "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" }, + "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/unsignedDecimal" }, + "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/unsignedDecimal" }, + "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/unsignedDecimal" }, + "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" }, + "weights_available": { "type": "boolean" }, + "cash_weight": { "$ref": "#/$defs/optionalWeight" }, "cash_balances": { "type": "array", "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/cashBalance" } + "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/cashAttribution" } }, "positions": { "type": "array", "minItems": 1, - "items": { "$ref": "#/$defs/position" } - }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/order" } + "items": { "$ref": "#/$defs/markedPosition" } }, - "latest_bars": { + "group_exposures": { "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/bar" } + "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/groupExposure" } } } }, - "position": { + "optionalWeight": { + "oneOf": [ + { "type": "null" }, + { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" } + ] + }, + "markedPosition": { "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quantity"], + "required": ["instrument_id", "quantity", "settled_quantity", "unsettled_quantity", "mark", "base_market_value", "weight"], "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" } + "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" }, + "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" }, + "settled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" }, + "unsettled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" }, + "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/positiveDecimal" }, + "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/signedDecimal" }, + "weight": { "$ref": "#/$defs/optionalWeight" } } }, "strategyEvent": { @@ -152,7 +192,7 @@ "required": ["type", "market_slice"], "properties": { "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/marketSlice" } + "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/marketSlice" } } }, { @@ -161,7 +201,7 @@ "required": ["type", "fill"], "properties": { "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/fill" } + "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/fill" } } }, { @@ -170,7 +210,7 @@ "required": ["type", "order"], "properties": { "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/order" } + "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/journal.schema.json#/$defs/order" } } }, { @@ -202,7 +242,8 @@ "properties": { "intents": { "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/intent" } + "maxItems": 4096, + "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/intent" } } } }, diff --git a/contracts/strategy/v1/transcript.schema.json b/contracts/strategy/v1/transcript.schema.json index c62a889..791e9cf 100644 --- a/contracts/strategy/v1/transcript.schema.json +++ b/contracts/strategy/v1/transcript.schema.json @@ -2,21 +2,81 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v1/transcript.schema.json", "title": "Trading Engine external strategy protocol v1 transcript record", - "description": "One ordered request or response retained from a supervised stdio strategy session.", - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "1" }, - "transcript_sequence": { + "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", + "oneOf": [ + { "$ref": "#/$defs/exchange" }, + { "$ref": "#/$defs/rejectedResponse" } + ], + "$defs": { + "canonicalSequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] + "exchange": { + "type": "object", + "additionalProperties": false, + "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], + "properties": { + "strategy_protocol_version": { "const": "1" }, + "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, + "direction": { + "enum": ["engine_to_strategy", "strategy_to_engine"] + }, + "message": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v1/message.schema.json" + } + } }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v1/message.schema.json" + "rejectedResponse": { + "type": "object", + "additionalProperties": false, + "required": [ + "strategy_diagnostic_version", + "transcript_sequence", + "record_type", + "expected_strategy_sequence", + "diagnostic", + "evidence" + ], + "properties": { + "strategy_diagnostic_version": { "const": "1" }, + "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, + "record_type": { "const": "rejected_strategy_response" }, + "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, + "diagnostic": { "$ref": "#/$defs/diagnostic" }, + "evidence": { "$ref": "#/$defs/evidence" } + } + }, + "diagnostic": { + "allOf": [ + { + "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" + }, + { + "properties": { + "code": { "enum": ["strategy.protocol", "resource.limit"] }, + "phase": { "const": "strategy" } + } + } + ] + }, + "evidence": { + "type": "object", + "additionalProperties": false, + "required": ["encoding", "prefix", "observed_bytes", "truncated"], + "properties": { + "encoding": { "const": "hex" }, + "prefix": { + "type": "string", + "pattern": "^(?:[0-9a-f]{2}){0,256}$" + }, + "observed_bytes": { + "type": "integer", + "minimum": 0, + "maximum": 1048577 + }, + "truncated": { "type": "boolean" } + } } } } diff --git a/contracts/strategy/v10/README.md b/contracts/strategy/v10/README.md deleted file mode 100644 index 17c89a1..0000000 --- a/contracts/strategy/v10/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# External strategy protocol v10 - -Version 10 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v9 remains available for scenario contract v11; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "10"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v12 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars, nested execution configuration, financing policy, and settlement policy, so a strategy -can construct DAY orders and reject incompatible execution, financing, or settlement state before -replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices with effective-time borrow and cash-rate observations -plus explicit settlement failures, fills, order updates, and rejected intents. Portfolio contexts -include cash-interest attribution and settled and unsettled cash and position quantities. Response -intents use the scenario v12 intent shapes. Market-slice events include lifecycle transitions and -the expanded corporate-action catalog. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v10/dune b/contracts/strategy/v10/dune deleted file mode 100644 index 7fa7432..0000000 --- a/contracts/strategy/v10/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v10/message.schema.json) - (transcript.schema.json as contracts/strategy/v10/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v10/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v10/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v10/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v10/fixtures/external.scenario.json b/contracts/strategy/v10/fixtures/external.scenario.json deleted file mode 100644 index c37e23b..0000000 --- a/contracts/strategy/v10/fixtures/external.scenario.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "contract_version": "12", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], "lifecycle_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/strategy/v10/fixtures/external.scenario.jsonl b/contracts/strategy/v10/fixtures/external.scenario.jsonl deleted file mode 100644 index e428012..0000000 --- a/contracts/strategy/v10/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"12","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"12","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"12","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"12","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v10/fixtures/external.strategy.jsonl b/contracts/strategy/v10/fixtures/external.strategy.jsonl deleted file mode 100644 index 0b07034..0000000 --- a/contracts/strategy/v10/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"10","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"10","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"12","scenario_sha256":"6809a3638fe668a2a11e56c42e9bac7e506c0064eb2cb0a3e71ba09d92839ee7","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"10","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"10","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"10","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"10","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}}}}} -{"strategy_protocol_version":"10","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"10","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"10","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"10","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"10","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"10","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"10","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"10","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"10","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"10","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"10","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"10","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"10","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"10","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"10","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"10","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}}}}} -{"strategy_protocol_version":"10","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"10","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"10","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"10","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"10","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"10","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v10/message.schema.json b/contracts/strategy/v10/message.schema.json deleted file mode 100644 index cf722e9..0000000 --- a/contracts/strategy/v10/message.schema.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v10/message.schema.json", - "title": "Trading Engine external strategy protocol v10 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "10" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "12" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/settlement" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "settled_quantity", "unsettled_quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" }, - "settled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" }, - "unsettled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v10/transcript.schema.json b/contracts/strategy/v10/transcript.schema.json deleted file mode 100644 index 02d3ca0..0000000 --- a/contracts/strategy/v10/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v10/transcript.schema.json", - "title": "Trading Engine external strategy protocol v10 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "10" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v10/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v11/README.md b/contracts/strategy/v11/README.md deleted file mode 100644 index 11d712c..0000000 --- a/contracts/strategy/v11/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# External strategy protocol v11 - -Version 11 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v10 remains available for scenario contract v12; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "11"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v13 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars, nested execution configuration, financing policy, and settlement policy, so a strategy -can construct DAY orders and reject incompatible execution, financing, or settlement state before -replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices with effective-time borrow and cash-rate observations -plus explicit settlement failures, fills, order updates, and rejected intents. Portfolio contexts -include cash-interest attribution and settled and unsettled cash and position quantities. Response -intents use the scenario v13 intent shapes. Market-slice events include lifecycle transitions and -the expanded corporate-action catalog. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v11/dune b/contracts/strategy/v11/dune deleted file mode 100644 index 977dbb1..0000000 --- a/contracts/strategy/v11/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v11/message.schema.json) - (transcript.schema.json as contracts/strategy/v11/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v11/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v11/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v11/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v11/fixtures/external.scenario.json b/contracts/strategy/v11/fixtures/external.scenario.json deleted file mode 100644 index d6f9bab..0000000 --- a/contracts/strategy/v11/fixtures/external.scenario.json +++ /dev/null @@ -1,304 +0,0 @@ -{ - "contract_version": "13", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/strategy/v11/fixtures/external.scenario.jsonl b/contracts/strategy/v11/fixtures/external.scenario.jsonl deleted file mode 100644 index c1ced72..0000000 --- a/contracts/strategy/v11/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"13","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"13","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"13","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"13","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v11/fixtures/external.strategy.jsonl b/contracts/strategy/v11/fixtures/external.strategy.jsonl deleted file mode 100644 index 712ebc6..0000000 --- a/contracts/strategy/v11/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"11","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"11","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"13","scenario_sha256":"6809a3638fe668a2a11e56c42e9bac7e506c0064eb2cb0a3e71ba09d92839ee7","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"11","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"11","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"11","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"11","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}}}}} -{"strategy_protocol_version":"11","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"11","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"11","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"11","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"11","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"11","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"11","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"11","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"11","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"11","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"11","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"11","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"11","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"11","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"11","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"11","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[]}}}}} -{"strategy_protocol_version":"11","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"11","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"11","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"11","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"11","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"11","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v11/message.schema.json b/contracts/strategy/v11/message.schema.json deleted file mode 100644 index 4d26106..0000000 --- a/contracts/strategy/v11/message.schema.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v11/message.schema.json", - "title": "Trading Engine external strategy protocol v11 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "11" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "13" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/settlement" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "settled_quantity", "unsettled_quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" }, - "settled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" }, - "unsettled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v11/transcript.schema.json b/contracts/strategy/v11/transcript.schema.json deleted file mode 100644 index bbbca4b..0000000 --- a/contracts/strategy/v11/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v11/transcript.schema.json", - "title": "Trading Engine external strategy protocol v11 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "11" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v11/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v12/README.md b/contracts/strategy/v12/README.md deleted file mode 100644 index 5aa17ef..0000000 --- a/contracts/strategy/v12/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# External strategy protocol v12 - -Version 12 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v11 remains available for scenario contract v13; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "12"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v14 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars, nested execution configuration, financing policy, and settlement policy, so a strategy -can construct DAY orders and reject incompatible execution, financing, or settlement state before -replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices with effective-time borrow and cash-rate observations -plus explicit settlement failures, fills, order updates, and rejected intents. Portfolio contexts -include cash-interest attribution and settled and unsettled cash and position quantities. Response -intents use the scenario v14 intent shapes. Market-slice events include lifecycle transitions and -the expanded corporate-action catalog, plus causally ordered quote/trade market events. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v12/dune b/contracts/strategy/v12/dune deleted file mode 100644 index 3351a8f..0000000 --- a/contracts/strategy/v12/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v12/message.schema.json) - (transcript.schema.json as contracts/strategy/v12/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v12/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v12/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v12/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v12/fixtures/external.scenario.json b/contracts/strategy/v12/fixtures/external.scenario.json deleted file mode 100644 index 724125a..0000000 --- a/contracts/strategy/v12/fixtures/external.scenario.json +++ /dev/null @@ -1,306 +0,0 @@ -{ - "contract_version": "14", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/strategy/v12/fixtures/external.scenario.jsonl b/contracts/strategy/v12/fixtures/external.scenario.jsonl deleted file mode 100644 index 793db28..0000000 --- a/contracts/strategy/v12/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"14","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"14","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"14","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"14","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v12/fixtures/external.strategy.jsonl b/contracts/strategy/v12/fixtures/external.strategy.jsonl deleted file mode 100644 index acbe035..0000000 --- a/contracts/strategy/v12/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"12","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"12","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"14","scenario_sha256":"6809a3638fe668a2a11e56c42e9bac7e506c0064eb2cb0a3e71ba09d92839ee7","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"12","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"12","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"12","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"12","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}}}}} -{"strategy_protocol_version":"12","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"12","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"12","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"12","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"12","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"12","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"12","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"12","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"12","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"12","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"12","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"12","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"12","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"12","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"12","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"12","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}}}}} -{"strategy_protocol_version":"12","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"12","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"12","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"12","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"12","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"12","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v12/message.schema.json b/contracts/strategy/v12/message.schema.json deleted file mode 100644 index 58c9e0c..0000000 --- a/contracts/strategy/v12/message.schema.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v12/message.schema.json", - "title": "Trading Engine external strategy protocol v12 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "12" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "14" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/settlement" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "settled_quantity", "unsettled_quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" }, - "settled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" }, - "unsettled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v12/transcript.schema.json b/contracts/strategy/v12/transcript.schema.json deleted file mode 100644 index f00912f..0000000 --- a/contracts/strategy/v12/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v12/transcript.schema.json", - "title": "Trading Engine external strategy protocol v12 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "12" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v12/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v13/README.md b/contracts/strategy/v13/README.md deleted file mode 100644 index bc7a8d5..0000000 --- a/contracts/strategy/v13/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# External strategy protocol v13 - -Version 13 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v11 remains available for scenario contract v13; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "13"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v15 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars, nested execution configuration, financing policy, and settlement policy, so a strategy -can construct DAY orders and reject incompatible execution, financing, or settlement state before -replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices with effective-time borrow and cash-rate observations -plus explicit settlement failures, fills, order updates, and rejected intents. Portfolio contexts -include cash-interest attribution and settled and unsettled cash and position quantities. Response -intents use the scenario v15 intent shapes. Market-slice events include lifecycle transitions and -the expanded corporate-action catalog, plus causally ordered quote/trade market events. -Protocol v13 also carries bounded order-book snapshots and incrementals and advertises the -`order_book_v1` configuration, including its maximum depth. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v13/dune b/contracts/strategy/v13/dune deleted file mode 100644 index 70ad1c7..0000000 --- a/contracts/strategy/v13/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v13/message.schema.json) - (transcript.schema.json as contracts/strategy/v13/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v13/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v13/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v13/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v13/fixtures/external.scenario.json b/contracts/strategy/v13/fixtures/external.scenario.json deleted file mode 100644 index 5d45ea2..0000000 --- a/contracts/strategy/v13/fixtures/external.scenario.json +++ /dev/null @@ -1,308 +0,0 @@ -{ - "contract_version": "15", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/strategy/v13/fixtures/external.scenario.jsonl b/contracts/strategy/v13/fixtures/external.scenario.jsonl deleted file mode 100644 index 15ab15e..0000000 --- a/contracts/strategy/v13/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"15","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"15","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"15","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"15","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v13/fixtures/external.strategy.jsonl b/contracts/strategy/v13/fixtures/external.strategy.jsonl deleted file mode 100644 index 13c41e1..0000000 --- a/contracts/strategy/v13/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"13","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"13","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"15","scenario_sha256":"6809a3638fe668a2a11e56c42e9bac7e506c0064eb2cb0a3e71ba09d92839ee7","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"13","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"13","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"13","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"13","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}}}}} -{"strategy_protocol_version":"13","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"13","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"13","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"13","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"13","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"13","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"13","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"13","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"13","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"13","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"13","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"13","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"13","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"13","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"13","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"13","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}}}}} -{"strategy_protocol_version":"13","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"13","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"13","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"13","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"13","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"13","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v13/message.schema.json b/contracts/strategy/v13/message.schema.json deleted file mode 100644 index ac9b452..0000000 --- a/contracts/strategy/v13/message.schema.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v13/message.schema.json", - "title": "Trading Engine external strategy protocol v13 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "13" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "15" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/settlement" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "settled_quantity", "unsettled_quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" }, - "settled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" }, - "unsettled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v13/transcript.schema.json b/contracts/strategy/v13/transcript.schema.json deleted file mode 100644 index 031b51b..0000000 --- a/contracts/strategy/v13/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v13/transcript.schema.json", - "title": "Trading Engine external strategy protocol v13 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "13" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v13/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v14/README.md b/contracts/strategy/v14/README.md deleted file mode 100644 index 1164118..0000000 --- a/contracts/strategy/v14/README.md +++ /dev/null @@ -1,64 +0,0 @@ -# External strategy protocol v14 - -Version 14 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v13 remains available for scenario contract v15; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "14"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -Intent batches use the scenario v16 typed metric contract. `emit_metric.value` declares a numeric, -string, or boolean value, with optional unit, aggregation, and bounded dimensions. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v16 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars, nested execution configuration, financing policy, and settlement policy, so a strategy -can construct DAY orders and reject incompatible execution, financing, or settlement state before -replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices with effective-time borrow and cash-rate observations -plus explicit settlement failures, fills, order updates, and rejected intents. Portfolio contexts -include cash-interest attribution and settled and unsettled cash and position quantities. Response -intents use the scenario v16 intent shapes. Market-slice events include lifecycle transitions and -the expanded corporate-action catalog, plus causally ordered quote/trade market events. -Protocol v14 also carries bounded order-book snapshots and incrementals and advertises the -`order_book_v1` configuration, including its maximum depth. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v14/dune b/contracts/strategy/v14/dune deleted file mode 100644 index 999eb39..0000000 --- a/contracts/strategy/v14/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v14/message.schema.json) - (transcript.schema.json as contracts/strategy/v14/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v14/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v14/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v14/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v14/fixtures/external.scenario.json b/contracts/strategy/v14/fixtures/external.scenario.json deleted file mode 100644 index 9fa4d9c..0000000 --- a/contracts/strategy/v14/fixtures/external.scenario.json +++ /dev/null @@ -1,308 +0,0 @@ -{ - "contract_version": "16", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/strategy/v14/fixtures/external.scenario.jsonl b/contracts/strategy/v14/fixtures/external.scenario.jsonl deleted file mode 100644 index 894bf5a..0000000 --- a/contracts/strategy/v14/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"16","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"16","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"16","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"16","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v14/fixtures/external.strategy.jsonl b/contracts/strategy/v14/fixtures/external.strategy.jsonl deleted file mode 100644 index ceed5d3..0000000 --- a/contracts/strategy/v14/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"14","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"14","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"16","scenario_sha256":"6809a3638fe668a2a11e56c42e9bac7e506c0064eb2cb0a3e71ba09d92839ee7","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"14","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"14","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"14","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"14","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}}}}} -{"strategy_protocol_version":"14","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"14","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":{"type":"numeric","value":"2"},"unit":"score","dimensions":{"source":"fixture"},"aggregation":"last"}]}}} -{"strategy_protocol_version":"14","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"14","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"14","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"14","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"14","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"14","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"14","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"14","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"14","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"14","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"14","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"14","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"14","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"14","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}}}}} -{"strategy_protocol_version":"14","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"14","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"14","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"14","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"14","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"14","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v14/message.schema.json b/contracts/strategy/v14/message.schema.json deleted file mode 100644 index 97d8a98..0000000 --- a/contracts/strategy/v14/message.schema.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v14/message.schema.json", - "title": "Trading Engine external strategy protocol v14 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "14" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "16" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/settlement" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "settled_quantity", "unsettled_quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" }, - "settled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" }, - "unsettled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v14/transcript.schema.json b/contracts/strategy/v14/transcript.schema.json deleted file mode 100644 index 4635866..0000000 --- a/contracts/strategy/v14/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v14/transcript.schema.json", - "title": "Trading Engine external strategy protocol v14 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "14" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v14/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v2/README.md b/contracts/strategy/v2/README.md deleted file mode 100644 index 0420e34..0000000 --- a/contracts/strategy/v2/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# External strategy protocol v2 - -Version 2 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. - -Every message repeats `strategy_protocol_version: "2"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, all working orders, -and the latest available bar for each instrument. The portfolio reports cash, equity, net, long, -short, and gross market value plus every attributed cash ledger and configured position. Position -quantities and weights reflect applied fills. Weights are truncated toward zero to six decimal -places. `weights_available` is false and all weights are null when equity is zero or negative. -Event payloads cover completed market slices, fills, order updates, and rejected intents. Response -intents use the scenario v3 intent shapes. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records both directions in a deterministic transcript. The transcript and audit journal retain -partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates retained transcript records. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v2/dune b/contracts/strategy/v2/dune deleted file mode 100644 index cd3cf5a..0000000 --- a/contracts/strategy/v2/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v2/message.schema.json) - (transcript.schema.json as contracts/strategy/v2/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v2/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v2/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v2/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v2/fixtures/external.scenario.json b/contracts/strategy/v2/fixtures/external.scenario.json deleted file mode 100644 index 5fe2d5a..0000000 --- a/contracts/strategy/v2/fixtures/external.scenario.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "contract_version": "3", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "10000" } - ], - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000", - "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 0 - }, - "execution": { - "model": "completed_bar_v1", - "participation_bps": 10000, - "fixed_fee": "0", - "fee_bps": 0 - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "100", "high": "105", "low": "99", "close": "104", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "103", "high": "108", "low": "102", "close": "107", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - } - ] -} diff --git a/contracts/strategy/v2/fixtures/external.scenario.jsonl b/contracts/strategy/v2/fixtures/external.scenario.jsonl deleted file mode 100644 index 1e168bf..0000000 --- a/contracts/strategy/v2/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"3","payload":{"base_currency":"USD","execution":{"fee_bps":0,"fixed_fee":"0","model":"completed_bar_v1","participation_bps":10000},"initial_cash":[{"amount":"10000","currency":"USD"}],"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"max_internal_events":1000,"metadata":{"producer":"strategy-protocol-fixture"},"risk":{"initial_margin_bps":5000,"maintenance_margin_bps":2500,"max_gross_exposure":"1000000","max_leverage":"2","max_long_position":"1000","max_order_quantity":"1000","max_short_position":"1000","short_borrow_bps":0},"run_id":"external-demo"},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"3","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v2/fixtures/external.strategy.jsonl b/contracts/strategy/v2/fixtures/external.strategy.jsonl deleted file mode 100644 index de2b8e7..0000000 --- a/contracts/strategy/v2/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"2","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"2","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"0.1.0-dev","scenario_contract_version":"3","scenario_sha256":"78df448f65b0d784d51951108cacb1db247d9d2dd03d93886f43e4acc0e83e1d","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_gross_exposure":"1000000","max_leverage":"2","initial_margin_bps":5000,"maintenance_margin_bps":2500,"short_borrow_bps":0},"execution":{"model":"completed_bar_v1","participation_bps":10000,"fixed_fee":"0","fee_bps":0},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"2","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"2","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"2","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"2","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"2","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"2","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"2","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"2","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"2","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"2","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"2","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"2","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9794","net_market_value":"208","long_market_value":"208","short_market_value":"0","gross_exposure":"208","equity":"10002","weights_available":true,"cash_weight":"0.979204","cash_balances":[{"currency":"USD","amount":"9794","fx_rate":"1","base_value":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"104","base_market_value":"208","weight":"0.020795"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}}}}} -{"strategy_protocol_version":"2","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"2","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"2","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"2","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9794","net_market_value":"208","long_market_value":"208","short_market_value":"0","gross_exposure":"208","equity":"10002","weights_available":true,"cash_weight":"0.979204","cash_balances":[{"currency":"USD","amount":"9794","fx_rate":"1","base_value":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"104","base_market_value":"208","weight":"0.020795"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"2","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"2","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"2","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"2","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9794","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10008","weights_available":true,"cash_weight":"0.978617","cash_balances":[{"currency":"USD","amount":"9794","fx_rate":"1","base_value":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021382"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"2","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"2","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"2","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"2","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"2","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"2","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v2/message.schema.json b/contracts/strategy/v2/message.schema.json deleted file mode 100644 index a3f9dee..0000000 --- a/contracts/strategy/v2/message.schema.json +++ /dev/null @@ -1,282 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v2/message.schema.json", - "title": "Trading Engine external strategy protocol v2 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "2" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "type": "string", "minLength": 1 }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/cashBalance" } - }, - "instruments": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/instrument" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/execution" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v2/transcript.schema.json b/contracts/strategy/v2/transcript.schema.json deleted file mode 100644 index bf84b7b..0000000 --- a/contracts/strategy/v2/transcript.schema.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v2/transcript.schema.json", - "title": "Trading Engine external strategy protocol v2 transcript record", - "description": "One ordered request or response retained from a supervised stdio strategy session.", - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "2" }, - "transcript_sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v2/message.schema.json" - } - } -} diff --git a/contracts/strategy/v3/README.md b/contracts/strategy/v3/README.md deleted file mode 100644 index ccaad1b..0000000 --- a/contracts/strategy/v3/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# External strategy protocol v3 - -Version 3 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. - -Every message repeats `strategy_protocol_version: "3"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, all working orders, -and the latest available bar for each instrument. Every callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices, fills, order updates, and rejected intents. Response -intents use the scenario v3 intent shapes. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v3/dune b/contracts/strategy/v3/dune deleted file mode 100644 index ec57607..0000000 --- a/contracts/strategy/v3/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v3/message.schema.json) - (transcript.schema.json as contracts/strategy/v3/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v3/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v3/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v3/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v3/fixtures/external.scenario.json b/contracts/strategy/v3/fixtures/external.scenario.json deleted file mode 100644 index 5fe2d5a..0000000 --- a/contracts/strategy/v3/fixtures/external.scenario.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "contract_version": "3", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "10000" } - ], - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000", - "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 0 - }, - "execution": { - "model": "completed_bar_v1", - "participation_bps": 10000, - "fixed_fee": "0", - "fee_bps": 0 - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "100", "high": "105", "low": "99", "close": "104", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "103", "high": "108", "low": "102", "close": "107", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - } - ] -} diff --git a/contracts/strategy/v3/fixtures/external.scenario.jsonl b/contracts/strategy/v3/fixtures/external.scenario.jsonl deleted file mode 100644 index 1e168bf..0000000 --- a/contracts/strategy/v3/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"3","payload":{"base_currency":"USD","execution":{"fee_bps":0,"fixed_fee":"0","model":"completed_bar_v1","participation_bps":10000},"initial_cash":[{"amount":"10000","currency":"USD"}],"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"max_internal_events":1000,"metadata":{"producer":"strategy-protocol-fixture"},"risk":{"initial_margin_bps":5000,"maintenance_margin_bps":2500,"max_gross_exposure":"1000000","max_leverage":"2","max_long_position":"1000","max_order_quantity":"1000","max_short_position":"1000","short_borrow_bps":0},"run_id":"external-demo"},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"3","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v3/fixtures/external.strategy.jsonl b/contracts/strategy/v3/fixtures/external.strategy.jsonl deleted file mode 100644 index 6839dc6..0000000 --- a/contracts/strategy/v3/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"3","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"3","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"3","scenario_sha256":"78df448f65b0d784d51951108cacb1db247d9d2dd03d93886f43e4acc0e83e1d","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_gross_exposure":"1000000","max_leverage":"2","initial_margin_bps":5000,"maintenance_margin_bps":2500,"short_borrow_bps":0},"execution":{"model":"completed_bar_v1","participation_bps":10000,"fixed_fee":"0","fee_bps":0},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"3","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"3","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"3","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"3","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"3","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"3","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"3","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"3","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"3","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"3","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"3","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"3","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9794","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10008","weights_available":true,"cash_weight":"0.978617","cash_balances":[{"currency":"USD","amount":"9794","fx_rate":"1","base_value":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021382"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}}}}} -{"strategy_protocol_version":"3","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"3","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"3","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"3","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9794","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10008","weights_available":true,"cash_weight":"0.978617","cash_balances":[{"currency":"USD","amount":"9794","fx_rate":"1","base_value":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021382"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000005","updated_event_id":"external-demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"3","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"3","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"3","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"3","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9794","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10008","weights_available":true,"cash_weight":"0.978617","cash_balances":[{"currency":"USD","amount":"9794","fx_rate":"1","base_value":"9794"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021382"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"3","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"3","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"3","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"3","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"3","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"3","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v3/message.schema.json b/contracts/strategy/v3/message.schema.json deleted file mode 100644 index 75e0ce4..0000000 --- a/contracts/strategy/v3/message.schema.json +++ /dev/null @@ -1,284 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v3/message.schema.json", - "title": "Trading Engine external strategy protocol v3 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "3" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "type": "string", "minLength": 1 }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/cashBalance" } - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/instrument" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/execution" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v3/transcript.schema.json b/contracts/strategy/v3/transcript.schema.json deleted file mode 100644 index 0ecb931..0000000 --- a/contracts/strategy/v3/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v3/transcript.schema.json", - "title": "Trading Engine external strategy protocol v3 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "3" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v3/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v4/README.md b/contracts/strategy/v4/README.md deleted file mode 100644 index 1883476..0000000 --- a/contracts/strategy/v4/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# External strategy protocol v4 - -Version 4 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v3 remains available for legacy scenario contracts and retains its frozen message and -transcript shapes. - -Every message repeats `strategy_protocol_version: "4"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, all working orders, -and the latest available bar for each instrument. Every callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v6 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the nested, versioned execution -configuration, so a strategy can reject incompatible state before replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices, fills, order updates, and rejected intents. Response -intents use the scenario v6 intent shapes. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v4/dune b/contracts/strategy/v4/dune deleted file mode 100644 index b1b6030..0000000 --- a/contracts/strategy/v4/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v4/message.schema.json) - (transcript.schema.json as contracts/strategy/v4/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v4/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v4/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v4/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v4/fixtures/external.scenario.json b/contracts/strategy/v4/fixtures/external.scenario.json deleted file mode 100644 index 3a0e07b..0000000 --- a/contracts/strategy/v4/fixtures/external.scenario.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "contract_version": "6", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000", - "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 0 - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/strategy/v4/fixtures/external.scenario.jsonl b/contracts/strategy/v4/fixtures/external.scenario.jsonl deleted file mode 100644 index 2048f33..0000000 --- a/contracts/strategy/v4/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"6","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"amount":"10000","currency":"USD"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"initial_margin_bps":5000,"maintenance_margin_bps":2500,"max_gross_exposure":"1000000","max_leverage":"2","max_long_position":"1000","max_order_quantity":"1000","max_short_position":"1000","short_borrow_bps":0},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"max_internal_events":1000},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"6","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"6","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"6","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v4/fixtures/external.strategy.jsonl b/contracts/strategy/v4/fixtures/external.strategy.jsonl deleted file mode 100644 index fd78fc4..0000000 --- a/contracts/strategy/v4/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"4","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"4","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"6","scenario_sha256":"1faa37778736b022309ffc290658161f9e97bb6f7492c7083045922998f237f5","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_gross_exposure":"1000000","max_leverage":"2","initial_margin_bps":5000,"maintenance_margin_bps":2500,"short_borrow_bps":0},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"4","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"4","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"4","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"4","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"4","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"4","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"4","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"4","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"4","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"4","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"4","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"4","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}}}}} -{"strategy_protocol_version":"4","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"4","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"4","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"4","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"4","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"4","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"4","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"4","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"4","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"4","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"4","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"4","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"4","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"4","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v4/message.schema.json b/contracts/strategy/v4/message.schema.json deleted file mode 100644 index cb3c259..0000000 --- a/contracts/strategy/v4/message.schema.json +++ /dev/null @@ -1,290 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v4/message.schema.json", - "title": "Trading Engine external strategy protocol v4 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "4" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "risk", "execution", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "6" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/instrument" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/execution" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v4/transcript.schema.json b/contracts/strategy/v4/transcript.schema.json deleted file mode 100644 index 0602db3..0000000 --- a/contracts/strategy/v4/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v4/transcript.schema.json", - "title": "Trading Engine external strategy protocol v4 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "4" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v4/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v5/README.md b/contracts/strategy/v5/README.md deleted file mode 100644 index d5da556..0000000 --- a/contracts/strategy/v5/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# External strategy protocol v5 - -Version 5 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocols v4 and v3 remain available for legacy scenario contracts and retain their frozen shapes. - -Every message repeats `strategy_protocol_version: "5"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v7 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the nested, versioned execution -configuration, so a strategy can reject incompatible state before replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices, fills, order updates, and rejected intents. Response -intents use the scenario v7 intent shapes. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v5/dune b/contracts/strategy/v5/dune deleted file mode 100644 index 3f3d97d..0000000 --- a/contracts/strategy/v5/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v5/message.schema.json) - (transcript.schema.json as contracts/strategy/v5/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v5/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v5/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v5/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v5/fixtures/external.scenario.json b/contracts/strategy/v5/fixtures/external.scenario.json deleted file mode 100644 index 7a4da01..0000000 --- a/contracts/strategy/v5/fixtures/external.scenario.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "contract_version": "7", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/strategy/v5/fixtures/external.scenario.jsonl b/contracts/strategy/v5/fixtures/external.scenario.jsonl deleted file mode 100644 index 83383a9..0000000 --- a/contracts/strategy/v5/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"7","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"amount":"10000","currency":"USD"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"max_internal_events":1000},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"7","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"7","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"7","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v5/fixtures/external.strategy.jsonl b/contracts/strategy/v5/fixtures/external.strategy.jsonl deleted file mode 100644 index d24e191..0000000 --- a/contracts/strategy/v5/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"5","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"5","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"7","scenario_sha256":"006cea48630b4cd06e7e3908de78065e931c069cac90ae04d2567f20896d413b","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"5","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"5","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"5","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"5","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"5","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"5","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"5","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"5","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"5","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"5","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"5","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"5","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}}}}} -{"strategy_protocol_version":"5","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"5","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"5","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"5","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"5","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"5","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"5","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"5","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"5","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"5","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"5","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"5","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"5","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"5","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v5/message.schema.json b/contracts/strategy/v5/message.schema.json deleted file mode 100644 index 1e49290..0000000 --- a/contracts/strategy/v5/message.schema.json +++ /dev/null @@ -1,294 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v5/message.schema.json", - "title": "Trading Engine external strategy protocol v5 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "5" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "risk", "execution", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "7" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/instrument" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/execution" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v5/transcript.schema.json b/contracts/strategy/v5/transcript.schema.json deleted file mode 100644 index cc6fba1..0000000 --- a/contracts/strategy/v5/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v5/transcript.schema.json", - "title": "Trading Engine external strategy protocol v5 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "5" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v5/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v6/README.md b/contracts/strategy/v6/README.md deleted file mode 100644 index c0cd6b1..0000000 --- a/contracts/strategy/v6/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# External strategy protocol v6 - -Version 6 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocols v4 and v3 remain available for legacy scenario contracts and retain their frozen shapes. - -Every message repeats `strategy_protocol_version: "6"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v8 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars and nested execution configuration, so a strategy can construct DAY orders and reject -incompatible state before replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices, fills, order updates, and rejected intents. Response -intents use the scenario v8 intent shapes. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v6/dune b/contracts/strategy/v6/dune deleted file mode 100644 index 626dd76..0000000 --- a/contracts/strategy/v6/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v6/message.schema.json) - (transcript.schema.json as contracts/strategy/v6/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v6/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v6/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v6/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v6/fixtures/external.scenario.json b/contracts/strategy/v6/fixtures/external.scenario.json deleted file mode 100644 index 1cd0108..0000000 --- a/contracts/strategy/v6/fixtures/external.scenario.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "contract_version": "8", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/strategy/v6/fixtures/external.scenario.jsonl b/contracts/strategy/v6/fixtures/external.scenario.jsonl deleted file mode 100644 index 6c1f91c..0000000 --- a/contracts/strategy/v6/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"8","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"amount":"10000","currency":"USD"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"max_internal_events":1000},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"8","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"8","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"8","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v6/fixtures/external.strategy.jsonl b/contracts/strategy/v6/fixtures/external.strategy.jsonl deleted file mode 100644 index 6bb8ac8..0000000 --- a/contracts/strategy/v6/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"6","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"6","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"8","scenario_sha256":"9399ec91936b6beff0701c5b730188f238921203553f6f4c1d9d92dc77110afe","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"6","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"6","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"6","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"6","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"6","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"6","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"6","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"6","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"6","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"6","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"6","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"6","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}}}}} -{"strategy_protocol_version":"6","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"6","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"6","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"6","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"6","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"6","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"6","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"6","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"6","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"6","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"6","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"6","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"6","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"6","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v6/message.schema.json b/contracts/strategy/v6/message.schema.json deleted file mode 100644 index 143e284..0000000 --- a/contracts/strategy/v6/message.schema.json +++ /dev/null @@ -1,298 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v6/message.schema.json", - "title": "Trading Engine external strategy protocol v6 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "6" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "8" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/execution" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v6/transcript.schema.json b/contracts/strategy/v6/transcript.schema.json deleted file mode 100644 index 3ec1993..0000000 --- a/contracts/strategy/v6/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v6/transcript.schema.json", - "title": "Trading Engine external strategy protocol v6 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "6" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v6/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v7/README.md b/contracts/strategy/v7/README.md deleted file mode 100644 index 8f89470..0000000 --- a/contracts/strategy/v7/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# External strategy protocol v7 - -Version 7 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v6 remains available for scenario contract v8; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "7"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v9 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars and nested execution configuration, so a strategy can construct DAY orders and reject -incompatible state before replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices, fills, order updates, and rejected intents. Response -intents use the scenario v9 intent shapes. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v7/dune b/contracts/strategy/v7/dune deleted file mode 100644 index fdc117e..0000000 --- a/contracts/strategy/v7/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v7/message.schema.json) - (transcript.schema.json as contracts/strategy/v7/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v7/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v7/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v7/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v7/fixtures/external.scenario.json b/contracts/strategy/v7/fixtures/external.scenario.json deleted file mode 100644 index 75f84da..0000000 --- a/contracts/strategy/v7/fixtures/external.scenario.json +++ /dev/null @@ -1,215 +0,0 @@ -{ - "contract_version": "9", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { "name": "broker", "currency": "USD", "kind": "fixed", "value": "0.25", "rounding": "up", "applies_to": "any" }, - { "name": "exchange", "currency": "USD", "kind": "notional_bps", "value": 10, "rounding": "up", "applies_to": "any" } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/strategy/v7/fixtures/external.scenario.jsonl b/contracts/strategy/v7/fixtures/external.scenario.jsonl deleted file mode 100644 index 34227d4..0000000 --- a/contracts/strategy/v7/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"9","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000}} -{"contract_version":"9","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"9","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"9","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v7/fixtures/external.strategy.jsonl b/contracts/strategy/v7/fixtures/external.strategy.jsonl deleted file mode 100644 index 85cdd80..0000000 --- a/contracts/strategy/v7/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"7","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"7","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"9","scenario_sha256":"46f4461cb699182509ef3f7a637cf5a8b33781252da7967a50e7af32399f402e","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"7","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"7","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"7","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"7","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"7","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"7","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"7","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"7","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"7","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"7","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"7","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"7","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"7","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"7","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"7","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"7","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"7","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"7","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"7","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"7","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}}}}} -{"strategy_protocol_version":"7","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"7","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"7","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"7","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"7","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"7","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v7/message.schema.json b/contracts/strategy/v7/message.schema.json deleted file mode 100644 index 7939e75..0000000 --- a/contracts/strategy/v7/message.schema.json +++ /dev/null @@ -1,299 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v7/message.schema.json", - "title": "Trading Engine external strategy protocol v7 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "7" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "9" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/execution" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} - diff --git a/contracts/strategy/v7/transcript.schema.json b/contracts/strategy/v7/transcript.schema.json deleted file mode 100644 index 03891d3..0000000 --- a/contracts/strategy/v7/transcript.schema.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v7/transcript.schema.json", - "title": "Trading Engine external strategy protocol v7 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "7" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v7/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} - diff --git a/contracts/strategy/v8/README.md b/contracts/strategy/v8/README.md deleted file mode 100644 index 5669e19..0000000 --- a/contracts/strategy/v8/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# External strategy protocol v8 - -Version 8 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v7 remains available for scenario contract v9; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "8"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v10 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars, nested execution configuration, and financing policy, so a strategy can construct DAY -orders and reject incompatible execution or financing state before replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices with effective-time borrow and cash-rate observations, -fills, order updates, and rejected intents. Portfolio contexts include cash-interest attribution. -Response intents use the scenario v10 intent shapes, including recall-origin order snapshots. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v8/dune b/contracts/strategy/v8/dune deleted file mode 100644 index c613fc4..0000000 --- a/contracts/strategy/v8/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v8/message.schema.json) - (transcript.schema.json as contracts/strategy/v8/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v8/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v8/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v8/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v8/fixtures/external.scenario.json b/contracts/strategy/v8/fixtures/external.scenario.json deleted file mode 100644 index e52dd61..0000000 --- a/contracts/strategy/v8/fixtures/external.scenario.json +++ /dev/null @@ -1,271 +0,0 @@ -{ - "contract_version": "10", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - } -} diff --git a/contracts/strategy/v8/fixtures/external.scenario.jsonl b/contracts/strategy/v8/fixtures/external.scenario.jsonl deleted file mode 100644 index d89b702..0000000 --- a/contracts/strategy/v8/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"10","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"}}} -{"contract_version":"10","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"10","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"10","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v8/fixtures/external.strategy.jsonl b/contracts/strategy/v8/fixtures/external.strategy.jsonl deleted file mode 100644 index 9622950..0000000 --- a/contracts/strategy/v8/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"8","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"8","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"10","scenario_sha256":"008026ed55d30ccabe95d2bb95a843b7631e00ddde2874155459717b53823c5f","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"8","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"8","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"8","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"8","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}]}}}}} -{"strategy_protocol_version":"8","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"8","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"8","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"8","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"8","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"8","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"8","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"8","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"8","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"8","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"8","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"8","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"8","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"8","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"8","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"8","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}]}}}}} -{"strategy_protocol_version":"8","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"8","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"8","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"8","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"8","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"8","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v8/message.schema.json b/contracts/strategy/v8/message.schema.json deleted file mode 100644 index dacc035..0000000 --- a/contracts/strategy/v8/message.schema.json +++ /dev/null @@ -1,299 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v8/message.schema.json", - "title": "Trading Engine external strategy protocol v8 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "8" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "10" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/financing" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v8/transcript.schema.json b/contracts/strategy/v8/transcript.schema.json deleted file mode 100644 index 8c66867..0000000 --- a/contracts/strategy/v8/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v8/transcript.schema.json", - "title": "Trading Engine external strategy protocol v8 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "8" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v8/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/strategy/v9/README.md b/contracts/strategy/v9/README.md deleted file mode 100644 index c449032..0000000 --- a/contracts/strategy/v9/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# External strategy protocol v9 - -Version 9 is a synchronous JSON Lines protocol over child-process standard input and output. -Trading Engine sends `initialize`, ordered `event` requests, and `shutdown`. The strategy answers -with `ready`, `intents`, and `stopped`. It may answer any request with `error`. -Protocol v8 remains available for scenario contract v10; earlier versions retain their frozen -shapes. - -Every message repeats `strategy_protocol_version: "9"` and a positive canonical -`strategy_sequence`. A response must repeat the sequence of its request. Only one request is -outstanding. Trading Engine rejects unknown or duplicate fields, invalid canonical values, -oversized lines, a wrong version or sequence, unexpected response types, EOF, timeout, and a -nonzero process exit. - -The event context contains the replay clock, a marked base-currency portfolio, deterministic group -exposure snapshots, all working orders, and the latest available bar for each instrument. Every -callback emitted for a market slice uses -that slice's `received_at` as `now` and uses its complete bars and FX vector. The portfolio reports -cash, equity, net, long, short, and gross market value plus every attributed cash ledger and -configured position. Position quantities and weights reflect applied fills. Weights are truncated -toward zero to six decimal places. `weights_available` is false and all weights are null when -equity is zero or negative. - -The `initialize` request identifies scenario contract v11 and includes the exact `initial_portfolio` -snapshot alongside the legacy cash projection. It also carries the complete versioned venue -calendars, nested execution configuration, financing policy, and settlement policy, so a strategy -can construct DAY orders and reject incompatible execution, financing, or settlement state before -replay. - -Matching pauses after each strategy callback. The engine applies the response against the exact -account and OMS state exposed by that callback before delivering another callback or considering -the next eligible order. Later same-slice contexts include the effects of earlier responses. The -eligible-order sequence is fixed at the start of matching, so newly submitted orders wait for a -later slice. Cancelling an order before its turn leaves its unused slice capacity available to the -next eligible order. - -Event payloads cover completed market slices with effective-time borrow and cash-rate observations -plus explicit settlement failures, fills, order updates, and rejected intents. Portfolio contexts -include cash-interest attribution and settled and unsettled cash and position quantities. Response -intents use the scenario v11 intent shapes, including recall-origin order snapshots. - -External replay requires an empty batch schedule and empty streamed intent batches. The engine -records accepted messages in both directions in a deterministic transcript. A response rejected -for invalid JSON, fields, version, sequence, EOF, or size is never stored as an accepted exchange. -Instead, the partial transcript ends with a `rejected_strategy_response` diagnostic record. Version -1 rejection diagnostics use the shared -[`diagnostic/v1`](../../diagnostic/v1/README.md) contract. The transcript schema narrows that -contract to the `strategy.protocol` and `resource.limit` codes in the `strategy` phase. The record -includes the structured rejection diagnostic and at most the first 256 raw response bytes encoded -as lowercase hexadecimal. `observed_bytes` counts bytes available when the engine rejected the -response, and `truncated` reports whether the prefix omits observed bytes. The transcript and audit -journal retain partial files after failure and finalize only after their respective success checks. - -- `message.schema.json` validates individual requests and responses. -- `transcript.schema.json` validates accepted exchanges and rejected-response diagnostics. -- `fixtures/external.scenario.json` is the batch replay fixture. -- `fixtures/external.scenario.jsonl` is its bounded-memory stream form. -- `fixtures/external.strategy.jsonl` is the canonical protocol transcript. diff --git a/contracts/strategy/v9/dune b/contracts/strategy/v9/dune deleted file mode 100644 index 8354cc5..0000000 --- a/contracts/strategy/v9/dune +++ /dev/null @@ -1,15 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (message.schema.json as contracts/strategy/v9/message.schema.json) - (transcript.schema.json as contracts/strategy/v9/transcript.schema.json) - (fixtures/external.scenario.json - as - contracts/strategy/v9/fixtures/external.scenario.json) - (fixtures/external.scenario.jsonl - as - contracts/strategy/v9/fixtures/external.scenario.jsonl) - (fixtures/external.strategy.jsonl - as - contracts/strategy/v9/fixtures/external.strategy.jsonl))) diff --git a/contracts/strategy/v9/fixtures/external.scenario.json b/contracts/strategy/v9/fixtures/external.scenario.json deleted file mode 100644 index 7d1a4a8..0000000 --- a/contracts/strategy/v9/fixtures/external.scenario.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "contract_version": "11", - "metadata": { - "producer": "strategy-protocol-fixture" - }, - "run_id": "external-demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 0, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "external-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 0, - "debit_rate_bps": 0 - } - ], - "settlement_failures": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/strategy/v9/fixtures/external.scenario.jsonl b/contracts/strategy/v9/fixtures/external.scenario.jsonl deleted file mode 100644 index 605761a..0000000 --- a/contracts/strategy/v9/fixtures/external.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"11","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"strategy-protocol-fixture"},"run_id":"external-demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"11","payload":{"intents":[],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"11","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"11","payload":{"slice_count":"2"},"record_type":"scenario_end","scenario_sequence":"4"} diff --git a/contracts/strategy/v9/fixtures/external.strategy.jsonl b/contracts/strategy/v9/fixtures/external.strategy.jsonl deleted file mode 100644 index 0875b1b..0000000 --- a/contracts/strategy/v9/fixtures/external.strategy.jsonl +++ /dev/null @@ -1,14 +0,0 @@ -{"strategy_protocol_version":"9","transcript_sequence":"1","direction":"engine_to_strategy","message":{"strategy_protocol_version":"9","strategy_sequence":"1","message_type":"initialize","payload":{"engine_version":"1.0.0","scenario_contract_version":"11","scenario_sha256":"d9b389a906984af1e3170e94863884a938b5c8b86025b1ccc1708e9896520278","run_id":"external-demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00.000000Z","closes_at":"2026-01-02T14:25:00.000000Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00.000000Z","closes_at":"2026-01-02T14:30:00.000000Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00.000000Z","closes_at":"2026-01-02T20:55:00.000000Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00.000000Z","closes_at":"2026-01-02T21:00:00.000000Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00.000000Z","closes_at":"2026-01-03T01:00:00.000000Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00.000000Z","closes_at":"2026-01-05T21:00:00.000000Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00.000000Z","closes_at":"2026-01-06T21:00:00.000000Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00.000000Z","closes_at":"2026-01-07T21:00:00.000000Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00.000000Z","closes_at":"2026-01-08T18:00:00.000000Z"}]}]}],"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":0,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"external-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"any"}]}]}},"metadata":{"producer":"strategy-protocol-fixture"}}}} -{"strategy_protocol_version":"9","transcript_sequence":"2","direction":"strategy_to_engine","message":{"strategy_protocol_version":"9","strategy_sequence":"1","message_type":"ready","payload":{"strategy_name":"fixture-strategy","strategy_version":"1"}}} -{"strategy_protocol_version":"9","transcript_sequence":"3","direction":"engine_to_strategy","message":{"strategy_protocol_version":"9","strategy_sequence":"2","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[]}}}}} -{"strategy_protocol_version":"9","transcript_sequence":"4","direction":"strategy_to_engine","message":{"strategy_protocol_version":"9","strategy_sequence":"2","message_type":"intents","payload":{"intents":[{"type":"target_quantities","targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}]},{"type":"emit_metric","name":"fixture_signal","value":"2"}]}}} -{"strategy_protocol_version":"9","transcript_sequence":"5","direction":"engine_to_strategy","message":{"strategy_protocol_version":"9","strategy_sequence":"3","message_type":"event","payload":{"context":{"now":"2026-01-02T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","equity":"10000","weights_available":true,"cash_weight":"1","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","base_market_value":"0","weight":"0","settled_quantity":"0","unsettled_quantity":"0"}],"group_exposures":[]},"working_orders":[{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}}}}} -{"strategy_protocol_version":"9","transcript_sequence":"6","direction":"strategy_to_engine","message":{"strategy_protocol_version":"9","strategy_sequence":"3","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"9","transcript_sequence":"7","direction":"engine_to_strategy","message":{"strategy_protocol_version":"9","strategy_sequence":"4","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"fill_received","fill":{"fill_id":"external-demo-fill-000000000001","order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2","price":"103","notional":"206","fee":"0.456","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.206","quote_amount":"0.206"}]}}}}} -{"strategy_protocol_version":"9","transcript_sequence":"8","direction":"strategy_to_engine","message":{"strategy_protocol_version":"9","strategy_sequence":"4","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"9","transcript_sequence":"9","direction":"engine_to_strategy","message":{"strategy_protocol_version":"9","strategy_sequence":"5","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"order_updated","order":{"order_id":"external-demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"2","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"external-demo-event-000000000007","updated_event_id":"external-demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"2","filled_notional":"206","status":"filled","rejection_reason":null}}}}} -{"strategy_protocol_version":"9","transcript_sequence":"10","direction":"strategy_to_engine","message":{"strategy_protocol_version":"9","strategy_sequence":"5","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"9","transcript_sequence":"11","direction":"engine_to_strategy","message":{"strategy_protocol_version":"9","strategy_sequence":"6","message_type":"event","payload":{"context":{"now":"2026-01-05T21:00:02.000000Z","portfolio":{"base_currency":"USD","cash":"9793.544","net_market_value":"214","long_market_value":"214","short_market_value":"0","gross_exposure":"214","equity":"10007.544","weights_available":true,"cash_weight":"0.978616","cash_balances":[{"currency":"USD","amount":"9793.544","fx_rate":"1","base_value":"9793.544","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"-206.456","base_settled_value":"10000","base_unsettled_value":"-206.456"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"107","base_market_value":"214","weight":"0.021383","settled_quantity":"0","unsettled_quantity":"2"}],"group_exposures":[]},"working_orders":[],"latest_bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}]},"event":{"type":"market_slice_closed","market_slice":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":0,"debit_rate_bps":0}],"settlement_failures":[]}}}}} -{"strategy_protocol_version":"9","transcript_sequence":"12","direction":"strategy_to_engine","message":{"strategy_protocol_version":"9","strategy_sequence":"6","message_type":"intents","payload":{"intents":[]}}} -{"strategy_protocol_version":"9","transcript_sequence":"13","direction":"engine_to_strategy","message":{"strategy_protocol_version":"9","strategy_sequence":"7","message_type":"shutdown","payload":{}}} -{"strategy_protocol_version":"9","transcript_sequence":"14","direction":"strategy_to_engine","message":{"strategy_protocol_version":"9","strategy_sequence":"7","message_type":"stopped","payload":{}}} diff --git a/contracts/strategy/v9/message.schema.json b/contracts/strategy/v9/message.schema.json deleted file mode 100644 index 3962824..0000000 --- a/contracts/strategy/v9/message.schema.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v9/message.schema.json", - "title": "Trading Engine external strategy protocol v9 message", - "description": "One strict request or response in the synchronous JSON Lines strategy protocol. The engine additionally enforces direction, sequence pairing, canonical values, response limits, and lifecycle order.", - "oneOf": [ - { "$ref": "#/$defs/initialize" }, - { "$ref": "#/$defs/ready" }, - { "$ref": "#/$defs/event" }, - { "$ref": "#/$defs/intents" }, - { "$ref": "#/$defs/shutdown" }, - { "$ref": "#/$defs/stopped" }, - { "$ref": "#/$defs/error" } - ], - "$defs": { - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "base": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "strategy_sequence", "message_type", "payload"], - "properties": { - "strategy_protocol_version": { "const": "9" }, - "strategy_sequence": { "$ref": "#/$defs/sequence" }, - "message_type": { "type": "string" }, - "payload": { "type": "object" } - } - }, - "initialize": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "initialize" }, - "payload": { "$ref": "#/$defs/initializePayload" } - } - } - ] - }, - "initializePayload": { - "type": "object", - "additionalProperties": false, - "required": ["engine_version", "scenario_contract_version", "scenario_sha256", "run_id", "base_currency", "initial_cash", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "metadata"], - "properties": { - "engine_version": { "type": "string", "minLength": 1 }, - "scenario_contract_version": { "const": "11" }, - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/cashBalance" } - }, - "initial_portfolio": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/initialPortfolio" } - ] - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/venueCalendar" } - }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/settlement" }, - "metadata": { "type": "object" } - } - }, - "ready": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "ready" }, - "payload": { "$ref": "#/$defs/readyPayload" } - } - } - ] - }, - "readyPayload": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_name", "strategy_version"], - "properties": { - "strategy_name": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/identifier" }, - "strategy_version": { - "oneOf": [ - { "type": "null" }, - { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - ] - } - } - }, - "event": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "event" }, - "payload": { "$ref": "#/$defs/eventPayload" } - } - } - ] - }, - "eventPayload": { - "type": "object", - "additionalProperties": false, - "required": ["context", "event"], - "properties": { - "context": { "$ref": "#/$defs/context" }, - "event": { "$ref": "#/$defs/strategyEvent" } - } - }, - "context": { - "type": "object", - "additionalProperties": false, - "required": ["now", "portfolio", "working_orders", "latest_bars"], - "properties": { - "now": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/timestamp" }, - "portfolio": { "$ref": "#/$defs/portfolio" }, - "working_orders": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/journal.schema.json#/$defs/order" } - }, - "latest_bars": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/bar" } - } - } - }, - "portfolio": { - "type": "object", - "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "equity", "weights_available", "cash_weight", "cash_balances", "positions", "group_exposures"], - "properties": { - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/identifier" }, - "cash": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" }, - "net_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" }, - "long_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/unsignedDecimal" }, - "short_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/unsignedDecimal" }, - "gross_exposure": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/unsignedDecimal" }, - "equity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" }, - "weights_available": { "type": "boolean" }, - "cash_weight": { "$ref": "#/$defs/optionalWeight" }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/journal.schema.json#/$defs/cashAttribution" } - }, - "positions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/markedPosition" } - }, - "group_exposures": { - "type": "array", - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/journal.schema.json#/$defs/groupExposure" } - } - } - }, - "optionalWeight": { - "oneOf": [ - { "type": "null" }, - { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" } - ] - }, - "markedPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "settled_quantity", "unsettled_quantity", "mark", "base_market_value", "weight"], - "properties": { - "instrument_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/identifier" }, - "quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" }, - "settled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" }, - "unsettled_quantity": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" }, - "mark": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/positiveDecimal" }, - "base_market_value": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/signedDecimal" }, - "weight": { "$ref": "#/$defs/optionalWeight" } - } - }, - "strategyEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "market_slice"], - "properties": { - "type": { "const": "market_slice_closed" }, - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/marketSlice" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "fill"], - "properties": { - "type": { "const": "fill_received" }, - "fill": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/journal.schema.json#/$defs/fill" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "order"], - "properties": { - "type": { "const": "order_updated" }, - "order": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/journal.schema.json#/$defs/order" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "reason"], - "properties": { - "type": { "const": "intent_rejected" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - }, - "intents": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "intents" }, - "payload": { "$ref": "#/$defs/intentsPayload" } - } - } - ] - }, - "intentsPayload": { - "type": "object", - "additionalProperties": false, - "required": ["intents"], - "properties": { - "intents": { - "type": "array", - "maxItems": 4096, - "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/intent" } - } - } - }, - "shutdown": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "shutdown" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "stopped": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "stopped" }, - "payload": { "$ref": "#/$defs/emptyPayload" } - } - } - ] - }, - "emptyPayload": { - "type": "object", - "additionalProperties": false, - "maxProperties": 0 - }, - "error": { - "allOf": [ - { "$ref": "#/$defs/base" }, - { - "properties": { - "message_type": { "const": "error" }, - "payload": { "$ref": "#/$defs/errorPayload" } - } - } - ] - }, - "errorPayload": { - "type": "object", - "additionalProperties": false, - "required": ["message"], - "properties": { - "message": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - } - } -} diff --git a/contracts/strategy/v9/transcript.schema.json b/contracts/strategy/v9/transcript.schema.json deleted file mode 100644 index 8b8fc95..0000000 --- a/contracts/strategy/v9/transcript.schema.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/strategy/v9/transcript.schema.json", - "title": "Trading Engine external strategy protocol v9 transcript record", - "description": "One accepted exchange or rejected-response diagnostic retained from a supervised stdio strategy session.", - "oneOf": [ - { "$ref": "#/$defs/exchange" }, - { "$ref": "#/$defs/rejectedResponse" } - ], - "$defs": { - "canonicalSequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "exchange": { - "type": "object", - "additionalProperties": false, - "required": ["strategy_protocol_version", "transcript_sequence", "direction", "message"], - "properties": { - "strategy_protocol_version": { "const": "9" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "direction": { - "enum": ["engine_to_strategy", "strategy_to_engine"] - }, - "message": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/strategy/v9/message.schema.json" - } - } - }, - "rejectedResponse": { - "type": "object", - "additionalProperties": false, - "required": [ - "strategy_diagnostic_version", - "transcript_sequence", - "record_type", - "expected_strategy_sequence", - "diagnostic", - "evidence" - ], - "properties": { - "strategy_diagnostic_version": { "const": "1" }, - "transcript_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "record_type": { "const": "rejected_strategy_response" }, - "expected_strategy_sequence": { "$ref": "#/$defs/canonicalSequence" }, - "diagnostic": { "$ref": "#/$defs/diagnostic" }, - "evidence": { "$ref": "#/$defs/evidence" } - } - }, - "diagnostic": { - "allOf": [ - { - "$ref": "https://github.com/fallblu/trading-engine/contracts/diagnostic/v1/diagnostic.schema.json" - }, - { - "properties": { - "code": { "enum": ["strategy.protocol", "resource.limit"] }, - "phase": { "const": "strategy" } - } - } - ] - }, - "evidence": { - "type": "object", - "additionalProperties": false, - "required": ["encoding", "prefix", "observed_bytes", "truncated"], - "properties": { - "encoding": { "const": "hex" }, - "prefix": { - "type": "string", - "pattern": "^(?:[0-9a-f]{2}){0,256}$" - }, - "observed_bytes": { - "type": "integer", - "minimum": 0, - "maximum": 1048577 - }, - "truncated": { "type": "boolean" } - } - } - } -} diff --git a/contracts/v1/README.md b/contracts/v1/README.md index e3bf5bb..0bd77e3 100644 --- a/contracts/v1/README.md +++ b/contracts/v1/README.md @@ -1,15 +1,19 @@ -# Trading Engine contract v1 +# Replay contract v1 -This frozen directory preserves the historical v1 process and file contract. The current runtime -advertises v4 and v3 only; these artifacts remain available for provenance and schema-only -compatibility testing by older consumers. +This directory is the authoritative replay contract for Trading Engine. -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- `fixtures/demo.scenario.json`, `fixtures/demo.scenario.jsonl`, and - `fixtures/demo.journal.jsonl` form the canonical valid conformance corpus. +- `scenario.schema.json` defines batch replay input. +- `scenario-stream.schema.json` defines the equivalent JSON Lines stream. +- `journal.schema.json` defines append-only audit records. +- `fixtures/` contains canonical scenarios and journals used by the conformance suite. -Every batch scenario, scenario-stream record, and journal record carries -`"contract_version": "1"`. Consumers must reject missing or unsupported versions before -interpreting the rest of a document. +Every scenario, stream record, and journal record carries `"contract_version": "1"`. +Objects are strict unless a field is explicitly open, decimal values use canonical strings, and +timestamps are bounded RFC 3339 instants. Runtime validation additionally enforces uniqueness, +causal ordering, non-overlapping slices, resource limits, and configuration coverage. + +The contract models an explicit initial portfolio, instrument-level and grouped risk policy, +execution and fee schedules, financing, settlement, venue calendars, lifecycle events, market +data, strategy intents, and causal audit output. A successful replay ends with `run_completed`. + +Run `make check` to validate schemas, fixtures, runtime behavior, and deterministic output. diff --git a/contracts/v1/dune b/contracts/v1/dune index fe01ab1..0f6b798 100644 --- a/contracts/v1/dune +++ b/contracts/v1/dune @@ -7,4 +7,28 @@ (scenario.schema.json as contracts/v1/scenario.schema.json) (fixtures/demo.journal.jsonl as contracts/v1/fixtures/demo.journal.jsonl) (fixtures/demo.scenario.json as contracts/v1/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v1/fixtures/demo.scenario.jsonl))) + (fixtures/demo.scenario.jsonl as contracts/v1/fixtures/demo.scenario.jsonl) + (fixtures/fill-clipped.journal.jsonl + as + contracts/v1/fixtures/fill-clipped.journal.jsonl) + (fixtures/fill-clipped.scenario.json + as + contracts/v1/fixtures/fill-clipped.scenario.json) + (fixtures/quote-trade.journal.jsonl + as + contracts/v1/fixtures/quote-trade.journal.jsonl) + (fixtures/quote-trade.scenario.json + as + contracts/v1/fixtures/quote-trade.scenario.json) + (fixtures/quote-trade.scenario.jsonl + as + contracts/v1/fixtures/quote-trade.scenario.jsonl) + (fixtures/order-book.journal.jsonl + as + contracts/v1/fixtures/order-book.journal.jsonl) + (fixtures/order-book.scenario.json + as + contracts/v1/fixtures/order-book.scenario.json) + (fixtures/order-book.scenario.jsonl + as + contracts/v1/fixtures/order-book.scenario.jsonl))) diff --git a/contracts/v1/fixtures/demo.journal.jsonl b/contracts/v1/fixtures/demo.journal.jsonl index 4d59346..cdafdd3 100644 --- a/contracts/v1/fixtures/demo.journal.jsonl +++ b/contracts/v1/fixtures/demo.journal.jsonl @@ -1,20 +1,34 @@ -{"contract_version":"1","engine_sequence":"1","run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"a782fbbee8b89332ee6491d9d9be36bf7f2aaacbd440d30c20ed033fd7566d19"}} -{"contract_version":"1","engine_sequence":"2","run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]}} -{"contract_version":"1","engine_sequence":"3","run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9","reference_price":"104"}]}} -{"contract_version":"1","engine_sequence":"4","run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"1","engine_sequence":"5","run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"1","engine_sequence":"6","run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"10000","market_value":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"10000","total_fees":"0"}} -{"contract_version":"1","engine_sequence":"7","run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}]}} -{"contract_version":"1","engine_sequence":"8","run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"1","engine_sequence":"9","run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"1","engine_sequence":"10","run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"3","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_sequence":"10","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"1","engine_sequence":"11","run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"9381.132","market_value":"642","cost_basis":"618.868","realized_pnl":"0","unrealized_pnl":"23.132","equity":"10023.132","total_fees":"0.868"}} -{"contract_version":"1","engine_sequence":"12","run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}]}} -{"contract_version":"1","engine_sequence":"13","run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"3","price":"107","notional":"321","fee":"0.571","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"1","engine_sequence":"14","run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2","reference_price":null}]}} -{"contract_version":"1","engine_sequence":"15","run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_sequence":"15","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"1","engine_sequence":"16","run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"9059.561","market_value":"945","cost_basis":"940.439","realized_pnl":"0","unrealized_pnl":"4.561","equity":"10004.561","total_fees":"1.439"}} -{"contract_version":"1","engine_sequence":"17","run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}]}} -{"contract_version":"1","engine_sequence":"18","run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7","price":"105","notional":"735","fee":"0.985","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"1","engine_sequence":"19","run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"9793.576","market_value":"212","cost_basis":"208.986445","realized_pnl":"2.562445","unrealized_pnl":"3.013555","equity":"10005.576","total_fees":"2.424"}} -{"contract_version":"1","engine_sequence":"20","run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"a782fbbee8b89332ee6491d9d9be36bf7f2aaacbd440d30c20ed033fd7566d19","valuation":{"cash":"9793.576","market_value":"212","cost_basis":"208.986445","realized_pnl":"2.562445","unrealized_pnl":"3.013555","equity":"10005.576","total_fees":"2.424"},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} +{"contract_version":"1","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"e2227af76072fab8151c3e1bd86f401293d16a736e32040efdaf8761cd397574","execution_model":"completed_bar_adverse_touch_v1"}} +{"contract_version":"1","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","execution_fee_components":[],"borrow_fees":"0.25","total_fees":"0.75","cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"10000","settled_amount":"10000","unsettled_amount":"0","fx_rate":"1","base_value":"10000","base_settled_value":"10000","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","settled_quantity":"1","unsettled_quantity":"0","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","execution_fee_components":[],"borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} +{"contract_version":"1","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","execution_fee_components":[],"borrow_fees":"0.25","total_fees":"0.75","cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"10000","settled_amount":"10000","unsettled_amount":"0","fx_rate":"1","base_value":"10000","base_settled_value":"10000","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","settled_quantity":"1","unsettled_quantity":"0","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","execution_fee_components":[],"borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} +{"contract_version":"1","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} +{"contract_version":"1","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":{"type":"numeric","value":"0.1"},"unit":"ratio","dimensions":{"instrument":"demo-equity-acme","source":"strategy"},"aggregation":"last"}} +{"contract_version":"1","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} +{"contract_version":"1","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","execution_fee_components":[],"borrow_fees":"0.25","total_fees":"0.75","cash_interest":"0.074201","settled_cash":"10000.074201","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"10000.074201","settled_amount":"10000.074201","unsettled_amount":"0","fx_rate":"1","base_value":"10000.074201","base_settled_value":"10000.074201","base_unsettled_value":"0","interest":"0.074201","base_interest":"0.074201"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","settled_quantity":"1","unsettled_quantity":"0","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","execution_fee_components":[],"borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"13"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} +{"contract_version":"1","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","reference_price":"103","spread_adjustment":"0.06","impact_adjustment":"0.13","final_price":"103.19"}} +{"contract_version":"1","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6.5","price":"103.19","notional":"670.735","fee":"0.920735","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_amount":"0.670735"}],"executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} +{"contract_version":"1","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000013"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000001-settlement","fill_id":"demo-fill-000000000001","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-671.655735","position_movement":"6.5","trade_date":"2026-01-05","due_date":"2026-01-06","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6.5","filled_notional":"670.735","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} +{"contract_version":"1","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000016","updated_event_id":"demo-event-000000000016","created_sequence":"16","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} +{"contract_version":"1","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9328.492667","net_market_value":"802.5","long_market_value":"802.5","short_market_value":"0","gross_exposure":"802.5","cost_basis":"761.655735","realized_pnl":"5.148402","unrealized_pnl":"40.844265","equity":"10130.992667","dividend_pnl":"1","execution_fees":"1.420735","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"borrow_fees":"0.25","total_fees":"1.670735","cash_interest":"0.148402","settled_cash":"10000.148402","unsettled_cash":"-671.655735","cash_balances":[{"currency":"USD","amount":"9328.492667","settled_amount":"10000.148402","unsettled_amount":"-671.655735","fx_rate":"1","base_value":"9328.492667","base_settled_value":"10000.148402","base_unsettled_value":"-671.655735","interest":"0.148402","base_interest":"0.148402"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7.5","settled_quantity":"1","unsettled_quantity":"6.5","mark":"107","fx_rate":"1","market_value":"802.5","base_market_value":"802.5","cost_basis":"761.655735","base_cost_basis":"761.655735","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.844265","base_unrealized_pnl":"40.844265","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.420735","base_execution_fees":"1.420735","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.670735","base_total_fees":"1.670735"}],"margin":{"initial_requirement":"401.25","maintenance_requirement":"200.625","initial_excess":"9729.742667","maintenance_excess":"9930.367667","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000018"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"settlement_completed","payload":{"instruction_id":"demo-fill-000000000001-settlement","fill_id":"demo-fill-000000000001","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-671.655735","position_movement":"6.5","trade_date":"2026-01-05","due_date":"2026-01-06","status":"settled","settled_at":"2026-01-06T14:30:00.000000Z","failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000018"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9328.492667","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.069218","closing_balance":"9328.561885"}} +{"contract_version":"1","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000016","demo-event-000000000018"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","reference_price":"107","spread_adjustment":"0.06","impact_adjustment":"0.01","final_price":"107.07"}} +{"contract_version":"1","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.215","price":"107.07","notional":"237.16005","fee":"0.487161","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.237161","quote_amount":"0.237161"}],"executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} +{"contract_version":"1","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000022"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000002-settlement","fill_id":"demo-fill-000000000002","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-237.647211","position_movement":"2.215","trade_date":"2026-01-06","due_date":"2026-01-07","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":["demo-event-000000000018"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} +{"contract_version":"1","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":["demo-event-000000000018","demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000025","updated_event_id":"demo-event-000000000025","created_sequence":"25","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} +{"contract_version":"1","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000018"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.914674","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.302946","realized_pnl":"5.21762","unrealized_pnl":"20.772054","equity":"10110.989674","dividend_pnl":"1","execution_fees":"1.907896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"borrow_fees":"0.25","total_fees":"2.157896","cash_interest":"0.21762","settled_cash":"9328.561885","unsettled_cash":"-237.647211","cash_balances":[{"currency":"USD","amount":"9090.914674","settled_amount":"9328.561885","unsettled_amount":"-237.647211","fx_rate":"1","base_value":"9090.914674","base_settled_value":"9328.561885","base_unsettled_value":"-237.647211","interest":"0.21762","base_interest":"0.21762"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","settled_quantity":"7.5","unsettled_quantity":"2.215","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.302946","base_cost_basis":"999.302946","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.772054","base_unrealized_pnl":"20.772054","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.907896","base_execution_fees":"1.907896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.157896","base_total_fees":"2.157896"}],"margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.952174","maintenance_excess":"9855.970924","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"27","event_id":"demo-event-000000000027","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"28","event_id":"demo-event-000000000028","causation_ids":["demo-event-000000000027"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"settlement_completed","payload":{"instruction_id":"demo-fill-000000000002-settlement","fill_id":"demo-fill-000000000002","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-237.647211","position_movement":"2.215","trade_date":"2026-01-06","due_date":"2026-01-07","status":"settled","settled_at":"2026-01-07T14:30:00.000000Z","failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"29","event_id":"demo-event-000000000029","causation_ids":["demo-event-000000000027"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.914674","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067455","closing_balance":"9090.982129"}} +{"contract_version":"1","engine_sequence":"30","event_id":"demo-event-000000000030","causation_ids":["demo-event-000000000025","demo-event-000000000027"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","reference_price":"105","spread_adjustment":"0.06","impact_adjustment":"0.02","final_price":"104.92"}} +{"contract_version":"1","engine_sequence":"31","event_id":"demo-event-000000000031","causation_ids":["demo-event-000000000030"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"104.92","notional":"756.9978","fee":"1","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.756998","quote_amount":"0.756998"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_amount":"-0.006998"}],"executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} +{"contract_version":"1","engine_sequence":"32","event_id":"demo-event-000000000032","causation_ids":["demo-event-000000000031"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000003-settlement","fill_id":"demo-fill-000000000003","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"755.9978","position_movement":"-7.215","trade_date":"2026-01-07","due_date":"2026-01-08","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"33","event_id":"demo-event-000000000033","causation_ids":["demo-event-000000000027"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"borrow_fees":"0.25","total_fees":"3.157896","cash_interest":"0.285075","settled_cash":"9090.982129","unsettled_cash":"755.9978","cash_balances":[{"currency":"USD","amount":"9846.979929","settled_amount":"9090.982129","unsettled_amount":"755.9978","fx_rate":"1","base_value":"9846.979929","base_settled_value":"9090.982129","base_unsettled_value":"755.9978","interest":"0.285075","base_interest":"0.285075"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","settled_quantity":"9.715","unsettled_quantity":"-7.215","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"34","event_id":"demo-event-000000000034","causation_ids":["demo-event-000000000033"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"e2227af76072fab8151c3e1bd86f401293d16a736e32040efdaf8761cd397574","execution_model":"completed_bar_adverse_touch_v1","valuation":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"borrow_fees":"0.25","total_fees":"3.157896","cash_interest":"0.285075","settled_cash":"9090.982129","unsettled_cash":"755.9978","cash_balances":[{"currency":"USD","amount":"9846.979929","settled_amount":"9090.982129","unsettled_amount":"755.9978","fx_rate":"1","base_value":"9846.979929","base_settled_value":"9090.982129","base_unsettled_value":"755.9978","interest":"0.285075","base_interest":"0.285075"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","settled_quantity":"9.715","unsettled_quantity":"-7.215","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v1/fixtures/demo.scenario.json b/contracts/v1/fixtures/demo.scenario.json index fd0da5d..db90199 100644 --- a/contracts/v1/fixtures/demo.scenario.json +++ b/contracts/v1/fixtures/demo.scenario.json @@ -6,24 +6,205 @@ }, "run_id": "demo", "base_currency": "USD", - "initial_cash": "10000", + "initial_portfolio": { + "cash": [ + { + "currency": "USD", + "amount": "10000" + } + ], + "positions": [ + { + "instrument_id": "demo-equity-acme", + "quantity": "1", + "cost_basis": "90", + "realized_pnl": "5", + "dividend_pnl": "1", + "execution_fees": "0.5", + "borrow_fees": "0.25" + } + ], + "marks": [ + { + "instrument_id": "demo-equity-acme", + "price": "100" + } + ], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } + ] + }, "instruments": [ { "instrument_id": "demo-equity-acme", "symbol": "ACME", "quote_currency": "USD", "tick_size": "0.01", - "lot_size": "1" + "lot_size": "0.001" + } + ], + "venue_calendars": [ + { + "calendar_id": "demo-xnas-2026", + "calendar_version": "1", + "venue_id": "XNAS", + "instrument_ids": [ + "demo-equity-acme" + ], + "sessions": [ + { + "session_date": "2026-01-01", + "policy": "holiday", + "phases": [] + }, + { + "session_date": "2026-01-02", + "policy": "regular", + "phases": [ + { + "phase": "premarket", + "opens_at": "2026-01-02T09:00:00Z", + "closes_at": "2026-01-02T14:25:00Z" + }, + { + "phase": "opening_auction", + "opens_at": "2026-01-02T14:25:00Z", + "closes_at": "2026-01-02T14:30:00Z" + }, + { + "phase": "regular", + "opens_at": "2026-01-02T14:30:00Z", + "closes_at": "2026-01-02T20:55:00Z" + }, + { + "phase": "closing_auction", + "opens_at": "2026-01-02T20:55:00Z", + "closes_at": "2026-01-02T21:00:00Z" + }, + { + "phase": "postmarket", + "opens_at": "2026-01-02T21:00:00Z", + "closes_at": "2026-01-03T01:00:00Z" + } + ] + }, + { + "session_date": "2026-01-05", + "policy": "regular", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-05T14:30:00Z", + "closes_at": "2026-01-05T21:00:00Z" + } + ] + }, + { + "session_date": "2026-01-06", + "policy": "regular", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-06T14:30:00Z", + "closes_at": "2026-01-06T21:00:00Z" + } + ] + }, + { + "session_date": "2026-01-07", + "policy": "regular", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-07T14:30:00Z", + "closes_at": "2026-01-07T21:00:00Z" + } + ] + }, + { + "session_date": "2026-01-08", + "policy": "early_close", + "phases": [ + { + "phase": "regular", + "opens_at": "2026-01-08T14:30:00Z", + "closes_at": "2026-01-08T18:00:00Z" + } + ] + } + ] } ], "risk": { - "max_order_quantity": "1000", - "max_position": "1000" + "max_gross_exposure": "1000000", + "max_leverage": "2", + "instrument_policies": [ + { + "instrument_id": "demo-equity-acme", + "max_order_quantity": "1000", + "max_long_position": "1000", + "max_short_position": "1000", + "max_notional_exposure": "1000000", + "initial_margin_bps": 5000, + "maintenance_margin_bps": 2500, + "shorting_allowed": true + } + ], + "groups": [] }, "execution": { - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 + "model": "completed_bar_adverse_touch_v1", + "configuration": { + "version": "1", + "participation_bps": 5000, + "fee_schedules": [ + { + "schedule_id": "demo-acme-fees-v1", + "instrument_id": "demo-equity-acme", + "settlement_currency": "USD", + "minimum": "0.3", + "maximum": "1", + "components": [ + { + "name": "broker", + "currency": "USD", + "kind": "fixed", + "value": "0.25", + "rounding": "up", + "applies_to": "any" + }, + { + "name": "exchange", + "currency": "USD", + "kind": "notional_bps", + "value": 10, + "rounding": "up", + "applies_to": "taker" + }, + { + "name": "maker_rebate", + "currency": "USD", + "kind": "notional_bps", + "value": -2, + "rounding": "nearest", + "applies_to": "maker" + } + ] + } + ], + "spread_model": { + "model": "fixed_half_spread_v1", + "half_spread_bps": 5 + }, + "impact_model": { + "model": "linear_participation_v1", + "coefficient_bps": 25, + "missing_volume_policy": "reject" + } + } }, "max_internal_events": 1000, "schedule": [ @@ -42,7 +223,10 @@ { "type": "emit_metric", "name": "desired_weight", - "value": "0.1" + "value": { "type": "numeric", "value": "0.1" }, + "unit": "ratio", + "dimensions": { "source": "strategy", "instrument": "demo-equity-acme" }, + "aggregation": "last" } ] }, @@ -54,7 +238,7 @@ "targets": [ { "instrument_id": "demo-equity-acme", - "quantity": "2" + "quantity": "2.5" } ] } @@ -77,7 +261,35 @@ "close": "104", "volume": "100" } - ] + ], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } + ], + "corporate_actions": [], + "borrow_observations": [ + { + "instrument_id": "demo-equity-acme", + "effective_at": "2026-01-02T14:30:00Z", + "available_quantity": "1000", + "annual_rate_bps": 100, + "recalled": false + } + ], + "cash_rate_observations": [ + { + "currency": "USD", + "effective_at": "2026-01-02T14:30:00Z", + "credit_rate_bps": 100, + "debit_rate_bps": 200 + } + ], + "settlement_failures": [], + "lifecycle_events": [], + "market_events": [], + "order_book_events": [] }, { "slice_sequence": "2", @@ -92,9 +304,37 @@ "high": "108", "low": "102", "close": "107", - "volume": "12" + "volume": "13" } - ] + ], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } + ], + "corporate_actions": [], + "borrow_observations": [ + { + "instrument_id": "demo-equity-acme", + "effective_at": "2026-01-05T14:30:00Z", + "available_quantity": "1000", + "annual_rate_bps": 100, + "recalled": false + } + ], + "cash_rate_observations": [ + { + "currency": "USD", + "effective_at": "2026-01-05T14:30:00Z", + "credit_rate_bps": 100, + "debit_rate_bps": 200 + } + ], + "settlement_failures": [], + "lifecycle_events": [], + "market_events": [], + "order_book_events": [] }, { "slice_sequence": "3", @@ -111,7 +351,35 @@ "close": "105", "volume": "100" } - ] + ], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } + ], + "corporate_actions": [], + "borrow_observations": [ + { + "instrument_id": "demo-equity-acme", + "effective_at": "2026-01-06T14:30:00Z", + "available_quantity": "1000", + "annual_rate_bps": 100, + "recalled": false + } + ], + "cash_rate_observations": [ + { + "currency": "USD", + "effective_at": "2026-01-06T14:30:00Z", + "credit_rate_bps": 100, + "debit_rate_bps": 200 + } + ], + "settlement_failures": [], + "lifecycle_events": [], + "market_events": [], + "order_book_events": [] }, { "slice_sequence": "4", @@ -128,7 +396,72 @@ "close": "106", "volume": "100" } - ] + ], + "fx_rates": [ + { + "currency": "USD", + "rate": "1" + } + ], + "corporate_actions": [], + "borrow_observations": [ + { + "instrument_id": "demo-equity-acme", + "effective_at": "2026-01-07T14:30:00Z", + "available_quantity": "1000", + "annual_rate_bps": 100, + "recalled": false + } + ], + "cash_rate_observations": [ + { + "currency": "USD", + "effective_at": "2026-01-07T14:30:00Z", + "credit_rate_bps": 100, + "debit_rate_bps": 200 + } + ], + "settlement_failures": [], + "lifecycle_events": [], + "market_events": [], + "order_book_events": [] } - ] + ], + "financing": { + "day_count": "actual_365", + "compounding": "simple", + "borrow_missing_data": "reject", + "cash_missing_data": "reject", + "locate_policy": "clip_fill", + "recall_policy": "close_out" + }, + "settlement": { + "cash_buying_power": "total_cash", + "position_availability": "total_positions", + "calendars": [ + { + "calendar_id": "default-settlement", + "version": "1", + "business_dates": [ + "2026-01-02", + "2026-01-05", + "2026-01-06", + "2026-01-07", + "2026-01-08", + "2026-01-09", + "2026-02-02", + "2026-02-03", + "2026-02-04", + "2026-02-05" + ] + } + ], + "rules": [ + { + "instrument_id": "demo-equity-acme", + "calendar_id": "default-settlement", + "lag_business_days": 1 + } + ] + } } diff --git a/contracts/v1/fixtures/demo.scenario.jsonl b/contracts/v1/fixtures/demo.scenario.jsonl index 6aa3248..bcb0aa8 100644 --- a/contracts/v1/fixtures/demo.scenario.jsonl +++ b/contracts/v1/fixtures/demo.scenario.jsonl @@ -1,6 +1,6 @@ -{"contract_version":"1","payload":{"base_currency":"USD","execution":{"fee_bps":10,"fixed_fee":"0.25","participation_bps":5000},"initial_cash":"10000","instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"max_internal_events":1000,"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"risk":{"max_order_quantity":"1000","max_position":"1000"},"run_id":"demo"},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"1","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"end_at":"2026-01-02T21:00:00Z","received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"1","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"end_at":"2026-01-05T21:00:00Z","received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"1","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"end_at":"2026-01-06T21:00:00Z","received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"1","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"end_at":"2026-01-07T21:00:00Z","received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} +{"contract_version":"1","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_adverse_touch_v1","configuration":{"version":"1","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}],"spread_model":{"model":"fixed_half_spread_v1","half_spread_bps":5},"impact_model":{"model":"linear_participation_v1","coefficient_bps":25,"missing_volume_policy":"reject"}}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} +{"contract_version":"1","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"aggregation":"last","dimensions":{"instrument":"demo-equity-acme","source":"strategy"},"name":"desired_weight","type":"emit_metric","unit":"ratio","value":{"type":"numeric","value":"0.1"}}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} +{"contract_version":"1","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"13"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} +{"contract_version":"1","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"4"} +{"contract_version":"1","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"5"} {"contract_version":"1","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v1/fixtures/fill-clipped.journal.jsonl b/contracts/v1/fixtures/fill-clipped.journal.jsonl new file mode 100644 index 0000000..7318059 --- /dev/null +++ b/contracts/v1/fixtures/fill-clipped.journal.jsonl @@ -0,0 +1,13 @@ +{"contract_version":"1","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"49451cf495ed00cdcc5330a62814b9b6adeb6e4fc844e74a5ae35f5cbf91c893","execution_model":"completed_bar_v1"}} +{"contract_version":"1","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0","settled_cash":"550","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"550","settled_amount":"550","unsettled_amount":"0","fx_rate":"1","base_value":"550","base_settled_value":"550","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} +{"contract_version":"1","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0","settled_cash":"550","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"550","settled_amount":"550","unsettled_amount":"0","fx_rate":"1","base_value":"550","base_settled_value":"550","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} +{"contract_version":"1","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} +{"contract_version":"1","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0.004081","settled_cash":"550.004081","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"550.004081","settled_amount":"550.004081","unsettled_amount":"0","fx_rate":"1","base_value":"550.004081","base_settled_value":"550.004081","base_unsettled_value":"0","interest":"0.004081","base_interest":"0.004081"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","settled_quantity":"0","unsettled_quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} +{"contract_version":"1","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} +{"contract_version":"1","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} +{"contract_version":"1","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"550.008162","settled_amount":"550.008162","unsettled_amount":"0","fx_rate":"1","base_value":"550.008162","base_settled_value":"550.008162","base_unsettled_value":"0","interest":"0.008162","base_interest":"0.008162"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","settled_quantity":"0","unsettled_quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"49451cf495ed00cdcc5330a62814b9b6adeb6e4fc844e74a5ae35f5cbf91c893","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"550.008162","settled_amount":"550.008162","unsettled_amount":"0","fx_rate":"1","base_value":"550.008162","base_settled_value":"550.008162","base_unsettled_value":"0","interest":"0.008162","base_interest":"0.008162"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","settled_quantity":"0","unsettled_quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v15/fixtures/fill-clipped.scenario.json b/contracts/v1/fixtures/fill-clipped.scenario.json similarity index 98% rename from contracts/v15/fixtures/fill-clipped.scenario.json rename to contracts/v1/fixtures/fill-clipped.scenario.json index 319e246..e4edda4 100644 --- a/contracts/v15/fixtures/fill-clipped.scenario.json +++ b/contracts/v1/fixtures/fill-clipped.scenario.json @@ -1,5 +1,5 @@ { - "contract_version": "15", + "contract_version": "1", "metadata": { "producer": "trading-engine", "purpose": "fill clipping conformance fixture" @@ -79,7 +79,6 @@ "risk": { "max_gross_exposure": "1000000000", "max_leverage": "1", - "short_borrow_bps": 100, "instrument_policies": [ { "instrument_id": "clip-equity", @@ -97,7 +96,7 @@ "execution": { "model": "completed_bar_v1", "configuration": { - "version": "2", + "version": "1", "participation_bps": 10000, "fee_schedules": [ { diff --git a/contracts/v1/fixtures/order-book.journal.jsonl b/contracts/v1/fixtures/order-book.journal.jsonl new file mode 100644 index 0000000..f016002 --- /dev/null +++ b/contracts/v1/fixtures/order-book.journal.jsonl @@ -0,0 +1,15 @@ +{"contract_version":"1","engine_sequence":"1","event_id":"order-book-event-000000000001","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"d1e8ead9f40facf6b095a785e56ce0dc6f40b8e37cfff91e8de87787bff38c8c","execution_model":"order_book_v1"}} +{"contract_version":"1","engine_sequence":"2","event_id":"order-book-event-000000000002","causation_ids":["order-book-event-000000000001"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"2000","settled_amount":"2000","unsettled_amount":"0","fx_rate":"1","base_value":"2000","base_settled_value":"2000","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}}} +{"contract_version":"1","engine_sequence":"3","event_id":"order-book-event-000000000003","causation_ids":["order-book-event-000000000002"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"2000","settled_amount":"2000","unsettled_amount":"0","fx_rate":"1","base_value":"2000","base_settled_value":"2000","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"4","event_id":"order-book-event-000000000004","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-02T14:31:00.000000Z","available_at":"2026-02-02T14:31:01.000000Z","received_at":"2026-02-02T14:31:02.000000Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"49","quantity":"20"}],"asks":[{"price":"51","quantity":"20"}]}]}} +{"contract_version":"1","engine_sequence":"5","event_id":"order-book-event-000000000005","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.01484"}} +{"contract_version":"1","engine_sequence":"6","event_id":"order-book-event-000000000006","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"order-book-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"order-book-event-000000000006","updated_event_id":"order-book-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} +{"contract_version":"1","engine_sequence":"7","event_id":"order-book-event-000000000007","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000.01484","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.01484","unrealized_pnl":"0","equity":"2000.01484","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0.01484","settled_cash":"2000.01484","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"2000.01484","settled_amount":"2000.01484","unsettled_amount":"0","fx_rate":"1","base_value":"2000.01484","base_settled_value":"2000.01484","base_unsettled_value":"0","interest":"0.01484","base_interest":"0.01484"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","settled_quantity":"0","unsettled_quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000.01484","maintenance_excess":"2000.01484","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"8","event_id":"order-book-event-000000000008","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00.000000Z","available_at":"2026-02-03T14:31:01.000000Z","received_at":"2026-02-03T14:31:02.000000Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"100","quantity":"5"}],"asks":[{"price":"101","quantity":"20"}]},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00.000000Z","available_at":"2026-02-03T14:32:01.000000Z","received_at":"2026-02-03T14:32:02.000000Z","ingest_sequence":"2","book_sequence":"2","side":"bid","price":"100","quantity":"3"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00.000000Z","available_at":"2026-02-03T14:33:01.000000Z","received_at":"2026-02-03T14:33:02.000000Z","ingest_sequence":"3","book_sequence":"3","price":"100","quantity":"3","aggressor_side":"sell"},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00.000000Z","available_at":"2026-02-03T14:34:01.000000Z","received_at":"2026-02-03T14:34:02.000000Z","ingest_sequence":"4","book_sequence":"4","side":"bid","price":"100","quantity":"10"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:35:00.000000Z","available_at":"2026-02-03T14:35:01.000000Z","received_at":"2026-02-03T14:35:02.000000Z","ingest_sequence":"5","book_sequence":"5","price":"100","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:36:00.000000Z","available_at":"2026-02-03T14:36:01.000000Z","received_at":"2026-02-03T14:36:02.000000Z","ingest_sequence":"6","book_sequence":"6","price":"100","quantity":"6","aggressor_side":"sell"}]}} +{"contract_version":"1","engine_sequence":"9","event_id":"order-book-event-000000000009","causation_ids":["order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000.01484","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.02968"}} +{"contract_version":"1","engine_sequence":"10","event_id":"order-book-event-000000000010","causation_ids":["order-book-event-000000000006","order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"order-book-fill-000000000001","order_id":"order-book-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"4","price":"100","notional":"400","fee":"10","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}],"executed_at":"2026-02-03T14:35:00.000000Z","slice_sequence":"2"}} +{"contract_version":"1","engine_sequence":"11","event_id":"order-book-event-000000000011","causation_ids":["order-book-event-000000000010"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"order-book-fill-000000000001-settlement","fill_id":"order-book-fill-000000000001","instrument_id":"clip-equity","currency":"USD","cash_movement":"-410","position_movement":"4","trade_date":"2026-02-03","due_date":"2026-02-04","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"12","event_id":"order-book-event-000000000012","causation_ids":["order-book-event-000000000006","order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"order-book-fill-000000000002","order_id":"order-book-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"6","price":"100","notional":"600","fee":"10","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}],"executed_at":"2026-02-03T14:36:00.000000Z","slice_sequence":"2"}} +{"contract_version":"1","engine_sequence":"13","event_id":"order-book-event-000000000013","causation_ids":["order-book-event-000000000012"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"order-book-fill-000000000002-settlement","fill_id":"order-book-fill-000000000002","instrument_id":"clip-equity","currency":"USD","cash_movement":"-610","position_movement":"6","trade_date":"2026-02-03","due_date":"2026-02-04","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"14","event_id":"order-book-event-000000000014","causation_ids":["order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"980.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1020","realized_pnl":"0.02968","unrealized_pnl":"-20","equity":"1980.02968","dividend_pnl":"0","execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","total_fees":"20","cash_interest":"0.02968","settled_cash":"2000.02968","unsettled_cash":"-1020","cash_balances":[{"currency":"USD","amount":"980.02968","settled_amount":"2000.02968","unsettled_amount":"-1020","fx_rate":"1","base_value":"980.02968","base_settled_value":"2000.02968","base_unsettled_value":"-1020","interest":"0.02968","base_interest":"0.02968"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","settled_quantity":"0","unsettled_quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1020","base_cost_basis":"1020","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-20","base_unrealized_pnl":"-20","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20"}],"margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1480.02968","maintenance_excess":"1730.02968","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"15","event_id":"order-book-event-000000000015","causation_ids":["order-book-event-000000000014"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"d1e8ead9f40facf6b095a785e56ce0dc6f40b8e37cfff91e8de87787bff38c8c","execution_model":"order_book_v1","valuation":{"base_currency":"USD","cash":"980.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1020","realized_pnl":"0.02968","unrealized_pnl":"-20","equity":"1980.02968","dividend_pnl":"0","execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","total_fees":"20","cash_interest":"0.02968","settled_cash":"2000.02968","unsettled_cash":"-1020","cash_balances":[{"currency":"USD","amount":"980.02968","settled_amount":"2000.02968","unsettled_amount":"-1020","fx_rate":"1","base_value":"980.02968","base_settled_value":"2000.02968","base_unsettled_value":"-1020","interest":"0.02968","base_interest":"0.02968"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","settled_quantity":"0","unsettled_quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1020","base_cost_basis":"1020","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-20","base_unrealized_pnl":"-20","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20"}],"margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1480.02968","maintenance_excess":"1730.02968","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":1,"rejected":0,"cancelled":0}}} diff --git a/contracts/v16/fixtures/order-book.scenario.json b/contracts/v1/fixtures/order-book.scenario.json similarity index 99% rename from contracts/v16/fixtures/order-book.scenario.json rename to contracts/v1/fixtures/order-book.scenario.json index 83e22e0..f107f4e 100644 --- a/contracts/v16/fixtures/order-book.scenario.json +++ b/contracts/v1/fixtures/order-book.scenario.json @@ -1,5 +1,5 @@ { - "contract_version": "16", + "contract_version": "1", "metadata": { "producer": "trading-engine", "purpose": "bounded order-book replay conformance fixture" @@ -79,7 +79,6 @@ "risk": { "max_gross_exposure": "1000000000", "max_leverage": "1", - "short_borrow_bps": 100, "instrument_policies": [ { "instrument_id": "clip-equity", diff --git a/contracts/v1/fixtures/order-book.scenario.jsonl b/contracts/v1/fixtures/order-book.scenario.jsonl new file mode 100644 index 0000000..0ef9d37 --- /dev/null +++ b/contracts/v1/fixtures/order-book.scenario.jsonl @@ -0,0 +1,4 @@ +{"contract_version":"1","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine","purpose":"bounded order-book replay conformance fixture"},"run_id":"order-book","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"clip-equity","symbol":"CLIP","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"clip-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["clip-equity"],"sessions":[{"session_date":"2026-02-02","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-02T14:30:00Z","closes_at":"2026-02-02T21:00:00Z"}]},{"session_date":"2026-02-03","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-03T14:30:00Z","closes_at":"2026-02-03T21:00:00Z"}]},{"session_date":"2026-02-04","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-02-04T14:30:00Z","closes_at":"2026-02-04T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000000","max_leverage":"1","instrument_policies":[{"instrument_id":"clip-equity","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"order_book_v1","configuration":{"version":"1","participation_bps":10000,"fee_schedules":[{"schedule_id":"clip-fees-v1","instrument_id":"clip-equity","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"10","rounding":"up","applies_to":"any"}]}],"max_depth_levels":10}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"clip-equity","calendar_id":"default-settlement","lag_business_days":1}]}}} +{"contract_version":"1","scenario_sequence":"2","record_type":"market_slice","payload":{"intents":[{"type":"submit_order","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null}],"market_slice":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00Z","end_at":"2026-02-02T21:00:00Z","available_at":"2026-02-02T21:00:01Z","received_at":"2026-02-02T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-02T14:31:00Z","available_at":"2026-02-02T14:31:01Z","received_at":"2026-02-02T14:31:02Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"49","quantity":"20"}],"asks":[{"price":"51","quantity":"20"}]}]}}} +{"contract_version":"1","scenario_sequence":"3","record_type":"market_slice","payload":{"intents":[],"market_slice":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00Z","end_at":"2026-02-03T21:00:00Z","available_at":"2026-02-03T21:00:01Z","received_at":"2026-02-03T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00Z","available_at":"2026-02-03T14:31:01Z","received_at":"2026-02-03T14:31:02Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"100","quantity":"5"}],"asks":[{"price":"101","quantity":"20"}]},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00Z","available_at":"2026-02-03T14:32:01Z","received_at":"2026-02-03T14:32:02Z","ingest_sequence":"2","book_sequence":"2","side":"bid","price":"100","quantity":"3"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00Z","available_at":"2026-02-03T14:33:01Z","received_at":"2026-02-03T14:33:02Z","ingest_sequence":"3","book_sequence":"3","price":"100","quantity":"3","aggressor_side":"sell"},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00Z","available_at":"2026-02-03T14:34:01Z","received_at":"2026-02-03T14:34:02Z","ingest_sequence":"4","book_sequence":"4","side":"bid","price":"100","quantity":"10"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:35:00Z","available_at":"2026-02-03T14:35:01Z","received_at":"2026-02-03T14:35:02Z","ingest_sequence":"5","book_sequence":"5","price":"100","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:36:00Z","available_at":"2026-02-03T14:36:01Z","received_at":"2026-02-03T14:36:02Z","ingest_sequence":"6","book_sequence":"6","price":"100","quantity":"6","aggressor_side":"sell"}]}}} +{"contract_version":"1","scenario_sequence":"4","record_type":"scenario_end","payload":{"slice_count":"2"}} diff --git a/contracts/v1/fixtures/quote-trade.journal.jsonl b/contracts/v1/fixtures/quote-trade.journal.jsonl new file mode 100644 index 0000000..615131a --- /dev/null +++ b/contracts/v1/fixtures/quote-trade.journal.jsonl @@ -0,0 +1,15 @@ +{"contract_version":"1","engine_sequence":"1","event_id":"quote-trade-event-000000000001","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"9c525db135cd830107ffd151024f807261c5e9403ec4e3734109fab1e0da8623","execution_model":"quote_trade_v1"}} +{"contract_version":"1","engine_sequence":"2","event_id":"quote-trade-event-000000000002","causation_ids":["quote-trade-event-000000000001"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"2000","settled_amount":"2000","unsettled_amount":"0","fx_rate":"1","base_value":"2000","base_settled_value":"2000","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}}} +{"contract_version":"1","engine_sequence":"3","event_id":"quote-trade-event-000000000003","causation_ids":["quote-trade-event-000000000002"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"2000","settled_amount":"2000","unsettled_amount":"0","fx_rate":"1","base_value":"2000","base_settled_value":"2000","base_unsettled_value":"0","interest":"0","base_interest":"0"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"4","event_id":"quote-trade-event-000000000004","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"5","event_id":"quote-trade-event-000000000005","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.01484"}} +{"contract_version":"1","engine_sequence":"6","event_id":"quote-trade-event-000000000006","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"quote-trade-event-000000000006","updated_event_id":"quote-trade-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} +{"contract_version":"1","engine_sequence":"7","event_id":"quote-trade-event-000000000007","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000.01484","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.01484","unrealized_pnl":"0","equity":"2000.01484","dividend_pnl":"0","execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","total_fees":"0","cash_interest":"0.01484","settled_cash":"2000.01484","unsettled_cash":"0","cash_balances":[{"currency":"USD","amount":"2000.01484","settled_amount":"2000.01484","unsettled_amount":"0","fx_rate":"1","base_value":"2000.01484","base_settled_value":"2000.01484","base_unsettled_value":"0","interest":"0.01484","base_interest":"0.01484"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","settled_quantity":"0","unsettled_quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","execution_fee_components":[],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000.01484","maintenance_excess":"2000.01484","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"8","event_id":"quote-trade-event-000000000008","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00.000000Z","available_at":"2026-02-03T14:31:01.000000Z","received_at":"2026-02-03T14:31:02.000000Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00.000000Z","available_at":"2026-02-03T14:32:01.000000Z","received_at":"2026-02-03T14:32:02.000000Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00.000000Z","available_at":"2026-02-03T14:33:01.000000Z","received_at":"2026-02-03T14:33:02.000000Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00.000000Z","available_at":"2026-02-03T14:34:01.000000Z","received_at":"2026-02-03T14:34:02.000000Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}],"order_book_events":[]}} +{"contract_version":"1","engine_sequence":"9","event_id":"quote-trade-event-000000000009","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000.01484","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.02968"}} +{"contract_version":"1","engine_sequence":"10","event_id":"quote-trade-event-000000000010","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000001","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"4","price":"99","notional":"396","fee":"10","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}],"executed_at":"2026-02-03T14:33:00.000000Z","slice_sequence":"2"}} +{"contract_version":"1","engine_sequence":"11","event_id":"quote-trade-event-000000000011","causation_ids":["quote-trade-event-000000000010"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"quote-trade-fill-000000000001-settlement","fill_id":"quote-trade-fill-000000000001","instrument_id":"clip-equity","currency":"USD","cash_movement":"-406","position_movement":"4","trade_date":"2026-02-03","due_date":"2026-02-04","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"12","event_id":"quote-trade-event-000000000012","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000002","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"6","price":"100","notional":"600","fee":"10","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}],"executed_at":"2026-02-03T14:34:00.000000Z","slice_sequence":"2"}} +{"contract_version":"1","engine_sequence":"13","event_id":"quote-trade-event-000000000013","causation_ids":["quote-trade-event-000000000012"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"quote-trade-fill-000000000002-settlement","fill_id":"quote-trade-fill-000000000002","instrument_id":"clip-equity","currency":"USD","cash_movement":"-610","position_movement":"6","trade_date":"2026-02-03","due_date":"2026-02-04","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} +{"contract_version":"1","engine_sequence":"14","event_id":"quote-trade-event-000000000014","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","total_fees":"20","cash_interest":"0.02968","settled_cash":"2000.02968","unsettled_cash":"-1016","cash_balances":[{"currency":"USD","amount":"984.02968","settled_amount":"2000.02968","unsettled_amount":"-1016","fx_rate":"1","base_value":"984.02968","base_settled_value":"2000.02968","base_unsettled_value":"-1016","interest":"0.02968","base_interest":"0.02968"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","settled_quantity":"0","unsettled_quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20"}],"margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]}} +{"contract_version":"1","engine_sequence":"15","event_id":"quote-trade-event-000000000015","causation_ids":["quote-trade-event-000000000014"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"9c525db135cd830107ffd151024f807261c5e9403ec4e3734109fab1e0da8623","execution_model":"quote_trade_v1","valuation":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","total_fees":"20","cash_interest":"0.02968","settled_cash":"2000.02968","unsettled_cash":"-1016","cash_balances":[{"currency":"USD","amount":"984.02968","settled_amount":"2000.02968","unsettled_amount":"-1016","fx_rate":"1","base_value":"984.02968","base_settled_value":"2000.02968","base_unsettled_value":"-1016","interest":"0.02968","base_interest":"0.02968"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","settled_quantity":"0","unsettled_quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20"}],"margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":1,"rejected":0,"cancelled":0}}} diff --git a/contracts/v15/fixtures/quote-trade.scenario.json b/contracts/v1/fixtures/quote-trade.scenario.json similarity index 99% rename from contracts/v15/fixtures/quote-trade.scenario.json rename to contracts/v1/fixtures/quote-trade.scenario.json index 6eb58b8..42e6682 100644 --- a/contracts/v15/fixtures/quote-trade.scenario.json +++ b/contracts/v1/fixtures/quote-trade.scenario.json @@ -1,5 +1,5 @@ { - "contract_version": "15", + "contract_version": "1", "metadata": { "producer": "trading-engine", "purpose": "bounded quote and trade replay fixture" @@ -79,7 +79,6 @@ "risk": { "max_gross_exposure": "1000000000", "max_leverage": "1", - "short_borrow_bps": 100, "instrument_policies": [ { "instrument_id": "clip-equity", diff --git a/contracts/v1/fixtures/quote-trade.scenario.jsonl b/contracts/v1/fixtures/quote-trade.scenario.jsonl new file mode 100644 index 0000000..b02c21c --- /dev/null +++ b/contracts/v1/fixtures/quote-trade.scenario.jsonl @@ -0,0 +1,4 @@ +{"contract_version":"1","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine","purpose":"bounded quote and trade replay fixture"},"run_id":"quote-trade","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"clip-equity","symbol":"CLIP","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"clip-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["clip-equity"],"sessions":[{"session_date":"2026-02-02","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-02T14:30:00Z","closes_at":"2026-02-02T21:00:00Z"}]},{"session_date":"2026-02-03","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-03T14:30:00Z","closes_at":"2026-02-03T21:00:00Z"}]},{"session_date":"2026-02-04","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-02-04T14:30:00Z","closes_at":"2026-02-04T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000000","max_leverage":"1","instrument_policies":[{"instrument_id":"clip-equity","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"quote_trade_v1","configuration":{"version":"1","participation_bps":10000,"fee_schedules":[{"schedule_id":"clip-fees-v1","instrument_id":"clip-equity","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"10","rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"clip-equity","calendar_id":"default-settlement","lag_business_days":1}]}}} +{"contract_version":"1","scenario_sequence":"2","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00Z","end_at":"2026-02-02T21:00:00Z","available_at":"2026-02-02T21:00:01Z","received_at":"2026-02-02T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]},"intents":[{"type":"submit_order","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null}]}} +{"contract_version":"1","scenario_sequence":"3","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00Z","end_at":"2026-02-03T21:00:00Z","available_at":"2026-02-03T21:00:01Z","received_at":"2026-02-03T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00Z","available_at":"2026-02-03T14:31:01Z","received_at":"2026-02-03T14:31:02Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00Z","available_at":"2026-02-03T14:32:01Z","received_at":"2026-02-03T14:32:02Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00Z","available_at":"2026-02-03T14:33:01Z","received_at":"2026-02-03T14:33:02Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00Z","available_at":"2026-02-03T14:34:01Z","received_at":"2026-02-03T14:34:02Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}],"order_book_events":[]},"intents":[]}} +{"contract_version":"1","scenario_sequence":"4","record_type":"scenario_end","payload":{"slice_count":"2"}} diff --git a/contracts/v1/journal.schema.json b/contracts/v1/journal.schema.json index 4308c58..a181854 100644 --- a/contracts/v1/journal.schema.json +++ b/contracts/v1/journal.schema.json @@ -7,82 +7,400 @@ "required": [ "contract_version", "engine_sequence", + "event_id", + "causation_ids", "run_id", "recorded_at", "event_type", "payload" ], "properties": { - "contract_version": { "const": "1" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, + "contract_version": { + "const": "1" + }, + "engine_sequence": { + "$ref": "#/$defs/sequence" + }, + "event_id": { + "$ref": "#/$defs/identifier" + }, + "causation_ids": { + "type": "array", + "uniqueItems": true, + "items": { + "$ref": "#/$defs/identifier" + } + }, + "run_id": { + "$ref": "#/$defs/identifier" + }, + "recorded_at": { + "$ref": "#/$defs/timestamp" + }, "event_type": { "enum": [ "run_started", + "initial_state", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", + "order_triggered", "order_cancelled", + "split_applied", + "cash_dividend_applied", + "distribution_applied", + "lifecycle_applied", + "order_adjusted", + "execution_price_selected", "fill_applied", - "cash_limited", + "settlement_instruction_created", + "settlement_completed", + "settlement_failed", + "fill_clipped", + "borrow_charge_applied", + "borrow_recall_received", + "cash_interest_applied", + "margin_call", + "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed" ] }, - "payload": { "type": "object" } + "payload": { + "type": "object" + } }, "allOf": [ { - "if": { "properties": { "event_type": { "const": "run_started" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } + "if": { "properties": { "event_type": { "const": "execution_price_selected" } } }, + "then": { "properties": { "payload": { "$ref": "#/$defs/executionPriceSelected" } } } + }, + { + "if": { + "properties": { + "event_type": { + "const": "run_started" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/runStarted" + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "initial_state" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/initialState" + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "market_slice_received" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/marketSlice" + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "target_portfolio_requested" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/targetPortfolio" + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "enum": [ + "order_accepted", + "order_rejected", + "order_triggered" + ] + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/order" + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "order_cancelled" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/orderCancelled" + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "split_applied" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/splitApplied" + } + } + } + }, + { + "if": { + "properties": { + "event_type": { + "const": "cash_dividend_applied" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/dividendApplied" + } + } + } + }, + { + "if": { "properties": { "event_type": { "const": "distribution_applied" } } }, + "then": { "properties": { "payload": { "$ref": "#/$defs/distributionApplied" } } } + }, + { + "if": { "properties": { "event_type": { "const": "lifecycle_applied" } } }, + "then": { "properties": { "payload": { "$ref": "#/$defs/lifecycleApplied" } } } }, { - "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } + "if": { + "properties": { + "event_type": { + "const": "order_adjusted" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/orderAdjusted" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } + "if": { + "properties": { + "event_type": { + "const": "fill_applied" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/fill" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "order_accepted" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } + "if": { + "properties": { + "event_type": { + "enum": [ + "settlement_instruction_created", + "settlement_completed", + "settlement_failed" + ] + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/settlementInstruction" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "order_rejected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } + "if": { + "properties": { + "event_type": { + "const": "fill_clipped" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/fillClipped" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } + "if": { + "properties": { + "event_type": { + "const": "borrow_charge_applied" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/borrowCharge" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "fill_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } + "if": { + "properties": { + "event_type": { + "const": "borrow_recall_received" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/borrowRecall" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "cash_limited" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/cashLimited" } } } + "if": { + "properties": { + "event_type": { + "const": "cash_interest_applied" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/cashInterest" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } + "if": { + "properties": { + "event_type": { + "enum": [ + "margin_call", + "margin_restored", + "valuation" + ] + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/valuation" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } + "if": { + "properties": { + "event_type": { + "const": "intent_rejected" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/intentRejected" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "valuation" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } + "if": { + "properties": { + "event_type": { + "const": "metric_emitted" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/metric" + } + } + } }, { - "if": { "properties": { "event_type": { "const": "run_completed" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } + "if": { + "properties": { + "event_type": { + "const": "run_completed" + } + } + }, + "then": { + "properties": { + "payload": { + "$ref": "#/$defs/runCompleted" + } + } + } } ], "$defs": { @@ -91,58 +409,190 @@ "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "unsignedDecimal": { + "signedDecimal": { "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)(?:[.][0-9]{0,5}[1-9])?$" + "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "signedDecimal": { + "unsignedDecimal": { "type": "string", - "pattern": "^(?:0(?:[.][0-9]{0,5}[1-9])?|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?|-(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" + "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "weight": { + "sequence": { "type": "string", - "pattern": "^(?:0(?:[.][0-9]{0,5}[1-9])?|1)$" + "pattern": "^[1-9][0-9]*$" }, - "quantity": { + "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "positiveQuantity": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "runStarted": { "type": "object", "additionalProperties": false, - "required": ["scenario_sha256"], - "properties": { "scenario_sha256": { "$ref": "#/$defs/sha256" } } + "required": [ + "scenario_sha256", + "execution_model" + ], + "properties": { + "scenario_sha256": { + "type": "string", + "pattern": "^[0-9a-f]{64}$" + }, + "execution_model": { + "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1", "order_book_v1"] + } + } + }, + "initialState": { + "type": "object", + "additionalProperties": false, + "required": [ + "portfolio", + "valuation" + ], + "properties": { + "portfolio": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/initialPortfolio" + }, + "valuation": { + "$ref": "#/$defs/valuation" + } + } }, "bar": { "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], + "required": [ + "instrument_id", + "open", + "high", + "low", + "close", + "volume" + ], "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "open": { + "$ref": "#/$defs/positiveDecimal" + }, + "high": { + "$ref": "#/$defs/positiveDecimal" + }, + "low": { + "$ref": "#/$defs/positiveDecimal" + }, + "close": { + "$ref": "#/$defs/positiveDecimal" + }, "volume": { "oneOf": [ - { "$ref": "#/$defs/quantity" }, - { "type": "null" } + { + "type": "null" + }, + { + "$ref": "#/$defs/unsignedDecimal" + } ] } } }, + "fxRate": { + "type": "object", + "additionalProperties": false, + "required": [ + "currency", + "rate" + ], + "properties": { + "currency": { + "$ref": "#/$defs/identifier" + }, + "rate": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "corporateAction": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "action_id", + "instrument_id", + "numerator", + "denominator" + ], + "properties": { + "type": { + "const": "split" + }, + "action_id": { + "$ref": "#/$defs/identifier" + }, + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "numerator": { + "$ref": "#/$defs/sequence" + }, + "denominator": { + "$ref": "#/$defs/sequence" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "type", + "action_id", + "instrument_id", + "amount_per_unit" + ], + "properties": { + "type": { + "const": "cash_dividend" + }, + "action_id": { + "$ref": "#/$defs/identifier" + }, + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "amount_per_unit": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], + "properties": { + "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, + "action_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "destination_instrument_id": { "$ref": "#/$defs/identifier" }, + "numerator": { "$ref": "#/$defs/sequence" }, + "denominator": { "$ref": "#/$defs/sequence" }, + "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, + "fractional_policy": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/fractionalPolicy" } + } + } + ] + }, "marketSlice": { "type": "object", "additionalProperties": false, @@ -152,72 +602,166 @@ "end_at", "available_at", "received_at", - "bars" + "bars", + "fx_rates", + "corporate_actions", + "borrow_observations", + "cash_rate_observations", + "settlement_failures", + "lifecycle_events", + "market_events", + "order_book_events" ], "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, + "slice_sequence": { + "$ref": "#/$defs/sequence" + }, + "start_at": { + "$ref": "#/$defs/timestamp" + }, + "end_at": { + "$ref": "#/$defs/timestamp" + }, + "available_at": { + "$ref": "#/$defs/timestamp" + }, + "received_at": { + "$ref": "#/$defs/timestamp" + }, "bars": { "type": "array", "minItems": 1, - "items": { "$ref": "#/$defs/bar" } + "items": { + "$ref": "#/$defs/bar" + } + }, + "fx_rates": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/fxRate" + } + }, + "corporate_actions": { + "type": "array", + "items": { + "$ref": "#/$defs/corporateAction" + } + }, + "borrow_observations": { + "type": "array", + "items": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/borrowObservation" + } + }, + "cash_rate_observations": { + "type": "array", + "items": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/cashRateObservation" + } + }, + "settlement_failures": { + "type": "array", + "items": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/settlementFailure" + } + }, + "lifecycle_events": { + "type": "array", + "items": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/lifecycleEvent" + } + }, + "market_events": { + "type": "array", + "items": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/marketEvent" + } + }, + "order_book_events": { + "type": "array", + "items": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/orderBookEvent" + } } } }, - "requestedWeightTarget": { + "settlementInstruction": { "type": "object", "additionalProperties": false, - "required": ["instrument_id", "weight", "quantity", "reference_price"], + "required": ["instruction_id", "fill_id", "instrument_id", "currency", "cash_movement", "position_movement", "trade_date", "due_date", "status", "settled_at", "failed_at", "failure_reason"], "properties": { + "instruction_id": { "$ref": "#/$defs/identifier" }, + "fill_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/weight" }, - "quantity": { "$ref": "#/$defs/quantity" }, - "reference_price": { "$ref": "#/$defs/positiveDecimal" } + "currency": { "$ref": "#/$defs/identifier" }, + "cash_movement": { "$ref": "#/$defs/signedDecimal" }, + "position_movement": { "$ref": "#/$defs/signedDecimal" }, + "trade_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, + "due_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, + "status": { "enum": ["pending", "settled", "failed"] }, + "settled_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, + "failed_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, + "failure_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" }] } } }, - "requestedQuantityTarget": { + "targetPortfolio": { "type": "object", "additionalProperties": false, - "required": ["instrument_id", "weight", "quantity", "reference_price"], + "required": [ + "basis", + "targets" + ], "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "type": "null" }, - "quantity": { "$ref": "#/$defs/quantity" }, - "reference_price": { "type": "null" } - } - }, - "targetPortfolio": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["basis", "targets"], - "properties": { - "basis": { "const": "weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/requestedWeightTarget" } - } - } + "basis": { + "enum": [ + "weights", + "quantities" + ] }, - { - "type": "object", - "additionalProperties": false, - "required": ["basis", "targets"], - "properties": { - "basis": { "const": "quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/requestedQuantityTarget" } + "targets": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "instrument_id", + "weight", + "quantity", + "reference_price" + ], + "properties": { + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "weight": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/signedDecimal" + } + ] + }, + "quantity": { + "$ref": "#/$defs/signedDecimal" + }, + "reference_price": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/positiveDecimal" + } + ] + } } } } - ] + } }, "order": { "type": "object", @@ -228,49 +772,321 @@ "side", "quantity", "order_kind", + "trigger_price", "limit_price", + "time_in_force", + "venue_id", + "calendar_id", + "expires_at", "origin", + "created_event_id", + "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", + "triggered_at", + "triggered_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason" ], "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveQuantity" }, - "order_kind": { "enum": ["market", "limit"] }, + "order_id": { + "$ref": "#/$defs/identifier" + }, + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "side": { + "enum": [ + "buy", + "sell" + ] + }, + "quantity": { + "$ref": "#/$defs/positiveDecimal" + }, + "order_kind": { + "enum": [ + "market", + "limit", + "stop", + "stop_limit" + ] + }, + "trigger_price": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/positiveDecimal" + } + ] + }, "limit_price": { "oneOf": [ - { "$ref": "#/$defs/positiveDecimal" }, - { "type": "null" } + { + "type": "null" + }, + { + "$ref": "#/$defs/positiveDecimal" + } ] }, - "origin": { "enum": ["direct", "target_rebalance"] }, - "created_sequence": { "$ref": "#/$defs/sequence" }, - "created_at": { "$ref": "#/$defs/timestamp" }, - "eligible_after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "filled_quantity": { "$ref": "#/$defs/quantity" }, - "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, + "time_in_force": { + "enum": [ + "gtc", + "ioc", + "fok", + "day", + "gtd" + ] + }, + "venue_id": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/identifier" + } + ] + }, + "calendar_id": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/identifier" + } + ] + }, + "expires_at": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/timestamp" + } + ] + }, + "origin": { + "enum": [ + "direct", + "target_rebalance", + "margin_liquidation", + "borrow_recall", + "instrument_halt", + "instrument_terminal" + ] + }, + "created_event_id": { + "$ref": "#/$defs/identifier" + }, + "updated_event_id": { + "$ref": "#/$defs/identifier" + }, + "created_sequence": { + "$ref": "#/$defs/sequence" + }, + "created_at": { + "$ref": "#/$defs/timestamp" + }, + "eligible_after_slice_sequence": { + "$ref": "#/$defs/nonnegativeSequence" + }, + "triggered_at": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/timestamp" + } + ] + }, + "triggered_slice_sequence": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/sequence" + } + ] + }, + "filled_quantity": { + "$ref": "#/$defs/unsignedDecimal" + }, + "filled_notional": { + "$ref": "#/$defs/unsignedDecimal" + }, "status": { - "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] + "enum": [ + "working", + "partially_filled", + "filled", + "cancelled", + "rejected" + ] }, "rejection_reason": { - "oneOf": [{ "type": "string" }, { "type": "null" }] + "oneOf": [ + { + "type": "null" + }, + { + "type": "string", + "minLength": 1 + } + ] } } }, "orderCancelled": { "type": "object", "additionalProperties": false, - "required": ["order", "reason"], + "required": [ + "order", + "reason" + ], + "properties": { + "order": { + "$ref": "#/$defs/order" + }, + "reason": { + "enum": [ + "strategy_requested", + "target_replaced", + "market_ioc", + "immediate_or_cancel", + "fill_or_kill", + "day_expired", + "gtd_expired", + "margin_call", + "borrow_recall" + ] + } + } + }, + "splitApplied": { + "type": "object", + "additionalProperties": false, + "required": [ + "action", + "previous_quantity", + "adjusted_quantity" + ], + "properties": { + "action": { + "$ref": "#/$defs/corporateAction" + }, + "previous_quantity": { + "$ref": "#/$defs/signedDecimal" + }, + "adjusted_quantity": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "dividendApplied": { + "type": "object", + "additionalProperties": false, + "required": [ + "action", + "quantity", + "cash_amount" + ], + "properties": { + "action": { + "$ref": "#/$defs/corporateAction" + }, + "quantity": { + "$ref": "#/$defs/signedDecimal" + }, + "cash_amount": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "distributionApplied": { + "type": "object", + "additionalProperties": false, + "required": ["action", "source_quantity", "destination_quantity", "fractional_quantity", "allocated_basis", "fractional_basis", "cash_in_lieu"], + "properties": { + "action": { "$ref": "#/$defs/corporateAction" }, + "source_quantity": { "$ref": "#/$defs/signedDecimal" }, + "destination_quantity": { "$ref": "#/$defs/signedDecimal" }, + "fractional_quantity": { "$ref": "#/$defs/signedDecimal" }, + "allocated_basis": { "$ref": "#/$defs/signedDecimal" }, + "fractional_basis": { "$ref": "#/$defs/signedDecimal" }, + "cash_in_lieu": { "$ref": "#/$defs/signedDecimal" } + } + }, + "lifecycleApplied": { + "type": "object", + "additionalProperties": false, + "required": ["lifecycle_event", "listing", "liquidated_quantity", "cash_amount"], + "properties": { + "lifecycle_event": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/lifecycleEvent" }, + "listing": { + "type": "object", + "additionalProperties": false, + "required": ["instrument_id", "symbol", "status", "provider_mappings"], + "properties": { + "instrument_id": { "$ref": "#/$defs/identifier" }, + "symbol": { "$ref": "#/$defs/identifier" }, + "status": { "enum": ["tradable", "halted", "expired", "delisted"] }, + "provider_mappings": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["provider", "provider_instrument_id"], + "properties": { + "provider": { "$ref": "#/$defs/identifier" }, + "provider_instrument_id": { "$ref": "#/$defs/identifier" } + } + } + } + } + }, + "liquidated_quantity": { "$ref": "#/$defs/signedDecimal" }, + "cash_amount": { "$ref": "#/$defs/signedDecimal" } + } + }, + "orderAdjusted": { + "type": "object", + "additionalProperties": false, + "required": [ + "order", + "action_id" + ], + "properties": { + "order": { + "$ref": "#/$defs/order" + }, + "action_id": { + "$ref": "#/$defs/identifier" + } + } + }, + "executionPriceSelected": { + "type": "object", + "additionalProperties": false, + "required": ["order_id", "instrument_id", "side", "reference_price", "spread_adjustment", "impact_adjustment", "final_price"], "properties": { - "order": { "$ref": "#/$defs/order" }, - "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc"] } + "order_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "side": { "enum": ["buy", "sell"] }, + "reference_price": { "$ref": "#/$defs/positiveDecimal" }, + "spread_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, + "impact_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, + "final_price": { "$ref": "#/$defs/positiveDecimal" } } }, "fill": { @@ -280,102 +1096,1286 @@ "fill_id", "order_id", "instrument_id", + "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", - "slice_sequence" + "slice_sequence", + "fee_components" ], "properties": { - "fill_id": { "$ref": "#/$defs/identifier" }, - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveQuantity" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "notional": { "$ref": "#/$defs/unsignedDecimal" }, - "fee": { "$ref": "#/$defs/unsignedDecimal" }, - "executed_at": { "$ref": "#/$defs/timestamp" }, - "slice_sequence": { "$ref": "#/$defs/sequence" } + "fill_id": { + "$ref": "#/$defs/identifier" + }, + "order_id": { + "$ref": "#/$defs/identifier" + }, + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "quote_currency": { + "$ref": "#/$defs/identifier" + }, + "side": { + "enum": [ + "buy", + "sell" + ] + }, + "quantity": { + "$ref": "#/$defs/positiveDecimal" + }, + "price": { + "$ref": "#/$defs/positiveDecimal" + }, + "notional": { + "$ref": "#/$defs/positiveDecimal" + }, + "fee": { + "$ref": "#/$defs/signedDecimal" + }, + "fee_components": { + "type": "array", + "items": { + "$ref": "#/$defs/calculatedFeeComponent" + } + }, + "executed_at": { + "$ref": "#/$defs/timestamp" + }, + "slice_sequence": { + "$ref": "#/$defs/sequence" + } } }, - "cashLimited": { + "calculatedFeeComponent": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "kind", + "currency", + "amount", + "quote_amount" + ], + "properties": { + "name": { + "$ref": "#/$defs/identifier" + }, + "kind": { + "enum": [ + "fixed", + "notional_bps", + "per_unit", + "minimum_adjustment", + "maximum_adjustment" + ] + }, + "currency": { + "$ref": "#/$defs/identifier" + }, + "amount": { + "$ref": "#/$defs/signedDecimal" + }, + "quote_amount": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "feeComponentAttribution": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "kind", + "currency", + "amount", + "quote_currency", + "quote_amount", + "base_amount" + ], + "properties": { + "name": { + "$ref": "#/$defs/identifier" + }, + "kind": { + "enum": [ + "fixed", + "notional_bps", + "per_unit", + "minimum_adjustment", + "maximum_adjustment" + ] + }, + "currency": { + "$ref": "#/$defs/identifier" + }, + "amount": { + "$ref": "#/$defs/signedDecimal" + }, + "quote_currency": { + "$ref": "#/$defs/identifier" + }, + "quote_amount": { + "$ref": "#/$defs/signedDecimal" + }, + "base_amount": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "quantityThreshold": { + "type": "object", + "additionalProperties": false, + "required": [ + "unit", + "value" + ], + "properties": { + "unit": { + "const": "quantity" + }, + "value": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "moneyThreshold": { + "type": "object", + "additionalProperties": false, + "required": [ + "unit", + "value" + ], + "properties": { + "unit": { + "const": "money" + }, + "value": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "ratioThreshold": { + "type": "object", + "additionalProperties": false, + "required": [ + "unit", + "value" + ], + "properties": { + "unit": { + "const": "ratio" + }, + "value": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "basisPointsThreshold": { + "type": "object", + "additionalProperties": false, + "required": [ + "unit", + "value" + ], + "properties": { + "unit": { + "const": "basis_points" + }, + "value": { + "type": "integer", + "minimum": 1, + "maximum": 10000 + } + } + }, + "instrumentQuantityThreshold": { "type": "object", "additionalProperties": false, "required": [ - "order_id", "instrument_id", - "requested_quantity", - "affordable_quantity", - "price" + "unit", + "value" ], "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "requested_quantity": { "$ref": "#/$defs/positiveQuantity" }, - "affordable_quantity": { "$ref": "#/$defs/quantity" }, - "price": { "$ref": "#/$defs/positiveDecimal" } + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "unit": { + "const": "quantity" + }, + "value": { + "$ref": "#/$defs/positiveDecimal" + } } }, - "intentRejected": { + "instrumentMoneyThreshold": { + "type": "object", + "additionalProperties": false, + "required": [ + "instrument_id", + "unit", + "value" + ], + "properties": { + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "unit": { + "const": "money" + }, + "value": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "currencyMoneyThreshold": { "type": "object", "additionalProperties": false, - "required": ["reason"], - "properties": { "reason": { "type": "string", "minLength": 1 } } + "required": ["currency", "unit", "value"], + "properties": { + "currency": { "$ref": "#/$defs/identifier" }, + "unit": { "const": "money" }, + "value": { "$ref": "#/$defs/unsignedDecimal" } + } }, - "metric": { + "settlementPositionThreshold": { "type": "object", "additionalProperties": false, - "required": ["name", "value"], + "required": ["instrument_id", "unit", "value"], "properties": { - "name": { "type": "string", "minLength": 1 }, - "value": { "type": "string" } + "instrument_id": { "$ref": "#/$defs/identifier" }, + "unit": { "const": "quantity" }, + "value": { "$ref": "#/$defs/unsignedDecimal" } } }, - "valuation": { + "instrumentBasisPointsThreshold": { "type": "object", "additionalProperties": false, "required": [ - "cash", - "market_value", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "total_fees" + "instrument_id", + "unit", + "value" ], "properties": { - "cash": { "$ref": "#/$defs/unsignedDecimal" }, - "market_value": { "$ref": "#/$defs/unsignedDecimal" }, - "cost_basis": { "$ref": "#/$defs/unsignedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "equity": { "$ref": "#/$defs/unsignedDecimal" }, - "total_fees": { "$ref": "#/$defs/unsignedDecimal" } + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "unit": { + "const": "basis_points" + }, + "value": { + "type": "integer", + "minimum": 1, + "maximum": 10000 + } } }, - "orderCounts": { + "instrumentShortingThreshold": { "type": "object", "additionalProperties": false, - "required": ["total", "active", "filled", "rejected", "cancelled"], + "required": [ + "instrument_id", + "value" + ], "properties": { - "total": { "type": "integer", "minimum": 0 }, - "active": { "type": "integer", "minimum": 0 }, - "filled": { "type": "integer", "minimum": 0 }, - "rejected": { "type": "integer", "minimum": 0 }, - "cancelled": { "type": "integer", "minimum": 0 } + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "value": { + "const": false + } } }, - "runCompleted": { + "groupMoneyThreshold": { + "type": "object", + "additionalProperties": false, + "required": [ + "group_id", + "unit", + "value" + ], + "properties": { + "group_id": { + "$ref": "#/$defs/identifier" + }, + "unit": { + "const": "money" + }, + "value": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "groupRatioThreshold": { "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "valuation", "order_counts"], + "required": [ + "group_id", + "unit", + "value" + ], "properties": { - "scenario_sha256": { "$ref": "#/$defs/sha256" }, - "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "$ref": "#/$defs/orderCounts" } + "group_id": { + "$ref": "#/$defs/identifier" + }, + "unit": { + "const": "ratio" + }, + "value": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "fillClipReason": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "max_order_quantity" + }, + "threshold": { + "$ref": "#/$defs/quantityThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "max_long_position" + }, + "threshold": { + "$ref": "#/$defs/quantityThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "max_short_position" + }, + "threshold": { + "$ref": "#/$defs/quantityThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "max_gross_exposure" + }, + "threshold": { + "$ref": "#/$defs/moneyThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "max_leverage" + }, + "threshold": { + "$ref": "#/$defs/ratioThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "initial_margin" + }, + "threshold": { + "$ref": "#/$defs/basisPointsThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "instrument_max_long_position" + }, + "threshold": { + "$ref": "#/$defs/instrumentQuantityThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["version", "policy", "threshold"], + "properties": { + "version": { "const": "1" }, + "policy": { "const": "settlement_cash_buying_power" }, + "threshold": { "$ref": "#/$defs/currencyMoneyThreshold" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["version", "policy", "threshold"], + "properties": { + "version": { "const": "1" }, + "policy": { "const": "settlement_position_availability" }, + "threshold": { "$ref": "#/$defs/settlementPositionThreshold" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "instrument_max_short_position" + }, + "threshold": { + "$ref": "#/$defs/instrumentQuantityThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "instrument_max_notional_exposure" + }, + "threshold": { + "$ref": "#/$defs/instrumentMoneyThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "instrument_shorting_disabled" + }, + "threshold": { + "$ref": "#/$defs/instrumentShortingThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "instrument_borrow_availability" + }, + "threshold": { + "$ref": "#/$defs/instrumentQuantityThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "instrument_initial_margin" + }, + "threshold": { + "$ref": "#/$defs/instrumentBasisPointsThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "group_max_gross_exposure" + }, + "threshold": { + "$ref": "#/$defs/groupMoneyThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "group_max_long_exposure" + }, + "threshold": { + "$ref": "#/$defs/groupMoneyThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "group_max_short_exposure" + }, + "threshold": { + "$ref": "#/$defs/groupMoneyThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "group_max_absolute_net_exposure" + }, + "threshold": { + "$ref": "#/$defs/groupMoneyThreshold" + } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "version", + "policy", + "threshold" + ], + "properties": { + "version": { + "const": "1" + }, + "policy": { + "const": "group_max_concentration" + }, + "threshold": { + "$ref": "#/$defs/groupRatioThreshold" + } + } + } + ] + }, + "fillClipped": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason", + "order_id", + "instrument_id", + "proposed_quantity", + "permitted_quantity", + "price" + ], + "properties": { + "reason": { + "$ref": "#/$defs/fillClipReason" + }, + "order_id": { + "$ref": "#/$defs/identifier" + }, + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "proposed_quantity": { + "$ref": "#/$defs/positiveDecimal" + }, + "permitted_quantity": { + "$ref": "#/$defs/unsignedDecimal" + }, + "price": { + "$ref": "#/$defs/positiveDecimal" + } + } + }, + "borrowCharge": { + "type": "object", + "additionalProperties": false, + "required": [ + "observation", + "quote_currency", + "short_quantity", + "reference_price", + "day_count", + "compounding", + "period_start", + "period_end", + "amount" + ], + "properties": { + "observation": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/borrowObservation" + }, + "quote_currency": { + "$ref": "#/$defs/identifier" + }, + "short_quantity": { + "$ref": "#/$defs/positiveDecimal" + }, + "reference_price": { + "$ref": "#/$defs/positiveDecimal" + }, + "day_count": { + "enum": [ + "actual_365", + "actual_360" + ] + }, + "compounding": { + "enum": [ + "simple", + "daily" + ] + }, + "period_start": { + "$ref": "#/$defs/timestamp" + }, + "period_end": { + "$ref": "#/$defs/timestamp" + }, + "amount": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "borrowRecall": { + "type": "object", + "additionalProperties": false, + "required": [ + "observation", + "short_quantity", + "close_out_quantity" + ], + "properties": { + "observation": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/borrowObservation" + }, + "short_quantity": { + "$ref": "#/$defs/positiveDecimal" + }, + "close_out_quantity": { + "$ref": "#/$defs/unsignedDecimal" + } + } + }, + "cashInterest": { + "type": "object", + "additionalProperties": false, + "required": [ + "observation", + "opening_balance", + "applied_rate_bps", + "day_count", + "compounding", + "period_start", + "period_end", + "amount", + "closing_balance" + ], + "properties": { + "observation": { + "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/cashRateObservation" + }, + "opening_balance": { + "$ref": "#/$defs/signedDecimal" + }, + "applied_rate_bps": { + "type": "integer", + "minimum": -1000000, + "maximum": 1000000 + }, + "day_count": { + "enum": [ + "actual_365", + "actual_360" + ] + }, + "compounding": { + "enum": [ + "simple", + "daily" + ] + }, + "period_start": { + "$ref": "#/$defs/timestamp" + }, + "period_end": { + "$ref": "#/$defs/timestamp" + }, + "amount": { + "$ref": "#/$defs/signedDecimal" + }, + "closing_balance": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "cashAttribution": { + "type": "object", + "additionalProperties": false, + "required": [ + "currency", + "amount", + "fx_rate", + "base_value", + "interest", + "base_interest", + "settled_amount", + "unsettled_amount", + "base_settled_value", + "base_unsettled_value" + ], + "properties": { + "currency": { + "$ref": "#/$defs/identifier" + }, + "amount": { + "$ref": "#/$defs/signedDecimal" + }, + "fx_rate": { + "$ref": "#/$defs/positiveDecimal" + }, + "base_value": { + "$ref": "#/$defs/signedDecimal" + }, + "interest": { + "$ref": "#/$defs/signedDecimal" + }, + "base_interest": { + "$ref": "#/$defs/signedDecimal" + }, + "settled_amount": { + "$ref": "#/$defs/signedDecimal" + }, + "unsettled_amount": { + "$ref": "#/$defs/signedDecimal" + }, + "base_settled_value": { + "$ref": "#/$defs/signedDecimal" + }, + "base_unsettled_value": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "positionAttribution": { + "type": "object", + "additionalProperties": false, + "required": [ + "instrument_id", + "quote_currency", + "quantity", + "settled_quantity", + "unsettled_quantity", + "mark", + "fx_rate", + "market_value", + "base_market_value", + "cost_basis", + "base_cost_basis", + "realized_pnl", + "base_realized_pnl", + "unrealized_pnl", + "base_unrealized_pnl", + "dividend_pnl", + "base_dividend_pnl", + "execution_fees", + "base_execution_fees", + "borrow_fees", + "base_borrow_fees", + "total_fees", + "base_total_fees", + "execution_fee_components" + ], + "properties": { + "instrument_id": { + "$ref": "#/$defs/identifier" + }, + "quote_currency": { + "$ref": "#/$defs/identifier" + }, + "quantity": { + "$ref": "#/$defs/signedDecimal" + }, + "settled_quantity": { + "$ref": "#/$defs/signedDecimal" + }, + "unsettled_quantity": { + "$ref": "#/$defs/signedDecimal" + }, + "mark": { + "$ref": "#/$defs/positiveDecimal" + }, + "fx_rate": { + "$ref": "#/$defs/positiveDecimal" + }, + "market_value": { + "$ref": "#/$defs/signedDecimal" + }, + "base_market_value": { + "$ref": "#/$defs/signedDecimal" + }, + "cost_basis": { + "$ref": "#/$defs/signedDecimal" + }, + "base_cost_basis": { + "$ref": "#/$defs/signedDecimal" + }, + "realized_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "base_realized_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "unrealized_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "base_unrealized_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "dividend_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "base_dividend_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "execution_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "base_execution_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "borrow_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "base_borrow_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "total_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "base_total_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "execution_fee_components": { + "type": "array", + "items": { + "$ref": "#/$defs/feeComponentAttribution" + } + } + } + }, + "margin": { + "type": "object", + "additionalProperties": false, + "required": [ + "initial_requirement", + "maintenance_requirement", + "initial_excess", + "maintenance_excess", + "margin_call" + ], + "properties": { + "initial_requirement": { + "$ref": "#/$defs/unsignedDecimal" + }, + "maintenance_requirement": { + "$ref": "#/$defs/unsignedDecimal" + }, + "initial_excess": { + "$ref": "#/$defs/signedDecimal" + }, + "maintenance_excess": { + "$ref": "#/$defs/signedDecimal" + }, + "margin_call": { + "type": "boolean" + } + } + }, + "groupExposure": { + "type": "object", + "additionalProperties": false, + "required": [ + "group_id", + "gross_exposure", + "net_exposure", + "long_exposure", + "short_exposure", + "concentration" + ], + "properties": { + "group_id": { + "$ref": "#/$defs/identifier" + }, + "gross_exposure": { + "$ref": "#/$defs/unsignedDecimal" + }, + "net_exposure": { + "$ref": "#/$defs/signedDecimal" + }, + "long_exposure": { + "$ref": "#/$defs/unsignedDecimal" + }, + "short_exposure": { + "$ref": "#/$defs/unsignedDecimal" + }, + "concentration": { + "oneOf": [ + { + "type": "null" + }, + { + "$ref": "#/$defs/signedDecimal" + } + ] + } + } + }, + "valuation": { + "type": "object", + "additionalProperties": false, + "required": [ + "base_currency", + "cash", + "settled_cash", + "unsettled_cash", + "net_market_value", + "long_market_value", + "short_market_value", + "gross_exposure", + "cost_basis", + "realized_pnl", + "unrealized_pnl", + "equity", + "dividend_pnl", + "execution_fees", + "borrow_fees", + "cash_interest", + "total_fees", + "cash_balances", + "positions", + "margin", + "group_exposures", + "execution_fee_components" + ], + "properties": { + "base_currency": { + "$ref": "#/$defs/identifier" + }, + "cash": { + "$ref": "#/$defs/signedDecimal" + }, + "settled_cash": { + "$ref": "#/$defs/signedDecimal" + }, + "unsettled_cash": { + "$ref": "#/$defs/signedDecimal" + }, + "net_market_value": { + "$ref": "#/$defs/signedDecimal" + }, + "long_market_value": { + "$ref": "#/$defs/unsignedDecimal" + }, + "short_market_value": { + "$ref": "#/$defs/unsignedDecimal" + }, + "gross_exposure": { + "$ref": "#/$defs/unsignedDecimal" + }, + "cost_basis": { + "$ref": "#/$defs/signedDecimal" + }, + "realized_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "unrealized_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "equity": { + "$ref": "#/$defs/signedDecimal" + }, + "dividend_pnl": { + "$ref": "#/$defs/signedDecimal" + }, + "execution_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "borrow_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "total_fees": { + "$ref": "#/$defs/signedDecimal" + }, + "cash_balances": { + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/$defs/cashAttribution" + } + }, + "positions": { + "type": "array", + "items": { + "$ref": "#/$defs/positionAttribution" + } + }, + "margin": { + "$ref": "#/$defs/margin" + }, + "group_exposures": { + "type": "array", + "items": { + "$ref": "#/$defs/groupExposure" + } + }, + "execution_fee_components": { + "type": "array", + "items": { + "$ref": "#/$defs/feeComponentAttribution" + } + }, + "cash_interest": { + "$ref": "#/$defs/signedDecimal" + } + } + }, + "intentRejected": { + "type": "object", + "additionalProperties": false, + "required": [ + "reason" + ], + "properties": { + "reason": { + "type": "string", + "minLength": 1 + } + } + }, + "metric": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "value" + ], + "properties": { + "name": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^\\S(?:.*\\S)?$" }, + "value": { "$ref": "#/$defs/metricValue" }, + "unit": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, + "dimensions": { + "type": "object", + "maxProperties": 16, + "propertyNames": { "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, + "additionalProperties": { "type": "string", "maxLength": 128 } + }, + "aggregation": { "enum": ["last", "sum", "minimum", "maximum", "mean"] } + }, + "allOf": [ + { "if": { "properties": { "value": { "properties": { "type": { "enum": ["string", "boolean"] } } } } }, "then": { "properties": { "aggregation": { "enum": ["last"] } } } } + ] + }, + "metricValue": { + "oneOf": [ + { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "numeric" }, "value": { "type": "string", "pattern": "^(0|[1-9][0-9]*|-[1-9][0-9]*)(\\.[0-9]*[1-9])?$|^-0\\.[0-9]*[1-9]$" } } }, + { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "string" }, "value": { "type": "string", "maxLength": 1024 } } }, + { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "boolean" }, "value": { "type": "boolean" } } } + ] + }, + "runCompleted": { + "type": "object", + "additionalProperties": false, + "required": [ + "scenario_sha256", + "execution_model", + "valuation", + "order_counts" + ], + "properties": { + "scenario_sha256": { + "type": "string", + "pattern": "^[0-9a-f]{64}$" + }, + "execution_model": { + "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1", "order_book_v1"] + }, + "valuation": { + "$ref": "#/$defs/valuation" + }, + "order_counts": { + "type": "object", + "additionalProperties": false, + "required": [ + "total", + "active", + "filled", + "rejected", + "cancelled" + ], + "properties": { + "total": { + "type": "integer", + "minimum": 0 + }, + "active": { + "type": "integer", + "minimum": 0 + }, + "filled": { + "type": "integer", + "minimum": 0 + }, + "rejected": { + "type": "integer", + "minimum": 0 + }, + "cancelled": { + "type": "integer", + "minimum": 0 + } + } + } } } } diff --git a/contracts/v1/scenario-stream.schema.json b/contracts/v1/scenario-stream.schema.json index c1c3d91..6743c1a 100644 --- a/contracts/v1/scenario-stream.schema.json +++ b/contracts/v1/scenario-stream.schema.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://github.com/fallblu/trading-engine/contracts/v1/scenario-stream.schema.json", "title": "Trading Engine v1 replay scenario stream record", - "description": "The structural contract for one record in a bounded-memory JSON Lines replay scenario. The engine additionally checks record order, terminal counts, catalog coverage, market ordering, causality, risk, tick, lot, time, and OHLC invariants.", + "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", "oneOf": [ { "$ref": "#/$defs/headerRecord" }, { "$ref": "#/$defs/sliceRecord" }, @@ -12,12 +12,7 @@ "headerRecord": { "type": "object", "additionalProperties": false, - "required": [ - "contract_version", - "scenario_sequence", - "record_type", - "payload" - ], + "required": ["contract_version", "scenario_sequence", "record_type", "payload"], "properties": { "contract_version": { "const": "1" }, "scenario_sequence": { "const": "1" }, @@ -28,17 +23,10 @@ "sliceRecord": { "type": "object", "additionalProperties": false, - "required": [ - "contract_version", - "scenario_sequence", - "record_type", - "payload" - ], + "required": ["contract_version", "scenario_sequence", "record_type", "payload"], "properties": { "contract_version": { "const": "1" }, - "scenario_sequence": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/sequence" - }, + "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/sequence" }, "record_type": { "const": "market_slice" }, "payload": { "$ref": "#/$defs/slicePayload" } } @@ -46,59 +34,35 @@ "endRecord": { "type": "object", "additionalProperties": false, - "required": [ - "contract_version", - "scenario_sequence", - "record_type", - "payload" - ], + "required": ["contract_version", "scenario_sequence", "record_type", "payload"], "properties": { "contract_version": { "const": "1" }, - "scenario_sequence": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/sequence" - }, + "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/sequence" }, "record_type": { "const": "scenario_end" }, - "payload": { "$ref": "#/$defs/endPayload" } + "payload": { + "type": "object", + "additionalProperties": false, + "required": ["slice_count"], + "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } + } } }, "headerPayload": { "type": "object", "additionalProperties": false, - "required": [ - "metadata", - "run_id", - "base_currency", - "initial_cash", - "instruments", - "risk", - "execution", - "max_internal_events" - ], + "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events"], "properties": { "metadata": { "type": "object" }, - "run_id": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" - }, - "base_currency": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" - }, - "initial_cash": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/unsignedDecimal" - }, - "instruments": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/instrument" - } - }, - "risk": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/risk" - }, - "execution": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/execution" - }, - "max_internal_events": { "type": "integer", "minimum": 1 } + "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" }, + "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/identifier" }, + "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/initialPortfolio" }, + "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/instrument" } }, + "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/venueCalendar" } }, + "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/risk" }, + "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/execution" }, + "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/financing" }, + "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/settlement" }, + "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } } }, "slicePayload": { @@ -106,25 +70,8 @@ "additionalProperties": false, "required": ["market_slice", "intents"], "properties": { - "market_slice": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/marketSlice" - }, - "intents": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/intent" - } - } - } - }, - "endPayload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { - "slice_count": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/quantity" - } + "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/marketSlice" }, + "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json#/$defs/intent" } } } } } diff --git a/contracts/v1/scenario.schema.json b/contracts/v1/scenario.schema.json index 2d1ffaf..48d09a1 100644 --- a/contracts/v1/scenario.schema.json +++ b/contracts/v1/scenario.schema.json @@ -2,255 +2,549 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://github.com/fallblu/trading-engine/contracts/v1/scenario.schema.json", "title": "Trading Engine v1 replay scenario", - "description": "The strict structural input contract. The engine additionally checks catalog coverage, ordering, causality, risk, tick, lot, time, and OHLC invariants.", + "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", "type": "object", "additionalProperties": false, - "required": [ - "contract_version", - "metadata", - "run_id", - "base_currency", - "initial_cash", - "instruments", - "risk", - "execution", - "max_internal_events", - "schedule", - "slices" - ], + "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events", "schedule", "slices"], "properties": { "contract_version": { "const": "1" }, "metadata": { "type": "object" }, "run_id": { "$ref": "#/$defs/identifier" }, "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_cash": { "$ref": "#/$defs/unsignedDecimal" }, + "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, "instruments": { "type": "array", "minItems": 1, + "maxItems": 4096, "items": { "$ref": "#/$defs/instrument" } }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1 }, - "schedule": { + "venue_calendars": { "type": "array", - "items": { "$ref": "#/$defs/scheduleItem" } + "minItems": 1, + "items": { "$ref": "#/$defs/venueCalendar" } }, + "risk": { "$ref": "#/$defs/risk" }, + "execution": { "$ref": "#/$defs/execution" }, + "financing": { "$ref": "#/$defs/financing" }, + "settlement": { "$ref": "#/$defs/settlement" }, + "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, + "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, "slices": { + "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", "type": "array", "items": { "$ref": "#/$defs/marketSlice" } } }, "$defs": { + "settlement": { + "type": "object", + "additionalProperties": false, + "required": ["cash_buying_power", "position_availability", "calendars", "rules"], + "properties": { + "cash_buying_power": { "enum": ["total_cash", "settled_cash"] }, + "position_availability": { "enum": ["total_positions", "settled_positions"] }, + "calendars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementCalendar" } }, + "rules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementRule" } } + } + }, + "settlementCalendar": { + "type": "object", + "additionalProperties": false, + "required": ["calendar_id", "version", "business_dates"], + "properties": { + "calendar_id": { "$ref": "#/$defs/identifier" }, + "version": { "const": "1" }, + "business_dates": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } + } + }, + "settlementRule": { + "type": "object", + "additionalProperties": false, + "required": ["instrument_id", "calendar_id", "lag_business_days"], + "properties": { + "instrument_id": { "$ref": "#/$defs/identifier" }, + "calendar_id": { "$ref": "#/$defs/identifier" }, + "lag_business_days": { "type": "integer", "minimum": 0, "maximum": 30 } + } + }, + "settlementFailure": { + "type": "object", + "additionalProperties": false, + "required": ["instruction_id", "reason"], + "properties": { + "instruction_id": { "$ref": "#/$defs/identifier" }, + "reason": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } + } + }, + "financing": { + "type": "object", + "additionalProperties": false, + "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], + "properties": { + "day_count": { "enum": ["actual_365", "actual_360"] }, + "compounding": { "enum": ["simple", "daily"] }, + "borrow_missing_data": { "enum": ["reject", "zero"] }, + "cash_missing_data": { "enum": ["reject", "zero"] }, + "locate_policy": { "enum": ["reject_order", "clip_fill"] }, + "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } + } + }, + "borrowObservation": { + "type": "object", + "additionalProperties": false, + "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], + "properties": { + "instrument_id": { "$ref": "#/$defs/identifier" }, + "effective_at": { "$ref": "#/$defs/timestamp" }, + "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, + "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, + "recalled": { "type": "boolean" } + } + }, + "cashRateObservation": { + "type": "object", + "additionalProperties": false, + "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], + "properties": { + "currency": { "$ref": "#/$defs/identifier" }, + "effective_at": { "$ref": "#/$defs/timestamp" }, + "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, + "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } + } + }, "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, + "signedDecimal": { + "type": "string", + "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" + }, "unsignedDecimal": { "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)(?:[.][0-9]{0,5}[1-9])?$" + "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "weight": { - "type": "string", - "pattern": "^(?:0(?:[.][0-9]{0,5}[1-9])?|1)$" - }, - "quantity": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "positiveQuantity": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, + "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "instrument": { + "cashBalance": { + "type": "object", + "additionalProperties": false, + "required": ["currency", "amount"], + "properties": { + "currency": { "$ref": "#/$defs/identifier" }, + "amount": { "$ref": "#/$defs/signedDecimal" } + } + }, + "initialPortfolio": { "type": "object", "additionalProperties": false, - "required": [ - "instrument_id", - "symbol", - "quote_currency", - "tick_size", - "lot_size" - ], + "required": ["cash", "positions", "marks", "fx_rates"], + "properties": { + "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, + "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, + "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, + "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } + } + }, + "initialPosition": { + "type": "object", + "additionalProperties": false, + "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveQuantity" } + "quantity": { "$ref": "#/$defs/signedDecimal" }, + "cost_basis": { "$ref": "#/$defs/signedDecimal" }, + "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, + "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, + "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, + "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } } }, - "risk": { + "initialMark": { "type": "object", "additionalProperties": false, - "required": ["max_order_quantity", "max_position"], + "required": ["instrument_id", "price"], "properties": { - "max_order_quantity": { "$ref": "#/$defs/positiveQuantity" }, - "max_position": { "$ref": "#/$defs/positiveQuantity" } + "instrument_id": { "$ref": "#/$defs/identifier" }, + "price": { "$ref": "#/$defs/positiveDecimal" } } }, - "execution": { + "instrument": { "type": "object", "additionalProperties": false, - "required": ["participation_bps", "fixed_fee", "fee_bps"], + "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], "properties": { - "participation_bps": { - "type": "integer", - "minimum": 0, - "maximum": 10000 - }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } + "instrument_id": { "$ref": "#/$defs/identifier" }, + "symbol": { "$ref": "#/$defs/identifier" }, + "quote_currency": { "$ref": "#/$defs/identifier" }, + "tick_size": { "$ref": "#/$defs/positiveDecimal" }, + "lot_size": { "$ref": "#/$defs/positiveDecimal" } } }, - "scheduleItem": { + "venueCalendar": { "type": "object", "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], + "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { + "calendar_id": { "$ref": "#/$defs/identifier" }, + "calendar_version": { "const": "1" }, + "venue_id": { "$ref": "#/$defs/identifier" }, + "instrument_ids": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { "$ref": "#/$defs/identifier" } + }, + "sessions": { "type": "array", - "items": { "$ref": "#/$defs/intent" } + "minItems": 1, + "items": { "$ref": "#/$defs/venueSession" } } } }, - "intent": { + "venueSession": { "oneOf": [ - { "$ref": "#/$defs/targetWeightsIntent" }, - { "$ref": "#/$defs/targetQuantitiesIntent" }, - { "$ref": "#/$defs/marketOrderIntent" }, - { "$ref": "#/$defs/limitOrderIntent" }, - { "$ref": "#/$defs/cancelOrderIntent" }, - { "$ref": "#/$defs/metricIntent" } + { "$ref": "#/$defs/openVenueSession" }, + { "$ref": "#/$defs/holidayVenueSession" } ] }, - "targetWeightsIntent": { + "openVenueSession": { "type": "object", "additionalProperties": false, - "required": ["type", "targets"], + "required": ["session_date", "policy", "phases"], "properties": { - "type": { "const": "target_weights" }, - "targets": { + "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, + "policy": { "enum": ["regular", "early_close"] }, + "phases": { "type": "array", "minItems": 1, - "items": { "$ref": "#/$defs/weightTarget" } + "maxItems": 5, + "items": { "$ref": "#/$defs/venuePhase" } } } }, - "weightTarget": { + "holidayVenueSession": { "type": "object", "additionalProperties": false, - "required": ["instrument_id", "weight"], + "required": ["session_date", "policy", "phases"], "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/weight" } + "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, + "policy": { "const": "holiday" }, + "phases": { "type": "array", "maxItems": 0 } } }, - "targetQuantitiesIntent": { + "venuePhase": { "type": "object", "additionalProperties": false, - "required": ["type", "targets"], + "required": ["phase", "opens_at", "closes_at"], "properties": { - "type": { "const": "target_quantities" }, - "targets": { + "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, + "opens_at": { "$ref": "#/$defs/timestamp" }, + "closes_at": { "$ref": "#/$defs/timestamp" } + } + }, + "risk": { + "type": "object", + "additionalProperties": false, + "required": ["max_gross_exposure", "max_leverage", "instrument_policies", "groups"], + "properties": { + "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, + "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, + "instrument_policies": { "type": "array", "minItems": 1, - "items": { "$ref": "#/$defs/quantityTarget" } + "items": { "$ref": "#/$defs/instrumentRiskPolicy" } + }, + "groups": { + "type": "array", + "items": { "$ref": "#/$defs/riskGroup" } } } }, - "quantityTarget": { + "instrumentRiskPolicy": { "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quantity"], + "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/quantity" } + "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, + "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, + "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, + "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, + "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, + "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, + "shorting_allowed": { "type": "boolean" } } }, - "orderFields": { + "nullablePositiveDecimal": { + "oneOf": [ + { "type": "null" }, + { "$ref": "#/$defs/positiveDecimal" } + ] + }, + "riskGroup": { "type": "object", - "required": [ - "type", - "instrument_id", - "side", - "quantity", - "order_kind", - "limit_price" - ], + "additionalProperties": false, + "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveQuantity" } + "group_id": { "$ref": "#/$defs/identifier" }, + "group_version": { "const": "1" }, + "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, + "instrument_ids": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { "$ref": "#/$defs/identifier" } + }, + "limits": { "$ref": "#/$defs/riskGroupLimits" } } }, - "marketOrderIntent": { - "allOf": [ - { "$ref": "#/$defs/orderFields" }, + "riskGroupLimits": { + "type": "object", + "additionalProperties": false, + "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], + "properties": { + "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, + "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, + "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, + "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, + "max_concentration": { + "oneOf": [ + { "type": "null" }, + { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } + ] + } + } + }, + "execution": { + "oneOf": [ { "type": "object", "additionalProperties": false, - "required": [ - "type", - "instrument_id", - "side", - "quantity", - "order_kind", - "limit_price" - ], + "required": ["model", "configuration"], "properties": { - "type": true, - "instrument_id": true, - "side": true, - "quantity": true, - "order_kind": { "const": "market" }, - "limit_price": { "type": "null" } + "model": { "const": "completed_bar_v1" }, + "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } } - } - ] - }, - "limitOrderIntent": { - "allOf": [ - { "$ref": "#/$defs/orderFields" }, + }, { "type": "object", "additionalProperties": false, - "required": [ - "type", - "instrument_id", - "side", - "quantity", - "order_kind", - "limit_price" - ], + "required": ["model", "configuration"], "properties": { - "type": true, - "instrument_id": true, - "side": true, - "quantity": true, - "order_kind": { "const": "limit" }, - "limit_price": { "$ref": "#/$defs/positiveDecimal" } + "model": { "enum": ["completed_bar_next_open_v1", "completed_bar_adverse_touch_v1"] }, + "configuration": { "$ref": "#/$defs/conservativeBarConfiguration" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["model", "configuration"], + "properties": { + "model": { "const": "quote_trade_v1" }, + "configuration": { "$ref": "#/$defs/quoteTradeConfiguration" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["model", "configuration"], + "properties": { + "model": { "const": "order_book_v1" }, + "configuration": { "$ref": "#/$defs/orderBookConfiguration" } } } ] }, - "cancelOrderIntent": { + "completedBarV1Configuration": { + "type": "object", + "additionalProperties": false, + "required": ["version", "participation_bps", "fee_schedules"], + "properties": { + "version": { "const": "1" }, + "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, + "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } + } + }, + "conservativeBarConfiguration": { + "type": "object", + "additionalProperties": false, + "required": ["version", "participation_bps", "fee_schedules", "spread_model", "impact_model"], + "properties": { + "version": { "const": "1" }, + "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, + "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, + "spread_model": { "$ref": "#/$defs/fixedSpreadModel" }, + "impact_model": { "$ref": "#/$defs/linearImpactModel" } + } + }, + "quoteTradeConfiguration": { + "type": "object", + "additionalProperties": false, + "required": ["version", "participation_bps", "fee_schedules"], + "properties": { + "version": { "const": "1" }, + "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, + "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } + } + }, + "orderBookConfiguration": { + "type": "object", + "additionalProperties": false, + "required": ["version", "participation_bps", "fee_schedules", "max_depth_levels"], + "properties": { + "version": { "const": "1" }, + "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, + "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, + "max_depth_levels": { "type": "integer", "minimum": 1, "maximum": 1024 } + } + }, + "fixedSpreadModel": { + "type": "object", + "additionalProperties": false, + "required": ["model", "half_spread_bps"], + "properties": { + "model": { "const": "fixed_half_spread_v1" }, + "half_spread_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } + } + }, + "linearImpactModel": { + "type": "object", + "additionalProperties": false, + "required": ["model", "coefficient_bps", "missing_volume_policy"], + "properties": { + "model": { "const": "linear_participation_v1" }, + "coefficient_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, + "missing_volume_policy": { "enum": ["reject", "zero_impact"] } + } + }, + "feeSchedule": { + "type": "object", + "additionalProperties": false, + "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], + "properties": { + "schedule_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "settlement_currency": { "$ref": "#/$defs/identifier" }, + "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, + "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, + "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } + } + }, + "feeComponent": { + "type": "object", + "additionalProperties": false, + "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], + "properties": { + "name": { "$ref": "#/$defs/identifier" }, + "currency": { "$ref": "#/$defs/identifier" }, + "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, + "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, + "rounding": { "enum": ["up", "down", "nearest"] }, + "applies_to": { "enum": ["any", "maker", "taker"] } + }, + "allOf": [ + { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, + { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } + ] + }, + "scheduleItem": { + "type": "object", + "additionalProperties": false, + "required": ["after_slice_sequence", "intents"], + "properties": { + "after_slice_sequence": { "$ref": "#/$defs/sequence" }, + "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } + } + }, + "intent": { + "oneOf": [ + { "$ref": "#/$defs/targetWeights" }, + { "$ref": "#/$defs/targetQuantities" }, + { "$ref": "#/$defs/submitOrder" }, + { "$ref": "#/$defs/cancelOrder" }, + { "$ref": "#/$defs/metric" } + ] + }, + "targetWeights": { + "type": "object", + "additionalProperties": false, + "required": ["type", "targets"], + "properties": { + "type": { "const": "target_weights" }, + "targets": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["instrument_id", "weight"], + "properties": { + "instrument_id": { "$ref": "#/$defs/identifier" }, + "weight": { "$ref": "#/$defs/signedDecimal" } + } + } + } + } + }, + "targetQuantities": { + "type": "object", + "additionalProperties": false, + "required": ["type", "targets"], + "properties": { + "type": { "const": "target_quantities" }, + "targets": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["instrument_id", "quantity"], + "properties": { + "instrument_id": { "$ref": "#/$defs/identifier" }, + "quantity": { "$ref": "#/$defs/signedDecimal" } + } + } + } + } + }, + "submitOrder": { + "type": "object", + "additionalProperties": false, + "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], + "properties": { + "type": { "const": "submit_order" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "side": { "enum": ["buy", "sell"] }, + "quantity": { "$ref": "#/$defs/positiveDecimal" }, + "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, + "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, + "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, + "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, + "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, + "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, + "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } + }, + "allOf": [ + { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, + { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, + { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, + { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, + { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, + { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, + { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } + ] + }, + "cancelOrder": { "type": "object", "additionalProperties": false, "required": ["type", "order_id"], @@ -259,38 +553,53 @@ "order_id": { "$ref": "#/$defs/identifier" } } }, - "metricIntent": { + "metric": { "type": "object", "additionalProperties": false, "required": ["type", "name", "value"], "properties": { "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } + "name": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^\\S(?:.*\\S)?$" }, + "value": { "$ref": "#/$defs/metricValue" }, + "unit": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, + "dimensions": { + "type": "object", + "maxProperties": 16, + "propertyNames": { "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, + "additionalProperties": { "type": "string", "maxLength": 128 } + }, + "aggregation": { "enum": ["last", "sum", "minimum", "maximum", "mean"] } + }, + "allOf": [ + { "if": { "properties": { "value": { "properties": { "type": { "enum": ["string", "boolean"] } } } } }, "then": { "properties": { "aggregation": { "enum": ["last"] } } } } + ] + }, + "metricValue": { + "oneOf": [ + { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "numeric" }, "value": { "type": "string", "pattern": "^(0|[1-9][0-9]*|-[1-9][0-9]*)(\\.[0-9]*[1-9])?$|^-0\\.[0-9]*[1-9]$" } } }, + { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "string" }, "value": { "type": "string", "maxLength": 1024 } } }, + { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "boolean" }, "value": { "type": "boolean" } } } + ] }, "marketSlice": { "type": "object", "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars" - ], + "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "market_events", "order_book_events", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations", "settlement_failures", "lifecycle_events"], "properties": { "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/bar" } - } + "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, + "market_events": { "type": "array", "items": { "$ref": "#/$defs/marketEvent" } }, + "order_book_events": { "type": "array", "items": { "$ref": "#/$defs/orderBookEvent" } }, + "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, + "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, + "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, + "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } }, + "settlement_failures": { "type": "array", "items": { "$ref": "#/$defs/settlementFailure" } }, + "lifecycle_events": { "type": "array", "items": { "$ref": "#/$defs/lifecycleEvent" } } } }, "bar": { @@ -303,13 +612,276 @@ "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { - "oneOf": [ - { "$ref": "#/$defs/quantity" }, - { "type": "null" } - ] + "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } + } + }, + "marketEvent": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "bid_price", "bid_quantity", "ask_price", "ask_quantity"], + "properties": { + "type": { "const": "quote" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "event_at": { "$ref": "#/$defs/timestamp" }, + "available_at": { "$ref": "#/$defs/timestamp" }, + "received_at": { "$ref": "#/$defs/timestamp" }, + "ingest_sequence": { "$ref": "#/$defs/sequence" }, + "bid_price": { "$ref": "#/$defs/positiveDecimal" }, + "bid_quantity": { "$ref": "#/$defs/positiveDecimal" }, + "ask_price": { "$ref": "#/$defs/positiveDecimal" }, + "ask_quantity": { "$ref": "#/$defs/positiveDecimal" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "price", "quantity", "aggressor_side"], + "properties": { + "type": { "const": "trade" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "event_at": { "$ref": "#/$defs/timestamp" }, + "available_at": { "$ref": "#/$defs/timestamp" }, + "received_at": { "$ref": "#/$defs/timestamp" }, + "ingest_sequence": { "$ref": "#/$defs/sequence" }, + "price": { "$ref": "#/$defs/positiveDecimal" }, + "quantity": { "$ref": "#/$defs/positiveDecimal" }, + "aggressor_side": { "enum": ["buy", "sell", "unknown"] } + } } + ] + }, + "orderBookLevel": { + "type": "object", + "additionalProperties": false, + "required": ["price", "quantity"], + "properties": { + "price": { "$ref": "#/$defs/positiveDecimal" }, + "quantity": { "$ref": "#/$defs/positiveDecimal" } } + }, + "orderBookEvent": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "bids", "asks"], + "properties": { + "type": { "const": "snapshot" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "event_at": { "$ref": "#/$defs/timestamp" }, + "available_at": { "$ref": "#/$defs/timestamp" }, + "received_at": { "$ref": "#/$defs/timestamp" }, + "ingest_sequence": { "$ref": "#/$defs/sequence" }, + "book_sequence": { "$ref": "#/$defs/sequence" }, + "bids": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/orderBookLevel" } }, + "asks": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/orderBookLevel" } } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "side", "price", "quantity"], + "properties": { + "type": { "const": "set" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "event_at": { "$ref": "#/$defs/timestamp" }, + "available_at": { "$ref": "#/$defs/timestamp" }, + "received_at": { "$ref": "#/$defs/timestamp" }, + "ingest_sequence": { "$ref": "#/$defs/sequence" }, + "book_sequence": { "$ref": "#/$defs/sequence" }, + "side": { "enum": ["bid", "ask"] }, + "price": { "$ref": "#/$defs/positiveDecimal" }, + "quantity": { "$ref": "#/$defs/positiveDecimal" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "side", "price"], + "properties": { + "type": { "const": "delete" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "event_at": { "$ref": "#/$defs/timestamp" }, + "available_at": { "$ref": "#/$defs/timestamp" }, + "received_at": { "$ref": "#/$defs/timestamp" }, + "ingest_sequence": { "$ref": "#/$defs/sequence" }, + "book_sequence": { "$ref": "#/$defs/sequence" }, + "side": { "enum": ["bid", "ask"] }, + "price": { "$ref": "#/$defs/positiveDecimal" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "price", "quantity", "aggressor_side"], + "properties": { + "type": { "const": "trade" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "event_at": { "$ref": "#/$defs/timestamp" }, + "available_at": { "$ref": "#/$defs/timestamp" }, + "received_at": { "$ref": "#/$defs/timestamp" }, + "ingest_sequence": { "$ref": "#/$defs/sequence" }, + "book_sequence": { "$ref": "#/$defs/sequence" }, + "price": { "$ref": "#/$defs/positiveDecimal" }, + "quantity": { "$ref": "#/$defs/positiveDecimal" }, + "aggressor_side": { "enum": ["buy", "sell", "unknown"] } + } + } + ] + }, + "fxRate": { + "type": "object", + "additionalProperties": false, + "required": ["currency", "rate"], + "properties": { + "currency": { "$ref": "#/$defs/identifier" }, + "rate": { "$ref": "#/$defs/positiveDecimal" } + } + }, + "corporateAction": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], + "properties": { + "type": { "const": "split" }, + "action_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "numerator": { "$ref": "#/$defs/sequence" }, + "denominator": { "$ref": "#/$defs/sequence" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "action_id", "instrument_id", "amount_per_unit"], + "properties": { + "type": { "const": "cash_dividend" }, + "action_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], + "properties": { + "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, + "action_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "destination_instrument_id": { "$ref": "#/$defs/identifier" }, + "numerator": { "$ref": "#/$defs/sequence" }, + "denominator": { "$ref": "#/$defs/sequence" }, + "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, + "fractional_policy": { "$ref": "#/$defs/fractionalPolicy" } + } + } + ] + }, + "fractionalPolicy": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["policy"], + "properties": { "policy": { "const": "reject" } } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["policy", "price", "currency"], + "properties": { + "policy": { "const": "cash_in_lieu" }, + "price": { "$ref": "#/$defs/positiveDecimal" }, + "currency": { "$ref": "#/$defs/identifier" } + } + } + ] + }, + "terminalPolicy": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["policy"], + "properties": { "policy": { "const": "hold" } } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["policy", "price", "currency"], + "properties": { + "policy": { "const": "cash_out" }, + "price": { "$ref": "#/$defs/positiveDecimal" }, + "currency": { "$ref": "#/$defs/identifier" } + } + } + ] + }, + "lifecycleEvent": { + "oneOf": [ + { + "type": "object", + "additionalProperties": false, + "required": ["type", "event_id", "instrument_id", "reason"], + "properties": { + "type": { "const": "halt" }, + "event_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "reason": { "type": "string", "minLength": 1 } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "event_id", "instrument_id"], + "properties": { + "type": { "const": "resume" }, + "event_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "event_id", "instrument_id", "symbol", "provider", "provider_instrument_id"], + "properties": { + "type": { "const": "identifier_change" }, + "event_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "symbol": { "$ref": "#/$defs/identifier" }, + "provider": { "$ref": "#/$defs/identifier" }, + "provider_instrument_id": { "$ref": "#/$defs/identifier" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "event_id", "instrument_id", "terminal_policy"], + "properties": { + "type": { "const": "expiration" }, + "event_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "terminal_policy": { "$ref": "#/$defs/terminalPolicy" } + } + }, + { + "type": "object", + "additionalProperties": false, + "required": ["type", "event_id", "instrument_id", "terminal_policy", "reason"], + "properties": { + "type": { "const": "delisting" }, + "event_id": { "$ref": "#/$defs/identifier" }, + "instrument_id": { "$ref": "#/$defs/identifier" }, + "terminal_policy": { "$ref": "#/$defs/terminalPolicy" }, + "reason": { "type": "string", "minLength": 1 } + } + } + ] } } } diff --git a/contracts/v10/README.md b/contracts/v10/README.md deleted file mode 100644 index 09a77f5..0000000 --- a/contracts/v10/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Trading Engine contract v10 - -This directory is the authoritative v10 process and file contract shared by Trading Engine and its -clients. Versions 9, 8, 7, 6, 5, 4, and 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v10 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v10 scenario, stream record, and journal record carries `"contract_version": "10"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v10 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. - -Version 10 adds a required `financing` policy and effective-time observations on every market -slice. Borrow observations provide per-instrument locate availability, signed annual rates, and -recall state. Cash observations provide separate annual credit and debit rates per currency. -Policies select Actual/365 or Actual/360 day count, simple or daily compounding, missing-data -handling, locate rejection or fill clipping, and recall rejection or deterministic close-out. - -Borrow availability is enforced when a fill would create or increase a short. Recalls cancel -active sells and may submit priority IOC covers until the position is flat. Borrow charges and cash -interest use the exact slice interval, update native ledgers deterministically, and emit dedicated -journal records. Valuations report cash interest separately and include it in aggregate realized -P&L. Version 9 and earlier retain their frozen fixed-borrow behavior and wire shapes. diff --git a/contracts/v10/dune b/contracts/v10/dune deleted file mode 100644 index 07b28ed..0000000 --- a/contracts/v10/dune +++ /dev/null @@ -1,18 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v10/journal.schema.json) - (scenario-stream.schema.json as contracts/v10/scenario-stream.schema.json) - (scenario.schema.json as contracts/v10/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v10/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v10/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl - as - contracts/v10/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v10/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v10/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v10/fixtures/demo.journal.jsonl b/contracts/v10/fixtures/demo.journal.jsonl deleted file mode 100644 index 7d920e6..0000000 --- a/contracts/v10/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,26 +0,0 @@ -{"contract_version":"10","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"c129c13b6e4273c4d2a784c5b9aaa2630ad67ecbafd6da303da12b2fb6f253bc","execution_model":"completed_bar_v1"}} -{"contract_version":"10","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[]}],"execution_fee_components":[],"cash_interest":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"10","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[]}],"execution_fee_components":[],"cash_interest":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}]}} -{"contract_version":"10","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} -{"contract_version":"10","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"10","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"10","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"10","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000.074201","fx_rate":"1","base_value":"10000.074201","interest":"0.074201","base_interest":"0.074201"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[]}],"execution_fee_components":[],"cash_interest":"0.074201","margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}]}} -{"contract_version":"10","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} -{"contract_version":"10","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_amount":"0.618"}]}} -{"contract_version":"10","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"10","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000014","updated_event_id":"demo-event-000000000014","created_sequence":"14","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"10","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.280402","net_market_value":"749","long_market_value":"749","short_market_value":"0","gross_exposure":"749","cost_basis":"708.868","realized_pnl":"5.148402","unrealized_pnl":"40.132","equity":"10130.280402","dividend_pnl":"1","execution_fees":"1.368","borrow_fees":"0.25","total_fees":"1.618","cash_balances":[{"currency":"USD","amount":"9381.280402","fx_rate":"1","base_value":"9381.280402","interest":"0.148402","base_interest":"0.148402"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7","mark":"107","fx_rate":"1","market_value":"749","base_market_value":"749","cost_basis":"708.868","base_cost_basis":"708.868","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.132","base_unrealized_pnl":"40.132","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.368","base_execution_fees":"1.368","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.618","base_total_fees":"1.618","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}],"cash_interest":"0.148402","margin":{"initial_requirement":"374.5","maintenance_requirement":"187.25","initial_excess":"9755.780402","maintenance_excess":"9943.030402","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}]}} -{"contract_version":"10","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":["demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9381.280402","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.06961","closing_balance":"9381.350012"}} -{"contract_version":"10","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000014","demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.715","price":"107","notional":"290.505","fee":"0.540505","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.290505","quote_amount":"0.290505"}]}} -{"contract_version":"10","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"10","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000016","demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000020","updated_event_id":"demo-event-000000000020","created_sequence":"20","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"10","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.304507","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.913505","realized_pnl":"5.218012","unrealized_pnl":"20.161495","equity":"10110.379507","dividend_pnl":"1","execution_fees":"1.908505","borrow_fees":"0.25","total_fees":"2.158505","cash_balances":[{"currency":"USD","amount":"9090.304507","fx_rate":"1","base_value":"9090.304507","interest":"0.218012","base_interest":"0.218012"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.913505","base_cost_basis":"999.913505","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.161495","base_unrealized_pnl":"20.161495","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.908505","base_execution_fees":"1.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.158505","base_total_fees":"2.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}],"cash_interest":"0.218012","margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.342007","maintenance_excess":"9855.360757","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}]}} -{"contract_version":"10","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000022"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.304507","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067451","closing_balance":"9090.371958"}} -{"contract_version":"10","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":["demo-event-000000000020","demo-event-000000000022"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"105","notional":"757.575","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.757575","quote_amount":"0.757575"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_amount":"-0.007575"}]}} -{"contract_version":"10","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":["demo-event-000000000022"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.946958","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"19.25872","unrealized_pnl":"7.688238","equity":"10111.946958","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.946958","fx_rate":"1","base_value":"9846.946958","interest":"0.285463","base_interest":"0.285463"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"cash_interest":"0.285463","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.446958","maintenance_excess":"10045.696958","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"c129c13b6e4273c4d2a784c5b9aaa2630ad67ecbafd6da303da12b2fb6f253bc","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9846.946958","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"19.25872","unrealized_pnl":"7.688238","equity":"10111.946958","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.946958","fx_rate":"1","base_value":"9846.946958","interest":"0.285463","base_interest":"0.285463"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"cash_interest":"0.285463","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.446958","maintenance_excess":"10045.696958","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v10/fixtures/demo.scenario.json b/contracts/v10/fixtures/demo.scenario.json deleted file mode 100644 index 9f0332b..0000000 --- a/contracts/v10/fixtures/demo.scenario.json +++ /dev/null @@ -1,411 +0,0 @@ -{ - "contract_version": "10", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "taker" - }, - { - "name": "maker_rebate", - "currency": "USD", - "kind": "notional_bps", - "value": -2, - "rounding": "nearest", - "applies_to": "maker" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-06T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-06T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-07T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-07T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - } -} diff --git a/contracts/v10/fixtures/demo.scenario.jsonl b/contracts/v10/fixtures/demo.scenario.jsonl deleted file mode 100644 index 1ce27fc..0000000 --- a/contracts/v10/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"10","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"}}} -{"contract_version":"10","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"10","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"10","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}]}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"10","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}]}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"10","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v10/fixtures/fill-clipped.journal.jsonl b/contracts/v10/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index d363391..0000000 --- a/contracts/v10/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"10","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"19f11d500905b44278fb098678e3a8467dedd02f5b98e126f0ed1a8e5773d53d","execution_model":"completed_bar_v1"}} -{"contract_version":"10","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"10","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}]}} -{"contract_version":"10","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} -{"contract_version":"10","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"10","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.004081","fx_rate":"1","base_value":"550.004081","interest":"0.004081","base_interest":"0.004081"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[]}],"execution_fee_components":[],"cash_interest":"0.004081","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}]}} -{"contract_version":"10","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} -{"contract_version":"10","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"10","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"10","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[]}],"execution_fee_components":[],"cash_interest":"0.008162","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} -{"contract_version":"10","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"19f11d500905b44278fb098678e3a8467dedd02f5b98e126f0ed1a8e5773d53d","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[]}],"execution_fee_components":[],"cash_interest":"0.008162","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v10/fixtures/fill-clipped.scenario.json b/contracts/v10/fixtures/fill-clipped.scenario.json deleted file mode 100644 index a408f1f..0000000 --- a/contracts/v10/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,236 +0,0 @@ -{ - "contract_version": "10", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - } -} diff --git a/contracts/v10/journal.schema.json b/contracts/v10/journal.schema.json deleted file mode 100644 index fc11e1c..0000000 --- a/contracts/v10/journal.schema.json +++ /dev/null @@ -1,2193 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v10/journal.schema.json", - "title": "Trading Engine v10 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { - "const": "10" - }, - "engine_sequence": { - "$ref": "#/$defs/sequence" - }, - "event_id": { - "$ref": "#/$defs/identifier" - }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/$defs/identifier" - } - }, - "run_id": { - "$ref": "#/$defs/identifier" - }, - "recorded_at": { - "$ref": "#/$defs/timestamp" - }, - "event_type": { - "enum": [ - "run_started", - "initial_state", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_triggered", - "order_cancelled", - "split_applied", - "cash_dividend_applied", - "order_adjusted", - "fill_applied", - "fill_clipped", - "borrow_fee_applied", - "borrow_charge_applied", - "borrow_recall_received", - "cash_interest_applied", - "margin_call", - "margin_restored", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { - "type": "object" - } - }, - "allOf": [ - { - "if": { - "properties": { - "event_type": { - "const": "run_started" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runStarted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "initial_state" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/initialState" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "market_slice_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/marketSlice" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "target_portfolio_requested" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/targetPortfolio" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "order_accepted", - "order_rejected", - "order_triggered" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/order" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_cancelled" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderCancelled" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "split_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/splitApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_dividend_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/dividendApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_adjusted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderAdjusted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fill" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_clipped" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fillClipped" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_fee_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowFee" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_charge_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowCharge" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_recall_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowRecall" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_interest_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/cashInterest" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "margin_call", - "margin_restored", - "valuation" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/valuation" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "intent_rejected" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/intentRejected" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "metric_emitted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/metric" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_completed" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runCompleted" - } - } - } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "nonnegativeSequence": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "const": "completed_bar_v1" - } - } - }, - "initialState": { - "type": "object", - "additionalProperties": false, - "required": [ - "portfolio", - "valuation" - ], - "properties": { - "portfolio": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/initialPortfolio" - }, - "valuation": { - "$ref": "#/$defs/valuation" - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "open", - "high", - "low", - "close", - "volume" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "open": { - "$ref": "#/$defs/positiveDecimal" - }, - "high": { - "$ref": "#/$defs/positiveDecimal" - }, - "low": { - "$ref": "#/$defs/positiveDecimal" - }, - "close": { - "$ref": "#/$defs/positiveDecimal" - }, - "volume": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/unsignedDecimal" - } - ] - } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "rate" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "rate": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "numerator", - "denominator" - ], - "properties": { - "type": { - "const": "split" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "numerator": { - "$ref": "#/$defs/sequence" - }, - "denominator": { - "$ref": "#/$defs/sequence" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "amount_per_unit" - ], - "properties": { - "type": { - "const": "cash_dividend" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "amount_per_unit": { - "$ref": "#/$defs/positiveDecimal" - } - } - } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars", - "fx_rates", - "corporate_actions", - "borrow_observations", - "cash_rate_observations" - ], - "properties": { - "slice_sequence": { - "$ref": "#/$defs/sequence" - }, - "start_at": { - "$ref": "#/$defs/timestamp" - }, - "end_at": { - "$ref": "#/$defs/timestamp" - }, - "available_at": { - "$ref": "#/$defs/timestamp" - }, - "received_at": { - "$ref": "#/$defs/timestamp" - }, - "bars": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/bar" - } - }, - "fx_rates": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/fxRate" - } - }, - "corporate_actions": { - "type": "array", - "items": { - "$ref": "#/$defs/corporateAction" - } - }, - "borrow_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/borrowObservation" - } - }, - "cash_rate_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/cashRateObservation" - } - } - } - }, - "targetPortfolio": { - "type": "object", - "additionalProperties": false, - "required": [ - "basis", - "targets" - ], - "properties": { - "basis": { - "enum": [ - "weights", - "quantities" - ] - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "weight", - "quantity", - "reference_price" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "weight": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "reference_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - } - } - } - } - } - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "trigger_price", - "limit_price", - "time_in_force", - "venue_id", - "calendar_id", - "expires_at", - "origin", - "created_event_id", - "updated_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "triggered_at", - "triggered_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "order_kind": { - "enum": [ - "market", - "limit", - "stop", - "stop_limit" - ] - }, - "trigger_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "limit_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "time_in_force": { - "enum": [ - "gtc", - "ioc", - "fok", - "day", - "gtd" - ] - }, - "venue_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "calendar_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "expires_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "origin": { - "enum": [ - "direct", - "target_rebalance", - "margin_liquidation", - "borrow_recall" - ] - }, - "created_event_id": { - "$ref": "#/$defs/identifier" - }, - "updated_event_id": { - "$ref": "#/$defs/identifier" - }, - "created_sequence": { - "$ref": "#/$defs/sequence" - }, - "created_at": { - "$ref": "#/$defs/timestamp" - }, - "eligible_after_slice_sequence": { - "$ref": "#/$defs/nonnegativeSequence" - }, - "triggered_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "triggered_slice_sequence": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/sequence" - } - ] - }, - "filled_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "filled_notional": { - "$ref": "#/$defs/unsignedDecimal" - }, - "status": { - "enum": [ - "working", - "partially_filled", - "filled", - "cancelled", - "rejected" - ] - }, - "rejection_reason": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "minLength": 1 - } - ] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "reason" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "reason": { - "enum": [ - "strategy_requested", - "target_replaced", - "market_ioc", - "immediate_or_cancel", - "fill_or_kill", - "day_expired", - "gtd_expired", - "margin_call", - "borrow_recall" - ] - } - } - }, - "splitApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "previous_quantity", - "adjusted_quantity" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "previous_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "adjusted_quantity": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "dividendApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "quantity", - "cash_amount" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "orderAdjusted": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "action_id" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "action_id": { - "$ref": "#/$defs/identifier" - } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "quote_currency", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence", - "fee_components" - ], - "properties": { - "fill_id": { - "$ref": "#/$defs/identifier" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - }, - "notional": { - "$ref": "#/$defs/positiveDecimal" - }, - "fee": { - "$ref": "#/$defs/signedDecimal" - }, - "fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/calculatedFeeComponent" - } - }, - "executed_at": { - "$ref": "#/$defs/timestamp" - }, - "slice_sequence": { - "$ref": "#/$defs/sequence" - } - } - }, - "calculatedFeeComponent": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "feeComponentAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_currency", - "quote_amount", - "base_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "quantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "moneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "ratioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "basisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentQuantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentBasisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentShortingThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "value": { - "const": false - } - } - }, - "groupMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "groupRatioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "fillClipReason": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_order_quantity" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_long_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_short_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/moneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_leverage" - }, - "threshold": { - "$ref": "#/$defs/ratioThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "initial_margin" - }, - "threshold": { - "$ref": "#/$defs/basisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_long_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_short_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_notional_exposure" - }, - "threshold": { - "$ref": "#/$defs/instrumentMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_shorting_disabled" - }, - "threshold": { - "$ref": "#/$defs/instrumentShortingThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_borrow_availability" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_initial_margin" - }, - "threshold": { - "$ref": "#/$defs/instrumentBasisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_long_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_short_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_absolute_net_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_concentration" - }, - "threshold": { - "$ref": "#/$defs/groupRatioThreshold" - } - } - } - ] - }, - "fillClipped": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason", - "order_id", - "instrument_id", - "proposed_quantity", - "permitted_quantity", - "price" - ], - "properties": { - "reason": { - "$ref": "#/$defs/fillClipReason" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "proposed_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "permitted_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowFee": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "short_quantity", - "reference_price", - "borrow_bps", - "period_start", - "period_end", - "fee" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "borrow_bps": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "fee": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowCharge": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "quote_currency", - "short_quantity", - "reference_price", - "day_count", - "compounding", - "period_start", - "period_end", - "amount" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/borrowObservation" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "borrowRecall": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "short_quantity", - "close_out_quantity" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/borrowObservation" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "close_out_quantity": { - "$ref": "#/$defs/unsignedDecimal" - } - } - }, - "cashInterest": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "opening_balance", - "applied_rate_bps", - "day_count", - "compounding", - "period_start", - "period_end", - "amount", - "closing_balance" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/cashRateObservation" - }, - "opening_balance": { - "$ref": "#/$defs/signedDecimal" - }, - "applied_rate_bps": { - "type": "integer", - "minimum": -1000000, - "maximum": 1000000 - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "closing_balance": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "cashAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "amount", - "fx_rate", - "base_value", - "interest", - "base_interest" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "base_value": { - "$ref": "#/$defs/signedDecimal" - }, - "interest": { - "$ref": "#/$defs/signedDecimal" - }, - "base_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "quantity", - "mark", - "fx_rate", - "market_value", - "base_market_value", - "cost_basis", - "base_cost_basis", - "realized_pnl", - "base_realized_pnl", - "unrealized_pnl", - "base_unrealized_pnl", - "dividend_pnl", - "base_dividend_pnl", - "execution_fees", - "base_execution_fees", - "borrow_fees", - "base_borrow_fees", - "total_fees", - "base_total_fees", - "execution_fee_components" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "mark": { - "$ref": "#/$defs/positiveDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "base_cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - } - } - }, - "margin": { - "type": "object", - "additionalProperties": false, - "required": [ - "initial_requirement", - "maintenance_requirement", - "initial_excess", - "maintenance_excess", - "margin_call" - ], - "properties": { - "initial_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "maintenance_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "initial_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "maintenance_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "margin_call": { - "type": "boolean" - } - } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "gross_exposure", - "net_exposure", - "long_exposure", - "short_exposure", - "concentration" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "net_exposure": { - "$ref": "#/$defs/signedDecimal" - }, - "long_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "concentration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "base_currency", - "cash", - "net_market_value", - "long_market_value", - "short_market_value", - "gross_exposure", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "dividend_pnl", - "execution_fees", - "borrow_fees", - "cash_interest", - "total_fees", - "cash_balances", - "positions", - "margin", - "group_exposures", - "execution_fee_components" - ], - "properties": { - "base_currency": { - "$ref": "#/$defs/identifier" - }, - "cash": { - "$ref": "#/$defs/signedDecimal" - }, - "net_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "long_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "equity": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/cashAttribution" - } - }, - "positions": { - "type": "array", - "items": { - "$ref": "#/$defs/positionAttribution" - } - }, - "margin": { - "$ref": "#/$defs/margin" - }, - "group_exposures": { - "type": "array", - "items": { - "$ref": "#/$defs/groupExposure" - } - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - }, - "cash_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "minLength": 1 - } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "const": "completed_bar_v1" - }, - "valuation": { - "$ref": "#/$defs/valuation" - }, - "order_counts": { - "type": "object", - "additionalProperties": false, - "required": [ - "total", - "active", - "filled", - "rejected", - "cancelled" - ], - "properties": { - "total": { - "type": "integer", - "minimum": 0 - }, - "active": { - "type": "integer", - "minimum": 0 - }, - "filled": { - "type": "integer", - "minimum": 0 - }, - "rejected": { - "type": "integer", - "minimum": 0 - }, - "cancelled": { - "type": "integer", - "minimum": 0 - } - } - } - } - } - } -} diff --git a/contracts/v10/scenario-stream.schema.json b/contracts/v10/scenario-stream.schema.json deleted file mode 100644 index 5f50c87..0000000 --- a/contracts/v10/scenario-stream.schema.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v10/scenario-stream.schema.json", - "title": "Trading Engine v10 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "10" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "10" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "10" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/financing" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v10/scenario.schema.json b/contracts/v10/scenario.schema.json deleted file mode 100644 index c470212..0000000 --- a/contracts/v10/scenario.schema.json +++ /dev/null @@ -1,510 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v10/scenario.schema.json", - "title": "Trading Engine v10 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "10" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "financing": { "$ref": "#/$defs/financing" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "financing": { - "type": "object", - "additionalProperties": false, - "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], - "properties": { - "day_count": { "enum": ["actual_365", "actual_360"] }, - "compounding": { "enum": ["simple", "daily"] }, - "borrow_missing_data": { "enum": ["reject", "zero"] }, - "cash_missing_data": { "enum": ["reject", "zero"] }, - "locate_policy": { "enum": ["reject_order", "clip_fill"] }, - "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } - } - }, - "borrowObservation": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, - "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "recalled": { "type": "boolean" } - } - }, - "cashRateObservation": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } - } - }, - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, - "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, - "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v11/README.md b/contracts/v11/README.md deleted file mode 100644 index cd3f5ae..0000000 --- a/contracts/v11/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Trading Engine contract v11 - -This directory is the authoritative v11 process and file contract shared by Trading Engine and its -clients. Versions 10 through 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v11 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v11 scenario, stream record, and journal record carries `"contract_version": "11"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v10 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. - -Version 10 adds a required `financing` policy and effective-time observations on every market -slice. Borrow observations provide per-instrument locate availability, signed annual rates, and -recall state. Cash observations provide separate annual credit and debit rates per currency. -Policies select Actual/365 or Actual/360 day count, simple or daily compounding, missing-data -handling, locate rejection or fill clipping, and recall rejection or deterministic close-out. - -Borrow availability is enforced when a fill would create or increase a short. Recalls cancel -active sells and may submit priority IOC covers until the position is flat. Borrow charges and cash -interest use the exact slice interval, update native ledgers deterministically, and emit dedicated -journal records. Valuations report cash interest separately and include it in aggregate realized -P&L. Version 9 and earlier retain their frozen fixed-borrow behavior and wire shapes. - -Version 11 separates trade-date economic accounting from settlement-date availability. A required -settlement policy selects total or settled cash buying power and total or settled position -availability. Versioned calendars enumerate canonical business dates, and each instrument has an -explicit business-day lag. Every fill creates a deterministic settlement instruction containing -its cash and position movements, trade date, and due date. A due instruction either settles on the -first eligible slice or records a named failure supplied by that slice. - -Valuations and strategy contexts report settled and unsettled cash and quantities without changing -economic equity. Journals include instruction-created, completed, and failed events. Scenario v10 -and strategy protocol v8 retain their frozen immediate-settlement wire behavior. diff --git a/contracts/v11/dune b/contracts/v11/dune deleted file mode 100644 index a0608ce..0000000 --- a/contracts/v11/dune +++ /dev/null @@ -1,18 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v11/journal.schema.json) - (scenario-stream.schema.json as contracts/v11/scenario-stream.schema.json) - (scenario.schema.json as contracts/v11/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v11/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v11/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl - as - contracts/v11/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v11/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v11/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v11/fixtures/demo.journal.jsonl b/contracts/v11/fixtures/demo.journal.jsonl deleted file mode 100644 index d8fd545..0000000 --- a/contracts/v11/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,31 +0,0 @@ -{"contract_version":"11","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"eb93b72479e9a6dc49111ba26dce90e04e98538fffc2717095a3f1d98be2a8c1","execution_model":"completed_bar_v1"}} -{"contract_version":"11","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"11","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}} -{"contract_version":"11","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} -{"contract_version":"11","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"11","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"11","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"11","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000.074201","fx_rate":"1","base_value":"10000.074201","interest":"0.074201","base_interest":"0.074201","settled_amount":"10000.074201","unsettled_amount":"0","base_settled_value":"10000.074201","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.074201","settled_cash":"10000.074201","unsettled_cash":"0","margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}} -{"contract_version":"11","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} -{"contract_version":"11","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_amount":"0.618"}]}} -{"contract_version":"11","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000001-settlement","fill_id":"demo-fill-000000000001","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-618.868","position_movement":"6","trade_date":"2026-01-05","due_date":"2026-01-06","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} -{"contract_version":"11","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"11","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"11","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.280402","net_market_value":"749","long_market_value":"749","short_market_value":"0","gross_exposure":"749","cost_basis":"708.868","realized_pnl":"5.148402","unrealized_pnl":"40.132","equity":"10130.280402","dividend_pnl":"1","execution_fees":"1.368","borrow_fees":"0.25","total_fees":"1.618","cash_balances":[{"currency":"USD","amount":"9381.280402","fx_rate":"1","base_value":"9381.280402","interest":"0.148402","base_interest":"0.148402","settled_amount":"10000.148402","unsettled_amount":"-618.868","base_settled_value":"10000.148402","base_unsettled_value":"-618.868"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7","mark":"107","fx_rate":"1","market_value":"749","base_market_value":"749","cost_basis":"708.868","base_cost_basis":"708.868","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.132","base_unrealized_pnl":"40.132","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.368","base_execution_fees":"1.368","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.618","base_total_fees":"1.618","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}],"settled_quantity":"1","unsettled_quantity":"6"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}],"cash_interest":"0.148402","settled_cash":"10000.148402","unsettled_cash":"-618.868","margin":{"initial_requirement":"374.5","maintenance_requirement":"187.25","initial_excess":"9755.780402","maintenance_excess":"9943.030402","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}} -{"contract_version":"11","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"settlement_completed","payload":{"instruction_id":"demo-fill-000000000001-settlement","fill_id":"demo-fill-000000000001","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-618.868","position_movement":"6","trade_date":"2026-01-05","due_date":"2026-01-06","status":"settled","settled_at":"2026-01-06T14:30:00.000000Z","failed_at":null,"failure_reason":null}} -{"contract_version":"11","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9381.280402","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.06961","closing_balance":"9381.350012"}} -{"contract_version":"11","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.715","price":"107","notional":"290.505","fee":"0.540505","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.290505","quote_amount":"0.290505"}]}} -{"contract_version":"11","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000020"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000002-settlement","fill_id":"demo-fill-000000000002","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-291.045505","position_movement":"2.715","trade_date":"2026-01-06","due_date":"2026-01-07","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} -{"contract_version":"11","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"11","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000017","demo-event-000000000022"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000023","updated_event_id":"demo-event-000000000023","created_sequence":"23","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"11","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.304507","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.913505","realized_pnl":"5.218012","unrealized_pnl":"20.161495","equity":"10110.379507","dividend_pnl":"1","execution_fees":"1.908505","borrow_fees":"0.25","total_fees":"2.158505","cash_balances":[{"currency":"USD","amount":"9090.304507","fx_rate":"1","base_value":"9090.304507","interest":"0.218012","base_interest":"0.218012","settled_amount":"9381.350012","unsettled_amount":"-291.045505","base_settled_value":"9381.350012","base_unsettled_value":"-291.045505"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.913505","base_cost_basis":"999.913505","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.161495","base_unrealized_pnl":"20.161495","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.908505","base_execution_fees":"1.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.158505","base_total_fees":"2.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}],"settled_quantity":"7","unsettled_quantity":"2.715"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}],"cash_interest":"0.218012","settled_cash":"9381.350012","unsettled_cash":"-291.045505","margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.342007","maintenance_excess":"9855.360757","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}} -{"contract_version":"11","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"settlement_completed","payload":{"instruction_id":"demo-fill-000000000002-settlement","fill_id":"demo-fill-000000000002","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-291.045505","position_movement":"2.715","trade_date":"2026-01-06","due_date":"2026-01-07","status":"settled","settled_at":"2026-01-07T14:30:00.000000Z","failed_at":null,"failure_reason":null}} -{"contract_version":"11","engine_sequence":"27","event_id":"demo-event-000000000027","causation_ids":["demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.304507","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067451","closing_balance":"9090.371958"}} -{"contract_version":"11","engine_sequence":"28","event_id":"demo-event-000000000028","causation_ids":["demo-event-000000000023","demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"105","notional":"757.575","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.757575","quote_amount":"0.757575"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_amount":"-0.007575"}]}} -{"contract_version":"11","engine_sequence":"29","event_id":"demo-event-000000000029","causation_ids":["demo-event-000000000028"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000003-settlement","fill_id":"demo-fill-000000000003","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"756.575","position_movement":"-7.215","trade_date":"2026-01-07","due_date":"2026-01-08","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} -{"contract_version":"11","engine_sequence":"30","event_id":"demo-event-000000000030","causation_ids":["demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.946958","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"19.25872","unrealized_pnl":"7.688238","equity":"10111.946958","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.946958","fx_rate":"1","base_value":"9846.946958","interest":"0.285463","base_interest":"0.285463","settled_amount":"9090.371958","unsettled_amount":"756.575","base_settled_value":"9090.371958","base_unsettled_value":"756.575"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"settled_quantity":"9.715","unsettled_quantity":"-7.215"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"cash_interest":"0.285463","settled_cash":"9090.371958","unsettled_cash":"756.575","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.446958","maintenance_excess":"10045.696958","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"31","event_id":"demo-event-000000000031","causation_ids":["demo-event-000000000030"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"eb93b72479e9a6dc49111ba26dce90e04e98538fffc2717095a3f1d98be2a8c1","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9846.946958","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"19.25872","unrealized_pnl":"7.688238","equity":"10111.946958","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.946958","fx_rate":"1","base_value":"9846.946958","interest":"0.285463","base_interest":"0.285463","settled_amount":"9090.371958","unsettled_amount":"756.575","base_settled_value":"9090.371958","base_unsettled_value":"756.575"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"settled_quantity":"9.715","unsettled_quantity":"-7.215"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"cash_interest":"0.285463","settled_cash":"9090.371958","unsettled_cash":"756.575","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.446958","maintenance_excess":"10045.696958","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v11/fixtures/demo.scenario.json b/contracts/v11/fixtures/demo.scenario.json deleted file mode 100644 index 0747373..0000000 --- a/contracts/v11/fixtures/demo.scenario.json +++ /dev/null @@ -1,444 +0,0 @@ -{ - "contract_version": "11", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "taker" - }, - { - "name": "maker_rebate", - "currency": "USD", - "kind": "notional_bps", - "value": -2, - "rounding": "nearest", - "applies_to": "maker" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-06T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-06T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-07T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-07T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v11/fixtures/demo.scenario.jsonl b/contracts/v11/fixtures/demo.scenario.jsonl deleted file mode 100644 index bc7d5d0..0000000 --- a/contracts/v11/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"11","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"11","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"11","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"11","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"11","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"11","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v11/fixtures/fill-clipped.journal.jsonl b/contracts/v11/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 9ad7d70..0000000 --- a/contracts/v11/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"11","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"8235142ca2e31e8db6f25372b1079adbb218b8b310bfd7a95672f766f43e6808","execution_model":"completed_bar_v1"}} -{"contract_version":"11","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"11","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}} -{"contract_version":"11","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} -{"contract_version":"11","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"11","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.004081","fx_rate":"1","base_value":"550.004081","interest":"0.004081","base_interest":"0.004081","settled_amount":"550.004081","unsettled_amount":"0","base_settled_value":"550.004081","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.004081","settled_cash":"550.004081","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[]}} -{"contract_version":"11","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} -{"contract_version":"11","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"11","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"11","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} -{"contract_version":"11","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"8235142ca2e31e8db6f25372b1079adbb218b8b310bfd7a95672f766f43e6808","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v11/fixtures/fill-clipped.scenario.json b/contracts/v11/fixtures/fill-clipped.scenario.json deleted file mode 100644 index 5729f37..0000000 --- a/contracts/v11/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,267 +0,0 @@ -{ - "contract_version": "11", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v11/journal.schema.json b/contracts/v11/journal.schema.json deleted file mode 100644 index d0e9c2d..0000000 --- a/contracts/v11/journal.schema.json +++ /dev/null @@ -1,2314 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v11/journal.schema.json", - "title": "Trading Engine v11 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { - "const": "11" - }, - "engine_sequence": { - "$ref": "#/$defs/sequence" - }, - "event_id": { - "$ref": "#/$defs/identifier" - }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/$defs/identifier" - } - }, - "run_id": { - "$ref": "#/$defs/identifier" - }, - "recorded_at": { - "$ref": "#/$defs/timestamp" - }, - "event_type": { - "enum": [ - "run_started", - "initial_state", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_triggered", - "order_cancelled", - "split_applied", - "cash_dividend_applied", - "order_adjusted", - "fill_applied", - "settlement_instruction_created", - "settlement_completed", - "settlement_failed", - "fill_clipped", - "borrow_fee_applied", - "borrow_charge_applied", - "borrow_recall_received", - "cash_interest_applied", - "margin_call", - "margin_restored", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { - "type": "object" - } - }, - "allOf": [ - { - "if": { - "properties": { - "event_type": { - "const": "run_started" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runStarted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "initial_state" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/initialState" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "market_slice_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/marketSlice" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "target_portfolio_requested" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/targetPortfolio" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "order_accepted", - "order_rejected", - "order_triggered" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/order" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_cancelled" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderCancelled" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "split_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/splitApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_dividend_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/dividendApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_adjusted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderAdjusted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fill" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "settlement_instruction_created", - "settlement_completed", - "settlement_failed" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/settlementInstruction" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_clipped" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fillClipped" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_fee_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowFee" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_charge_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowCharge" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_recall_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowRecall" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_interest_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/cashInterest" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "margin_call", - "margin_restored", - "valuation" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/valuation" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "intent_rejected" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/intentRejected" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "metric_emitted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/metric" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_completed" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runCompleted" - } - } - } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "nonnegativeSequence": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "const": "completed_bar_v1" - } - } - }, - "initialState": { - "type": "object", - "additionalProperties": false, - "required": [ - "portfolio", - "valuation" - ], - "properties": { - "portfolio": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/initialPortfolio" - }, - "valuation": { - "$ref": "#/$defs/valuation" - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "open", - "high", - "low", - "close", - "volume" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "open": { - "$ref": "#/$defs/positiveDecimal" - }, - "high": { - "$ref": "#/$defs/positiveDecimal" - }, - "low": { - "$ref": "#/$defs/positiveDecimal" - }, - "close": { - "$ref": "#/$defs/positiveDecimal" - }, - "volume": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/unsignedDecimal" - } - ] - } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "rate" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "rate": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "numerator", - "denominator" - ], - "properties": { - "type": { - "const": "split" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "numerator": { - "$ref": "#/$defs/sequence" - }, - "denominator": { - "$ref": "#/$defs/sequence" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "amount_per_unit" - ], - "properties": { - "type": { - "const": "cash_dividend" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "amount_per_unit": { - "$ref": "#/$defs/positiveDecimal" - } - } - } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars", - "fx_rates", - "corporate_actions", - "borrow_observations", - "cash_rate_observations", - "settlement_failures" - ], - "properties": { - "slice_sequence": { - "$ref": "#/$defs/sequence" - }, - "start_at": { - "$ref": "#/$defs/timestamp" - }, - "end_at": { - "$ref": "#/$defs/timestamp" - }, - "available_at": { - "$ref": "#/$defs/timestamp" - }, - "received_at": { - "$ref": "#/$defs/timestamp" - }, - "bars": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/bar" - } - }, - "fx_rates": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/fxRate" - } - }, - "corporate_actions": { - "type": "array", - "items": { - "$ref": "#/$defs/corporateAction" - } - }, - "borrow_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/borrowObservation" - } - }, - "cash_rate_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/cashRateObservation" - } - }, - "settlement_failures": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/settlementFailure" - } - } - } - }, - "settlementInstruction": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "fill_id", "instrument_id", "currency", "cash_movement", "position_movement", "trade_date", "due_date", "status", "settled_at", "failed_at", "failure_reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "fill_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "cash_movement": { "$ref": "#/$defs/signedDecimal" }, - "position_movement": { "$ref": "#/$defs/signedDecimal" }, - "trade_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "due_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "status": { "enum": ["pending", "settled", "failed"] }, - "settled_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failed_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failure_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" }] } - } - }, - "targetPortfolio": { - "type": "object", - "additionalProperties": false, - "required": [ - "basis", - "targets" - ], - "properties": { - "basis": { - "enum": [ - "weights", - "quantities" - ] - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "weight", - "quantity", - "reference_price" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "weight": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "reference_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - } - } - } - } - } - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "trigger_price", - "limit_price", - "time_in_force", - "venue_id", - "calendar_id", - "expires_at", - "origin", - "created_event_id", - "updated_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "triggered_at", - "triggered_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "order_kind": { - "enum": [ - "market", - "limit", - "stop", - "stop_limit" - ] - }, - "trigger_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "limit_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "time_in_force": { - "enum": [ - "gtc", - "ioc", - "fok", - "day", - "gtd" - ] - }, - "venue_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "calendar_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "expires_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "origin": { - "enum": [ - "direct", - "target_rebalance", - "margin_liquidation", - "borrow_recall" - ] - }, - "created_event_id": { - "$ref": "#/$defs/identifier" - }, - "updated_event_id": { - "$ref": "#/$defs/identifier" - }, - "created_sequence": { - "$ref": "#/$defs/sequence" - }, - "created_at": { - "$ref": "#/$defs/timestamp" - }, - "eligible_after_slice_sequence": { - "$ref": "#/$defs/nonnegativeSequence" - }, - "triggered_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "triggered_slice_sequence": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/sequence" - } - ] - }, - "filled_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "filled_notional": { - "$ref": "#/$defs/unsignedDecimal" - }, - "status": { - "enum": [ - "working", - "partially_filled", - "filled", - "cancelled", - "rejected" - ] - }, - "rejection_reason": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "minLength": 1 - } - ] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "reason" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "reason": { - "enum": [ - "strategy_requested", - "target_replaced", - "market_ioc", - "immediate_or_cancel", - "fill_or_kill", - "day_expired", - "gtd_expired", - "margin_call", - "borrow_recall" - ] - } - } - }, - "splitApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "previous_quantity", - "adjusted_quantity" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "previous_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "adjusted_quantity": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "dividendApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "quantity", - "cash_amount" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "orderAdjusted": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "action_id" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "action_id": { - "$ref": "#/$defs/identifier" - } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "quote_currency", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence", - "fee_components" - ], - "properties": { - "fill_id": { - "$ref": "#/$defs/identifier" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - }, - "notional": { - "$ref": "#/$defs/positiveDecimal" - }, - "fee": { - "$ref": "#/$defs/signedDecimal" - }, - "fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/calculatedFeeComponent" - } - }, - "executed_at": { - "$ref": "#/$defs/timestamp" - }, - "slice_sequence": { - "$ref": "#/$defs/sequence" - } - } - }, - "calculatedFeeComponent": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "feeComponentAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_currency", - "quote_amount", - "base_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "quantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "moneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "ratioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "basisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentQuantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "currencyMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "unit", "value"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "money" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "settlementPositionThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "unit", "value"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "quantity" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrumentBasisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentShortingThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "value": { - "const": false - } - } - }, - "groupMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "groupRatioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "fillClipReason": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_order_quantity" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_long_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_short_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/moneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_leverage" - }, - "threshold": { - "$ref": "#/$defs/ratioThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "initial_margin" - }, - "threshold": { - "$ref": "#/$defs/basisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_long_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_cash_buying_power" }, - "threshold": { "$ref": "#/$defs/currencyMoneyThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_position_availability" }, - "threshold": { "$ref": "#/$defs/settlementPositionThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_short_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_notional_exposure" - }, - "threshold": { - "$ref": "#/$defs/instrumentMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_shorting_disabled" - }, - "threshold": { - "$ref": "#/$defs/instrumentShortingThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_borrow_availability" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_initial_margin" - }, - "threshold": { - "$ref": "#/$defs/instrumentBasisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_long_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_short_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_absolute_net_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_concentration" - }, - "threshold": { - "$ref": "#/$defs/groupRatioThreshold" - } - } - } - ] - }, - "fillClipped": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason", - "order_id", - "instrument_id", - "proposed_quantity", - "permitted_quantity", - "price" - ], - "properties": { - "reason": { - "$ref": "#/$defs/fillClipReason" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "proposed_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "permitted_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowFee": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "short_quantity", - "reference_price", - "borrow_bps", - "period_start", - "period_end", - "fee" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "borrow_bps": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "fee": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowCharge": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "quote_currency", - "short_quantity", - "reference_price", - "day_count", - "compounding", - "period_start", - "period_end", - "amount" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/borrowObservation" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "borrowRecall": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "short_quantity", - "close_out_quantity" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/borrowObservation" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "close_out_quantity": { - "$ref": "#/$defs/unsignedDecimal" - } - } - }, - "cashInterest": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "opening_balance", - "applied_rate_bps", - "day_count", - "compounding", - "period_start", - "period_end", - "amount", - "closing_balance" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/cashRateObservation" - }, - "opening_balance": { - "$ref": "#/$defs/signedDecimal" - }, - "applied_rate_bps": { - "type": "integer", - "minimum": -1000000, - "maximum": 1000000 - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "closing_balance": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "cashAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "amount", - "fx_rate", - "base_value", - "interest", - "base_interest", - "settled_amount", - "unsettled_amount", - "base_settled_value", - "base_unsettled_value" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "base_value": { - "$ref": "#/$defs/signedDecimal" - }, - "interest": { - "$ref": "#/$defs/signedDecimal" - }, - "base_interest": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_settled_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unsettled_value": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "quantity", - "settled_quantity", - "unsettled_quantity", - "mark", - "fx_rate", - "market_value", - "base_market_value", - "cost_basis", - "base_cost_basis", - "realized_pnl", - "base_realized_pnl", - "unrealized_pnl", - "base_unrealized_pnl", - "dividend_pnl", - "base_dividend_pnl", - "execution_fees", - "base_execution_fees", - "borrow_fees", - "base_borrow_fees", - "total_fees", - "base_total_fees", - "execution_fee_components" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "mark": { - "$ref": "#/$defs/positiveDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "base_cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - } - } - }, - "margin": { - "type": "object", - "additionalProperties": false, - "required": [ - "initial_requirement", - "maintenance_requirement", - "initial_excess", - "maintenance_excess", - "margin_call" - ], - "properties": { - "initial_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "maintenance_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "initial_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "maintenance_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "margin_call": { - "type": "boolean" - } - } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "gross_exposure", - "net_exposure", - "long_exposure", - "short_exposure", - "concentration" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "net_exposure": { - "$ref": "#/$defs/signedDecimal" - }, - "long_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "concentration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "base_currency", - "cash", - "settled_cash", - "unsettled_cash", - "net_market_value", - "long_market_value", - "short_market_value", - "gross_exposure", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "dividend_pnl", - "execution_fees", - "borrow_fees", - "cash_interest", - "total_fees", - "cash_balances", - "positions", - "margin", - "group_exposures", - "execution_fee_components" - ], - "properties": { - "base_currency": { - "$ref": "#/$defs/identifier" - }, - "cash": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "net_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "long_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "equity": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/cashAttribution" - } - }, - "positions": { - "type": "array", - "items": { - "$ref": "#/$defs/positionAttribution" - } - }, - "margin": { - "$ref": "#/$defs/margin" - }, - "group_exposures": { - "type": "array", - "items": { - "$ref": "#/$defs/groupExposure" - } - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - }, - "cash_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "minLength": 1 - } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "const": "completed_bar_v1" - }, - "valuation": { - "$ref": "#/$defs/valuation" - }, - "order_counts": { - "type": "object", - "additionalProperties": false, - "required": [ - "total", - "active", - "filled", - "rejected", - "cancelled" - ], - "properties": { - "total": { - "type": "integer", - "minimum": 0 - }, - "active": { - "type": "integer", - "minimum": 0 - }, - "filled": { - "type": "integer", - "minimum": 0 - }, - "rejected": { - "type": "integer", - "minimum": 0 - }, - "cancelled": { - "type": "integer", - "minimum": 0 - } - } - } - } - } - } -} diff --git a/contracts/v11/scenario-stream.schema.json b/contracts/v11/scenario-stream.schema.json deleted file mode 100644 index ede8140..0000000 --- a/contracts/v11/scenario-stream.schema.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v11/scenario-stream.schema.json", - "title": "Trading Engine v11 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "11" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "11" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "11" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v11/scenario.schema.json b/contracts/v11/scenario.schema.json deleted file mode 100644 index 8198197..0000000 --- a/contracts/v11/scenario.schema.json +++ /dev/null @@ -1,552 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v11/scenario.schema.json", - "title": "Trading Engine v11 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "11" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "financing": { "$ref": "#/$defs/financing" }, - "settlement": { "$ref": "#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "settlement": { - "type": "object", - "additionalProperties": false, - "required": ["cash_buying_power", "position_availability", "calendars", "rules"], - "properties": { - "cash_buying_power": { "enum": ["total_cash", "settled_cash"] }, - "position_availability": { "enum": ["total_positions", "settled_positions"] }, - "calendars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementCalendar" } }, - "rules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementRule" } } - } - }, - "settlementCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "version", "business_dates"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "version": { "const": "1" }, - "business_dates": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } - } - }, - "settlementRule": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "calendar_id", "lag_business_days"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "calendar_id": { "$ref": "#/$defs/identifier" }, - "lag_business_days": { "type": "integer", "minimum": 0, "maximum": 30 } - } - }, - "settlementFailure": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - }, - "financing": { - "type": "object", - "additionalProperties": false, - "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], - "properties": { - "day_count": { "enum": ["actual_365", "actual_360"] }, - "compounding": { "enum": ["simple", "daily"] }, - "borrow_missing_data": { "enum": ["reject", "zero"] }, - "cash_missing_data": { "enum": ["reject", "zero"] }, - "locate_policy": { "enum": ["reject_order", "clip_fill"] }, - "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } - } - }, - "borrowObservation": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, - "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "recalled": { "type": "boolean" } - } - }, - "cashRateObservation": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } - } - }, - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations", "settlement_failures"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, - "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, - "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } }, - "settlement_failures": { "type": "array", "items": { "$ref": "#/$defs/settlementFailure" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v12/README.md b/contracts/v12/README.md deleted file mode 100644 index 970097d..0000000 --- a/contracts/v12/README.md +++ /dev/null @@ -1,85 +0,0 @@ -# Trading Engine contract v12 - -This directory is the authoritative v12 process and file contract shared by Trading Engine and its -clients. Versions 11 through 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v12 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v12 scenario, stream record, and journal record carries `"contract_version": "12"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v10 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. - -Version 10 adds a required `financing` policy and effective-time observations on every market -slice. Borrow observations provide per-instrument locate availability, signed annual rates, and -recall state. Cash observations provide separate annual credit and debit rates per currency. -Policies select Actual/365 or Actual/360 day count, simple or daily compounding, missing-data -handling, locate rejection or fill clipping, and recall rejection or deterministic close-out. - -Borrow availability is enforced when a fill would create or increase a short. Recalls cancel -active sells and may submit priority IOC covers until the position is flat. Borrow charges and cash -interest use the exact slice interval, update native ledgers deterministically, and emit dedicated -journal records. Valuations report cash interest separately and include it in aggregate realized -P&L. Version 9 and earlier retain their frozen fixed-borrow behavior and wire shapes. - -Version 11 separates trade-date economic accounting from settlement-date availability. A required -settlement policy selects total or settled cash buying power and total or settled position -availability. Versioned calendars enumerate canonical business dates, and each instrument has an -explicit business-day lag. Every fill creates a deterministic settlement instruction containing -its cash and position movements, trade date, and due date. A due instruction either settles on the -first eligible slice or records a named failure supplied by that slice. - -Valuations and strategy contexts report settled and unsettled cash and quantities without changing -economic equity. Journals include instruction-created, completed, and failed events. Scenario v10 -and strategy protocol v8 retain their frozen immediate-settlement wire behavior. - -Version 12 adds exact stock-dividend, rights, and spin-off distributions. Each distribution names -its destination instrument, exact entitlement ratio, basis allocation in basis points, and either -rejects fractional entitlements or converts them to cash at an explicit price and currency. -Stock dividends adjust persistent targets and eligible working orders; every distribution journals -delivered quantity, fractional quantity, allocated basis, fractional basis, and cash in lieu. - -Lifecycle events keep stable instrument identity separate from mutable symbol and provider -mappings. Halt and resume transitions control tradability. Expiration and delisting are terminal, -cancel active orders, clear target exposure, and require an explicit hold or cash-out policy. -Cash-out specifies its terminal price and currency. Every transition journals the source event, -resulting listing state, provider provenance, liquidated quantity, and cash attribution. diff --git a/contracts/v12/dune b/contracts/v12/dune deleted file mode 100644 index 5cff266..0000000 --- a/contracts/v12/dune +++ /dev/null @@ -1,18 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v12/journal.schema.json) - (scenario-stream.schema.json as contracts/v12/scenario-stream.schema.json) - (scenario.schema.json as contracts/v12/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v12/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v12/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl - as - contracts/v12/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v12/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v12/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v12/fixtures/demo.journal.jsonl b/contracts/v12/fixtures/demo.journal.jsonl deleted file mode 100644 index 204d4df..0000000 --- a/contracts/v12/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,31 +0,0 @@ -{"contract_version":"12","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"ee80423182d458afa2458803c30af1d18f0a8d873bbfe4e16c510920a6aee7d3","execution_model":"completed_bar_v1"}} -{"contract_version":"12","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"12","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"12","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} -{"contract_version":"12","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"12","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"12","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"12","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000.074201","fx_rate":"1","base_value":"10000.074201","interest":"0.074201","base_interest":"0.074201","settled_amount":"10000.074201","unsettled_amount":"0","base_settled_value":"10000.074201","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.074201","settled_cash":"10000.074201","unsettled_cash":"0","margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"12","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} -{"contract_version":"12","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_amount":"0.618"}]}} -{"contract_version":"12","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000001-settlement","fill_id":"demo-fill-000000000001","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-618.868","position_movement":"6","trade_date":"2026-01-05","due_date":"2026-01-06","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} -{"contract_version":"12","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"12","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"12","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.280402","net_market_value":"749","long_market_value":"749","short_market_value":"0","gross_exposure":"749","cost_basis":"708.868","realized_pnl":"5.148402","unrealized_pnl":"40.132","equity":"10130.280402","dividend_pnl":"1","execution_fees":"1.368","borrow_fees":"0.25","total_fees":"1.618","cash_balances":[{"currency":"USD","amount":"9381.280402","fx_rate":"1","base_value":"9381.280402","interest":"0.148402","base_interest":"0.148402","settled_amount":"10000.148402","unsettled_amount":"-618.868","base_settled_value":"10000.148402","base_unsettled_value":"-618.868"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7","mark":"107","fx_rate":"1","market_value":"749","base_market_value":"749","cost_basis":"708.868","base_cost_basis":"708.868","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.132","base_unrealized_pnl":"40.132","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.368","base_execution_fees":"1.368","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.618","base_total_fees":"1.618","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}],"settled_quantity":"1","unsettled_quantity":"6"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}],"cash_interest":"0.148402","settled_cash":"10000.148402","unsettled_cash":"-618.868","margin":{"initial_requirement":"374.5","maintenance_requirement":"187.25","initial_excess":"9755.780402","maintenance_excess":"9943.030402","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"12","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"settlement_completed","payload":{"instruction_id":"demo-fill-000000000001-settlement","fill_id":"demo-fill-000000000001","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-618.868","position_movement":"6","trade_date":"2026-01-05","due_date":"2026-01-06","status":"settled","settled_at":"2026-01-06T14:30:00.000000Z","failed_at":null,"failure_reason":null}} -{"contract_version":"12","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9381.280402","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.06961","closing_balance":"9381.350012"}} -{"contract_version":"12","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.715","price":"107","notional":"290.505","fee":"0.540505","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.290505","quote_amount":"0.290505"}]}} -{"contract_version":"12","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000020"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000002-settlement","fill_id":"demo-fill-000000000002","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-291.045505","position_movement":"2.715","trade_date":"2026-01-06","due_date":"2026-01-07","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} -{"contract_version":"12","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"12","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000017","demo-event-000000000022"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000023","updated_event_id":"demo-event-000000000023","created_sequence":"23","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"12","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.304507","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.913505","realized_pnl":"5.218012","unrealized_pnl":"20.161495","equity":"10110.379507","dividend_pnl":"1","execution_fees":"1.908505","borrow_fees":"0.25","total_fees":"2.158505","cash_balances":[{"currency":"USD","amount":"9090.304507","fx_rate":"1","base_value":"9090.304507","interest":"0.218012","base_interest":"0.218012","settled_amount":"9381.350012","unsettled_amount":"-291.045505","base_settled_value":"9381.350012","base_unsettled_value":"-291.045505"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.913505","base_cost_basis":"999.913505","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.161495","base_unrealized_pnl":"20.161495","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.908505","base_execution_fees":"1.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.158505","base_total_fees":"2.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}],"settled_quantity":"7","unsettled_quantity":"2.715"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}],"cash_interest":"0.218012","settled_cash":"9381.350012","unsettled_cash":"-291.045505","margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.342007","maintenance_excess":"9855.360757","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"12","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"settlement_completed","payload":{"instruction_id":"demo-fill-000000000002-settlement","fill_id":"demo-fill-000000000002","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"-291.045505","position_movement":"2.715","trade_date":"2026-01-06","due_date":"2026-01-07","status":"settled","settled_at":"2026-01-07T14:30:00.000000Z","failed_at":null,"failure_reason":null}} -{"contract_version":"12","engine_sequence":"27","event_id":"demo-event-000000000027","causation_ids":["demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.304507","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067451","closing_balance":"9090.371958"}} -{"contract_version":"12","engine_sequence":"28","event_id":"demo-event-000000000028","causation_ids":["demo-event-000000000023","demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"105","notional":"757.575","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.757575","quote_amount":"0.757575"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_amount":"-0.007575"}]}} -{"contract_version":"12","engine_sequence":"29","event_id":"demo-event-000000000029","causation_ids":["demo-event-000000000028"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"settlement_instruction_created","payload":{"instruction_id":"demo-fill-000000000003-settlement","fill_id":"demo-fill-000000000003","instrument_id":"demo-equity-acme","currency":"USD","cash_movement":"756.575","position_movement":"-7.215","trade_date":"2026-01-07","due_date":"2026-01-08","status":"pending","settled_at":null,"failed_at":null,"failure_reason":null}} -{"contract_version":"12","engine_sequence":"30","event_id":"demo-event-000000000030","causation_ids":["demo-event-000000000025"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.946958","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"19.25872","unrealized_pnl":"7.688238","equity":"10111.946958","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.946958","fx_rate":"1","base_value":"9846.946958","interest":"0.285463","base_interest":"0.285463","settled_amount":"9090.371958","unsettled_amount":"756.575","base_settled_value":"9090.371958","base_unsettled_value":"756.575"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"settled_quantity":"9.715","unsettled_quantity":"-7.215"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"cash_interest":"0.285463","settled_cash":"9090.371958","unsettled_cash":"756.575","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.446958","maintenance_excess":"10045.696958","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"31","event_id":"demo-event-000000000031","causation_ids":["demo-event-000000000030"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"ee80423182d458afa2458803c30af1d18f0a8d873bbfe4e16c510920a6aee7d3","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9846.946958","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"19.25872","unrealized_pnl":"7.688238","equity":"10111.946958","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.946958","fx_rate":"1","base_value":"9846.946958","interest":"0.285463","base_interest":"0.285463","settled_amount":"9090.371958","unsettled_amount":"756.575","base_settled_value":"9090.371958","base_unsettled_value":"756.575"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"settled_quantity":"9.715","unsettled_quantity":"-7.215"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"cash_interest":"0.285463","settled_cash":"9090.371958","unsettled_cash":"756.575","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.446958","maintenance_excess":"10045.696958","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v12/fixtures/demo.scenario.json b/contracts/v12/fixtures/demo.scenario.json deleted file mode 100644 index cbabef0..0000000 --- a/contracts/v12/fixtures/demo.scenario.json +++ /dev/null @@ -1,444 +0,0 @@ -{ - "contract_version": "12", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "taker" - }, - { - "name": "maker_rebate", - "currency": "USD", - "kind": "notional_bps", - "value": -2, - "rounding": "nearest", - "applies_to": "maker" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-06T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-06T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-07T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-07T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v12/fixtures/demo.scenario.jsonl b/contracts/v12/fixtures/demo.scenario.jsonl deleted file mode 100644 index d4e5fbb..0000000 --- a/contracts/v12/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"12","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"12","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"12","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"12","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"12","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"12","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v12/fixtures/fill-clipped.journal.jsonl b/contracts/v12/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 168bcc2..0000000 --- a/contracts/v12/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"12","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"24baff6bd716f87e9bb1aab521527ba056c089390c442e6e650ea193df12abfe","execution_model":"completed_bar_v1"}} -{"contract_version":"12","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"12","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"12","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} -{"contract_version":"12","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"12","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.004081","fx_rate":"1","base_value":"550.004081","interest":"0.004081","base_interest":"0.004081","settled_amount":"550.004081","unsettled_amount":"0","base_settled_value":"550.004081","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.004081","settled_cash":"550.004081","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"12","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} -{"contract_version":"12","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"12","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"12","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} -{"contract_version":"12","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"24baff6bd716f87e9bb1aab521527ba056c089390c442e6e650ea193df12abfe","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v12/fixtures/fill-clipped.scenario.json b/contracts/v12/fixtures/fill-clipped.scenario.json deleted file mode 100644 index ff34f55..0000000 --- a/contracts/v12/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,267 +0,0 @@ -{ - "contract_version": "12", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v12/journal.schema.json b/contracts/v12/journal.schema.json deleted file mode 100644 index 210f8e3..0000000 --- a/contracts/v12/journal.schema.json +++ /dev/null @@ -1,2394 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v12/journal.schema.json", - "title": "Trading Engine v12 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { - "const": "12" - }, - "engine_sequence": { - "$ref": "#/$defs/sequence" - }, - "event_id": { - "$ref": "#/$defs/identifier" - }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/$defs/identifier" - } - }, - "run_id": { - "$ref": "#/$defs/identifier" - }, - "recorded_at": { - "$ref": "#/$defs/timestamp" - }, - "event_type": { - "enum": [ - "run_started", - "initial_state", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_triggered", - "order_cancelled", - "split_applied", - "cash_dividend_applied", - "distribution_applied", - "lifecycle_applied", - "order_adjusted", - "fill_applied", - "settlement_instruction_created", - "settlement_completed", - "settlement_failed", - "fill_clipped", - "borrow_fee_applied", - "borrow_charge_applied", - "borrow_recall_received", - "cash_interest_applied", - "margin_call", - "margin_restored", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { - "type": "object" - } - }, - "allOf": [ - { - "if": { - "properties": { - "event_type": { - "const": "run_started" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runStarted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "initial_state" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/initialState" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "market_slice_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/marketSlice" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "target_portfolio_requested" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/targetPortfolio" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "order_accepted", - "order_rejected", - "order_triggered" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/order" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_cancelled" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderCancelled" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "split_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/splitApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_dividend_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/dividendApplied" - } - } - } - }, - { - "if": { "properties": { "event_type": { "const": "distribution_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/distributionApplied" } } } - }, - { - "if": { "properties": { "event_type": { "const": "lifecycle_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/lifecycleApplied" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_adjusted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderAdjusted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fill" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "settlement_instruction_created", - "settlement_completed", - "settlement_failed" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/settlementInstruction" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_clipped" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fillClipped" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_fee_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowFee" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_charge_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowCharge" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_recall_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowRecall" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_interest_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/cashInterest" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "margin_call", - "margin_restored", - "valuation" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/valuation" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "intent_rejected" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/intentRejected" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "metric_emitted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/metric" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_completed" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runCompleted" - } - } - } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "nonnegativeSequence": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "const": "completed_bar_v1" - } - } - }, - "initialState": { - "type": "object", - "additionalProperties": false, - "required": [ - "portfolio", - "valuation" - ], - "properties": { - "portfolio": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/initialPortfolio" - }, - "valuation": { - "$ref": "#/$defs/valuation" - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "open", - "high", - "low", - "close", - "volume" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "open": { - "$ref": "#/$defs/positiveDecimal" - }, - "high": { - "$ref": "#/$defs/positiveDecimal" - }, - "low": { - "$ref": "#/$defs/positiveDecimal" - }, - "close": { - "$ref": "#/$defs/positiveDecimal" - }, - "volume": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/unsignedDecimal" - } - ] - } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "rate" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "rate": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "numerator", - "denominator" - ], - "properties": { - "type": { - "const": "split" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "numerator": { - "$ref": "#/$defs/sequence" - }, - "denominator": { - "$ref": "#/$defs/sequence" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "amount_per_unit" - ], - "properties": { - "type": { - "const": "cash_dividend" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "amount_per_unit": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/fractionalPolicy" } - } - } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars", - "fx_rates", - "corporate_actions", - "borrow_observations", - "cash_rate_observations", - "settlement_failures", - "lifecycle_events" - ], - "properties": { - "slice_sequence": { - "$ref": "#/$defs/sequence" - }, - "start_at": { - "$ref": "#/$defs/timestamp" - }, - "end_at": { - "$ref": "#/$defs/timestamp" - }, - "available_at": { - "$ref": "#/$defs/timestamp" - }, - "received_at": { - "$ref": "#/$defs/timestamp" - }, - "bars": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/bar" - } - }, - "fx_rates": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/fxRate" - } - }, - "corporate_actions": { - "type": "array", - "items": { - "$ref": "#/$defs/corporateAction" - } - }, - "borrow_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/borrowObservation" - } - }, - "cash_rate_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/cashRateObservation" - } - }, - "settlement_failures": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/settlementFailure" - } - }, - "lifecycle_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/lifecycleEvent" - } - } - } - }, - "settlementInstruction": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "fill_id", "instrument_id", "currency", "cash_movement", "position_movement", "trade_date", "due_date", "status", "settled_at", "failed_at", "failure_reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "fill_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "cash_movement": { "$ref": "#/$defs/signedDecimal" }, - "position_movement": { "$ref": "#/$defs/signedDecimal" }, - "trade_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "due_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "status": { "enum": ["pending", "settled", "failed"] }, - "settled_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failed_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failure_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" }] } - } - }, - "targetPortfolio": { - "type": "object", - "additionalProperties": false, - "required": [ - "basis", - "targets" - ], - "properties": { - "basis": { - "enum": [ - "weights", - "quantities" - ] - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "weight", - "quantity", - "reference_price" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "weight": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "reference_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - } - } - } - } - } - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "trigger_price", - "limit_price", - "time_in_force", - "venue_id", - "calendar_id", - "expires_at", - "origin", - "created_event_id", - "updated_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "triggered_at", - "triggered_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "order_kind": { - "enum": [ - "market", - "limit", - "stop", - "stop_limit" - ] - }, - "trigger_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "limit_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "time_in_force": { - "enum": [ - "gtc", - "ioc", - "fok", - "day", - "gtd" - ] - }, - "venue_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "calendar_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "expires_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "origin": { - "enum": [ - "direct", - "target_rebalance", - "margin_liquidation", - "borrow_recall", - "instrument_halt", - "instrument_terminal" - ] - }, - "created_event_id": { - "$ref": "#/$defs/identifier" - }, - "updated_event_id": { - "$ref": "#/$defs/identifier" - }, - "created_sequence": { - "$ref": "#/$defs/sequence" - }, - "created_at": { - "$ref": "#/$defs/timestamp" - }, - "eligible_after_slice_sequence": { - "$ref": "#/$defs/nonnegativeSequence" - }, - "triggered_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "triggered_slice_sequence": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/sequence" - } - ] - }, - "filled_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "filled_notional": { - "$ref": "#/$defs/unsignedDecimal" - }, - "status": { - "enum": [ - "working", - "partially_filled", - "filled", - "cancelled", - "rejected" - ] - }, - "rejection_reason": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "minLength": 1 - } - ] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "reason" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "reason": { - "enum": [ - "strategy_requested", - "target_replaced", - "market_ioc", - "immediate_or_cancel", - "fill_or_kill", - "day_expired", - "gtd_expired", - "margin_call", - "borrow_recall" - ] - } - } - }, - "splitApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "previous_quantity", - "adjusted_quantity" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "previous_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "adjusted_quantity": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "dividendApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "quantity", - "cash_amount" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "distributionApplied": { - "type": "object", - "additionalProperties": false, - "required": ["action", "source_quantity", "destination_quantity", "fractional_quantity", "allocated_basis", "fractional_basis", "cash_in_lieu"], - "properties": { - "action": { "$ref": "#/$defs/corporateAction" }, - "source_quantity": { "$ref": "#/$defs/signedDecimal" }, - "destination_quantity": { "$ref": "#/$defs/signedDecimal" }, - "fractional_quantity": { "$ref": "#/$defs/signedDecimal" }, - "allocated_basis": { "$ref": "#/$defs/signedDecimal" }, - "fractional_basis": { "$ref": "#/$defs/signedDecimal" }, - "cash_in_lieu": { "$ref": "#/$defs/signedDecimal" } - } - }, - "lifecycleApplied": { - "type": "object", - "additionalProperties": false, - "required": ["lifecycle_event", "listing", "liquidated_quantity", "cash_amount"], - "properties": { - "lifecycle_event": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/lifecycleEvent" }, - "listing": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "status", "provider_mappings"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "status": { "enum": ["tradable", "halted", "expired", "delisted"] }, - "provider_mappings": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["provider", "provider_instrument_id"], - "properties": { - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - } - } - } - }, - "liquidated_quantity": { "$ref": "#/$defs/signedDecimal" }, - "cash_amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "orderAdjusted": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "action_id" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "action_id": { - "$ref": "#/$defs/identifier" - } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "quote_currency", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence", - "fee_components" - ], - "properties": { - "fill_id": { - "$ref": "#/$defs/identifier" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - }, - "notional": { - "$ref": "#/$defs/positiveDecimal" - }, - "fee": { - "$ref": "#/$defs/signedDecimal" - }, - "fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/calculatedFeeComponent" - } - }, - "executed_at": { - "$ref": "#/$defs/timestamp" - }, - "slice_sequence": { - "$ref": "#/$defs/sequence" - } - } - }, - "calculatedFeeComponent": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "feeComponentAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_currency", - "quote_amount", - "base_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "quantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "moneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "ratioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "basisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentQuantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "currencyMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "unit", "value"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "money" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "settlementPositionThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "unit", "value"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "quantity" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrumentBasisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentShortingThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "value": { - "const": false - } - } - }, - "groupMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "groupRatioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "fillClipReason": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_order_quantity" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_long_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_short_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/moneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_leverage" - }, - "threshold": { - "$ref": "#/$defs/ratioThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "initial_margin" - }, - "threshold": { - "$ref": "#/$defs/basisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_long_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_cash_buying_power" }, - "threshold": { "$ref": "#/$defs/currencyMoneyThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_position_availability" }, - "threshold": { "$ref": "#/$defs/settlementPositionThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_short_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_notional_exposure" - }, - "threshold": { - "$ref": "#/$defs/instrumentMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_shorting_disabled" - }, - "threshold": { - "$ref": "#/$defs/instrumentShortingThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_borrow_availability" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_initial_margin" - }, - "threshold": { - "$ref": "#/$defs/instrumentBasisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_long_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_short_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_absolute_net_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_concentration" - }, - "threshold": { - "$ref": "#/$defs/groupRatioThreshold" - } - } - } - ] - }, - "fillClipped": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason", - "order_id", - "instrument_id", - "proposed_quantity", - "permitted_quantity", - "price" - ], - "properties": { - "reason": { - "$ref": "#/$defs/fillClipReason" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "proposed_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "permitted_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowFee": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "short_quantity", - "reference_price", - "borrow_bps", - "period_start", - "period_end", - "fee" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "borrow_bps": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "fee": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowCharge": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "quote_currency", - "short_quantity", - "reference_price", - "day_count", - "compounding", - "period_start", - "period_end", - "amount" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/borrowObservation" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "borrowRecall": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "short_quantity", - "close_out_quantity" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/borrowObservation" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "close_out_quantity": { - "$ref": "#/$defs/unsignedDecimal" - } - } - }, - "cashInterest": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "opening_balance", - "applied_rate_bps", - "day_count", - "compounding", - "period_start", - "period_end", - "amount", - "closing_balance" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/cashRateObservation" - }, - "opening_balance": { - "$ref": "#/$defs/signedDecimal" - }, - "applied_rate_bps": { - "type": "integer", - "minimum": -1000000, - "maximum": 1000000 - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "closing_balance": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "cashAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "amount", - "fx_rate", - "base_value", - "interest", - "base_interest", - "settled_amount", - "unsettled_amount", - "base_settled_value", - "base_unsettled_value" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "base_value": { - "$ref": "#/$defs/signedDecimal" - }, - "interest": { - "$ref": "#/$defs/signedDecimal" - }, - "base_interest": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_settled_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unsettled_value": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "quantity", - "settled_quantity", - "unsettled_quantity", - "mark", - "fx_rate", - "market_value", - "base_market_value", - "cost_basis", - "base_cost_basis", - "realized_pnl", - "base_realized_pnl", - "unrealized_pnl", - "base_unrealized_pnl", - "dividend_pnl", - "base_dividend_pnl", - "execution_fees", - "base_execution_fees", - "borrow_fees", - "base_borrow_fees", - "total_fees", - "base_total_fees", - "execution_fee_components" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "mark": { - "$ref": "#/$defs/positiveDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "base_cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - } - } - }, - "margin": { - "type": "object", - "additionalProperties": false, - "required": [ - "initial_requirement", - "maintenance_requirement", - "initial_excess", - "maintenance_excess", - "margin_call" - ], - "properties": { - "initial_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "maintenance_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "initial_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "maintenance_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "margin_call": { - "type": "boolean" - } - } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "gross_exposure", - "net_exposure", - "long_exposure", - "short_exposure", - "concentration" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "net_exposure": { - "$ref": "#/$defs/signedDecimal" - }, - "long_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "concentration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "base_currency", - "cash", - "settled_cash", - "unsettled_cash", - "net_market_value", - "long_market_value", - "short_market_value", - "gross_exposure", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "dividend_pnl", - "execution_fees", - "borrow_fees", - "cash_interest", - "total_fees", - "cash_balances", - "positions", - "margin", - "group_exposures", - "execution_fee_components" - ], - "properties": { - "base_currency": { - "$ref": "#/$defs/identifier" - }, - "cash": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "net_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "long_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "equity": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/cashAttribution" - } - }, - "positions": { - "type": "array", - "items": { - "$ref": "#/$defs/positionAttribution" - } - }, - "margin": { - "$ref": "#/$defs/margin" - }, - "group_exposures": { - "type": "array", - "items": { - "$ref": "#/$defs/groupExposure" - } - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - }, - "cash_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "minLength": 1 - } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "const": "completed_bar_v1" - }, - "valuation": { - "$ref": "#/$defs/valuation" - }, - "order_counts": { - "type": "object", - "additionalProperties": false, - "required": [ - "total", - "active", - "filled", - "rejected", - "cancelled" - ], - "properties": { - "total": { - "type": "integer", - "minimum": 0 - }, - "active": { - "type": "integer", - "minimum": 0 - }, - "filled": { - "type": "integer", - "minimum": 0 - }, - "rejected": { - "type": "integer", - "minimum": 0 - }, - "cancelled": { - "type": "integer", - "minimum": 0 - } - } - } - } - } - } -} diff --git a/contracts/v12/scenario-stream.schema.json b/contracts/v12/scenario-stream.schema.json deleted file mode 100644 index e6aa4dd..0000000 --- a/contracts/v12/scenario-stream.schema.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v12/scenario-stream.schema.json", - "title": "Trading Engine v12 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "12" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "12" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "12" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v12/scenario.schema.json b/contracts/v12/scenario.schema.json deleted file mode 100644 index 82c0c8c..0000000 --- a/contracts/v12/scenario.schema.json +++ /dev/null @@ -1,669 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v12/scenario.schema.json", - "title": "Trading Engine v12 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "12" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "financing": { "$ref": "#/$defs/financing" }, - "settlement": { "$ref": "#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "settlement": { - "type": "object", - "additionalProperties": false, - "required": ["cash_buying_power", "position_availability", "calendars", "rules"], - "properties": { - "cash_buying_power": { "enum": ["total_cash", "settled_cash"] }, - "position_availability": { "enum": ["total_positions", "settled_positions"] }, - "calendars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementCalendar" } }, - "rules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementRule" } } - } - }, - "settlementCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "version", "business_dates"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "version": { "const": "1" }, - "business_dates": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } - } - }, - "settlementRule": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "calendar_id", "lag_business_days"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "calendar_id": { "$ref": "#/$defs/identifier" }, - "lag_business_days": { "type": "integer", "minimum": 0, "maximum": 30 } - } - }, - "settlementFailure": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - }, - "financing": { - "type": "object", - "additionalProperties": false, - "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], - "properties": { - "day_count": { "enum": ["actual_365", "actual_360"] }, - "compounding": { "enum": ["simple", "daily"] }, - "borrow_missing_data": { "enum": ["reject", "zero"] }, - "cash_missing_data": { "enum": ["reject", "zero"] }, - "locate_policy": { "enum": ["reject_order", "clip_fill"] }, - "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } - } - }, - "borrowObservation": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, - "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "recalled": { "type": "boolean" } - } - }, - "cashRateObservation": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } - } - }, - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations", "settlement_failures", "lifecycle_events"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, - "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, - "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } }, - "settlement_failures": { "type": "array", "items": { "$ref": "#/$defs/settlementFailure" } }, - "lifecycle_events": { "type": "array", "items": { "$ref": "#/$defs/lifecycleEvent" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "#/$defs/fractionalPolicy" } - } - } - ] - }, - "fractionalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "reject" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_in_lieu" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "terminalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "hold" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_out" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "lifecycleEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "reason"], - "properties": { - "type": { "const": "halt" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1 } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id"], - "properties": { - "type": { "const": "resume" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "symbol", "provider", "provider_instrument_id"], - "properties": { - "type": { "const": "identifier_change" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy"], - "properties": { - "type": { "const": "expiration" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy", "reason"], - "properties": { - "type": { "const": "delisting" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - } - } -} diff --git a/contracts/v13/README.md b/contracts/v13/README.md deleted file mode 100644 index 093283c..0000000 --- a/contracts/v13/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# Trading Engine contract v13 - -This directory is the authoritative v13 process and file contract shared by Trading Engine and its -clients. Versions 12 through 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v13 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v13 scenario, stream record, and journal record carries `"contract_version": "13"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v10 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. - -Version 10 adds a required `financing` policy and effective-time observations on every market -slice. Borrow observations provide per-instrument locate availability, signed annual rates, and -recall state. Cash observations provide separate annual credit and debit rates per currency. -Policies select Actual/365 or Actual/360 day count, simple or daily compounding, missing-data -handling, locate rejection or fill clipping, and recall rejection or deterministic close-out. - -Borrow availability is enforced when a fill would create or increase a short. Recalls cancel -active sells and may submit priority IOC covers until the position is flat. Borrow charges and cash -interest use the exact slice interval, update native ledgers deterministically, and emit dedicated -journal records. Valuations report cash interest separately and include it in aggregate realized -P&L. Version 9 and earlier retain their frozen fixed-borrow behavior and wire shapes. - -Version 11 separates trade-date economic accounting from settlement-date availability. A required -settlement policy selects total or settled cash buying power and total or settled position -availability. Versioned calendars enumerate canonical business dates, and each instrument has an -explicit business-day lag. Every fill creates a deterministic settlement instruction containing -its cash and position movements, trade date, and due date. A due instruction either settles on the -first eligible slice or records a named failure supplied by that slice. - -Valuations and strategy contexts report settled and unsettled cash and quantities without changing -economic equity. Journals include instruction-created, completed, and failed events. Scenario v10 -and strategy protocol v8 retain their frozen immediate-settlement wire behavior. - -Version 12 adds exact stock-dividend, rights, and spin-off distributions. Each distribution names -its destination instrument, exact entitlement ratio, basis allocation in basis points, and either -rejects fractional entitlements or converts them to cash at an explicit price and currency. -Stock dividends adjust persistent targets and eligible working orders; every distribution journals -delivered quantity, fractional quantity, allocated basis, fractional basis, and cash in lieu. - -Lifecycle events keep stable instrument identity separate from mutable symbol and provider -mappings. Halt and resume transitions control tradability. Expiration and delisting are terminal, -cancel active orders, clear target exposure, and require an explicit hold or cash-out policy. -Cash-out specifies its terminal price and currency. Every transition journals the source event, -resulting listing state, provider provenance, liquidated quantity, and cash attribution. - -Version 13 adds `completed_bar_next_open_v1` and `completed_bar_adverse_touch_v1` without changing -the frozen `completed_bar_v1` semantics. Next-open limits require a marketable later open; -adverse-touch limits require a one-tick trade-through before a maker fill is eligible. Both models -declare fixed half-spread and linear participation-impact catalogs, including an explicit policy -for missing bar volume. Price costs round away from the reference price to instrument ticks and -cannot violate a limit. An `execution_price_selected` audit record attributes the reference price, -spread adjustment, impact adjustment, and final executable price before each fill. diff --git a/contracts/v13/dune b/contracts/v13/dune deleted file mode 100644 index e8c2b5c..0000000 --- a/contracts/v13/dune +++ /dev/null @@ -1,18 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v13/journal.schema.json) - (scenario-stream.schema.json as contracts/v13/scenario-stream.schema.json) - (scenario.schema.json as contracts/v13/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v13/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v13/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl - as - contracts/v13/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v13/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v13/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v13/fixtures/demo.journal.jsonl b/contracts/v13/fixtures/demo.journal.jsonl deleted file mode 100644 index 4379ef7..0000000 --- a/contracts/v13/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,29 +0,0 @@ -{"contract_version":"13","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"e6d10a0b0f54a6ba6e1b37d0b35fbea5eaad7bf24fe36a6911ae44949ef9de9d","execution_model":"completed_bar_adverse_touch_v1"}} -{"contract_version":"13","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"13","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"13","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} -{"contract_version":"13","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"13","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"13","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"13","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000.074201","fx_rate":"1","base_value":"10000.074201","interest":"0.074201","base_interest":"0.074201","settled_amount":"10000.074201","unsettled_amount":"0","base_settled_value":"10000.074201","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.074201","settled_cash":"10000.074201","unsettled_cash":"0","margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"13"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"13","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} -{"contract_version":"13","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","reference_price":"103","spread_adjustment":"0.06","impact_adjustment":"0.13","final_price":"103.19"}} -{"contract_version":"13","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6.5","price":"103.19","notional":"670.735","fee":"0.920735","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_amount":"0.670735"}]}} -{"contract_version":"13","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6.5","filled_notional":"670.735","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"13","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"13","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9328.492667","net_market_value":"802.5","long_market_value":"802.5","short_market_value":"0","gross_exposure":"802.5","cost_basis":"761.655735","realized_pnl":"5.148402","unrealized_pnl":"40.844265","equity":"10130.992667","dividend_pnl":"1","execution_fees":"1.420735","borrow_fees":"0.25","total_fees":"1.670735","cash_balances":[{"currency":"USD","amount":"9328.492667","fx_rate":"1","base_value":"9328.492667","interest":"0.148402","base_interest":"0.148402","settled_amount":"9328.492667","unsettled_amount":"0","base_settled_value":"9328.492667","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7.5","mark":"107","fx_rate":"1","market_value":"802.5","base_market_value":"802.5","cost_basis":"761.655735","base_cost_basis":"761.655735","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.844265","base_unrealized_pnl":"40.844265","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.420735","base_execution_fees":"1.420735","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.670735","base_total_fees":"1.670735","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"settled_quantity":"7.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"cash_interest":"0.148402","settled_cash":"9328.492667","unsettled_cash":"0","margin":{"initial_requirement":"401.25","maintenance_requirement":"200.625","initial_excess":"9729.742667","maintenance_excess":"9930.367667","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"13","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9328.492667","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.069218","closing_balance":"9328.561885"}} -{"contract_version":"13","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","reference_price":"107","spread_adjustment":"0.06","impact_adjustment":"0.01","final_price":"107.07"}} -{"contract_version":"13","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.215","price":"107.07","notional":"237.16005","fee":"0.487161","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.237161","quote_amount":"0.237161"}]}} -{"contract_version":"13","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"13","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000017","demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000022","updated_event_id":"demo-event-000000000022","created_sequence":"22","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"13","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.914674","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.302946","realized_pnl":"5.21762","unrealized_pnl":"20.772054","equity":"10110.989674","dividend_pnl":"1","execution_fees":"1.907896","borrow_fees":"0.25","total_fees":"2.157896","cash_balances":[{"currency":"USD","amount":"9090.914674","fx_rate":"1","base_value":"9090.914674","interest":"0.21762","base_interest":"0.21762","settled_amount":"9090.914674","unsettled_amount":"0","base_settled_value":"9090.914674","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.302946","base_cost_basis":"999.302946","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.772054","base_unrealized_pnl":"20.772054","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.907896","base_execution_fees":"1.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.157896","base_total_fees":"2.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"settled_quantity":"9.715","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"cash_interest":"0.21762","settled_cash":"9090.914674","unsettled_cash":"0","margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.952174","maintenance_excess":"9855.970924","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"13","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.914674","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067455","closing_balance":"9090.982129"}} -{"contract_version":"13","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000022","demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","reference_price":"105","spread_adjustment":"0.06","impact_adjustment":"0.02","final_price":"104.92"}} -{"contract_version":"13","engine_sequence":"27","event_id":"demo-event-000000000027","causation_ids":["demo-event-000000000026"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"104.92","notional":"756.9978","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.756998","quote_amount":"0.756998"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_amount":"-0.006998"}]}} -{"contract_version":"13","engine_sequence":"28","event_id":"demo-event-000000000028","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"29","event_id":"demo-event-000000000029","causation_ids":["demo-event-000000000028"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"e6d10a0b0f54a6ba6e1b37d0b35fbea5eaad7bf24fe36a6911ae44949ef9de9d","execution_model":"completed_bar_adverse_touch_v1","valuation":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v13/fixtures/demo.scenario.json b/contracts/v13/fixtures/demo.scenario.json deleted file mode 100644 index a5d6f3b..0000000 --- a/contracts/v13/fixtures/demo.scenario.json +++ /dev/null @@ -1,453 +0,0 @@ -{ - "contract_version": "13", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_adverse_touch_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "taker" - }, - { - "name": "maker_rebate", - "currency": "USD", - "kind": "notional_bps", - "value": -2, - "rounding": "nearest", - "applies_to": "maker" - } - ] - } - ], - "spread_model": { - "model": "fixed_half_spread_v1", - "half_spread_bps": 5 - }, - "impact_model": { - "model": "linear_participation_v1", - "coefficient_bps": 25, - "missing_volume_policy": "reject" - } - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "13" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-06T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-06T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-07T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-07T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v13/fixtures/demo.scenario.jsonl b/contracts/v13/fixtures/demo.scenario.jsonl deleted file mode 100644 index b42027a..0000000 --- a/contracts/v13/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"13","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_adverse_touch_v1","configuration":{"version":"1","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}],"spread_model":{"model":"fixed_half_spread_v1","half_spread_bps":5},"impact_model":{"model":"linear_participation_v1","coefficient_bps":25,"missing_volume_policy":"reject"}}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"13","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"13","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"13"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"13","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"13","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"13","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v13/fixtures/fill-clipped.journal.jsonl b/contracts/v13/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 995c19a..0000000 --- a/contracts/v13/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"13","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"a7bee278b2c1dd07734d797ca94eae4f4a8bba1dd892ac25df31a4fa504f7b75","execution_model":"completed_bar_v1"}} -{"contract_version":"13","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"13","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"13","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} -{"contract_version":"13","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"13","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.004081","fx_rate":"1","base_value":"550.004081","interest":"0.004081","base_interest":"0.004081","settled_amount":"550.004081","unsettled_amount":"0","base_settled_value":"550.004081","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.004081","settled_cash":"550.004081","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[]}} -{"contract_version":"13","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} -{"contract_version":"13","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"13","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"13","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} -{"contract_version":"13","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"a7bee278b2c1dd07734d797ca94eae4f4a8bba1dd892ac25df31a4fa504f7b75","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v13/fixtures/fill-clipped.scenario.json b/contracts/v13/fixtures/fill-clipped.scenario.json deleted file mode 100644 index 9884ef4..0000000 --- a/contracts/v13/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,267 +0,0 @@ -{ - "contract_version": "13", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], "lifecycle_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v13/journal.schema.json b/contracts/v13/journal.schema.json deleted file mode 100644 index 1c63368..0000000 --- a/contracts/v13/journal.schema.json +++ /dev/null @@ -1,2413 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v13/journal.schema.json", - "title": "Trading Engine v13 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { - "const": "13" - }, - "engine_sequence": { - "$ref": "#/$defs/sequence" - }, - "event_id": { - "$ref": "#/$defs/identifier" - }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/$defs/identifier" - } - }, - "run_id": { - "$ref": "#/$defs/identifier" - }, - "recorded_at": { - "$ref": "#/$defs/timestamp" - }, - "event_type": { - "enum": [ - "run_started", - "initial_state", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_triggered", - "order_cancelled", - "split_applied", - "cash_dividend_applied", - "distribution_applied", - "lifecycle_applied", - "order_adjusted", - "execution_price_selected", - "fill_applied", - "settlement_instruction_created", - "settlement_completed", - "settlement_failed", - "fill_clipped", - "borrow_fee_applied", - "borrow_charge_applied", - "borrow_recall_received", - "cash_interest_applied", - "margin_call", - "margin_restored", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { - "type": "object" - } - }, - "allOf": [ - { - "if": { "properties": { "event_type": { "const": "execution_price_selected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/executionPriceSelected" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_started" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runStarted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "initial_state" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/initialState" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "market_slice_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/marketSlice" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "target_portfolio_requested" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/targetPortfolio" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "order_accepted", - "order_rejected", - "order_triggered" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/order" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_cancelled" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderCancelled" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "split_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/splitApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_dividend_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/dividendApplied" - } - } - } - }, - { - "if": { "properties": { "event_type": { "const": "distribution_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/distributionApplied" } } } - }, - { - "if": { "properties": { "event_type": { "const": "lifecycle_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/lifecycleApplied" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_adjusted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderAdjusted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fill" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "settlement_instruction_created", - "settlement_completed", - "settlement_failed" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/settlementInstruction" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_clipped" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fillClipped" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_fee_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowFee" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_charge_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowCharge" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_recall_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowRecall" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_interest_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/cashInterest" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "margin_call", - "margin_restored", - "valuation" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/valuation" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "intent_rejected" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/intentRejected" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "metric_emitted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/metric" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_completed" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runCompleted" - } - } - } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "nonnegativeSequence": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1"] - } - } - }, - "initialState": { - "type": "object", - "additionalProperties": false, - "required": [ - "portfolio", - "valuation" - ], - "properties": { - "portfolio": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/initialPortfolio" - }, - "valuation": { - "$ref": "#/$defs/valuation" - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "open", - "high", - "low", - "close", - "volume" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "open": { - "$ref": "#/$defs/positiveDecimal" - }, - "high": { - "$ref": "#/$defs/positiveDecimal" - }, - "low": { - "$ref": "#/$defs/positiveDecimal" - }, - "close": { - "$ref": "#/$defs/positiveDecimal" - }, - "volume": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/unsignedDecimal" - } - ] - } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "rate" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "rate": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "numerator", - "denominator" - ], - "properties": { - "type": { - "const": "split" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "numerator": { - "$ref": "#/$defs/sequence" - }, - "denominator": { - "$ref": "#/$defs/sequence" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "amount_per_unit" - ], - "properties": { - "type": { - "const": "cash_dividend" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "amount_per_unit": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/fractionalPolicy" } - } - } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars", - "fx_rates", - "corporate_actions", - "borrow_observations", - "cash_rate_observations", - "settlement_failures", - "lifecycle_events" - ], - "properties": { - "slice_sequence": { - "$ref": "#/$defs/sequence" - }, - "start_at": { - "$ref": "#/$defs/timestamp" - }, - "end_at": { - "$ref": "#/$defs/timestamp" - }, - "available_at": { - "$ref": "#/$defs/timestamp" - }, - "received_at": { - "$ref": "#/$defs/timestamp" - }, - "bars": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/bar" - } - }, - "fx_rates": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/fxRate" - } - }, - "corporate_actions": { - "type": "array", - "items": { - "$ref": "#/$defs/corporateAction" - } - }, - "borrow_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/borrowObservation" - } - }, - "cash_rate_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/cashRateObservation" - } - }, - "settlement_failures": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/settlementFailure" - } - }, - "lifecycle_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/lifecycleEvent" - } - } - } - }, - "settlementInstruction": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "fill_id", "instrument_id", "currency", "cash_movement", "position_movement", "trade_date", "due_date", "status", "settled_at", "failed_at", "failure_reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "fill_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "cash_movement": { "$ref": "#/$defs/signedDecimal" }, - "position_movement": { "$ref": "#/$defs/signedDecimal" }, - "trade_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "due_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "status": { "enum": ["pending", "settled", "failed"] }, - "settled_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failed_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failure_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" }] } - } - }, - "targetPortfolio": { - "type": "object", - "additionalProperties": false, - "required": [ - "basis", - "targets" - ], - "properties": { - "basis": { - "enum": [ - "weights", - "quantities" - ] - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "weight", - "quantity", - "reference_price" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "weight": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "reference_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - } - } - } - } - } - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "trigger_price", - "limit_price", - "time_in_force", - "venue_id", - "calendar_id", - "expires_at", - "origin", - "created_event_id", - "updated_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "triggered_at", - "triggered_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "order_kind": { - "enum": [ - "market", - "limit", - "stop", - "stop_limit" - ] - }, - "trigger_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "limit_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "time_in_force": { - "enum": [ - "gtc", - "ioc", - "fok", - "day", - "gtd" - ] - }, - "venue_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "calendar_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "expires_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "origin": { - "enum": [ - "direct", - "target_rebalance", - "margin_liquidation", - "borrow_recall", - "instrument_halt", - "instrument_terminal" - ] - }, - "created_event_id": { - "$ref": "#/$defs/identifier" - }, - "updated_event_id": { - "$ref": "#/$defs/identifier" - }, - "created_sequence": { - "$ref": "#/$defs/sequence" - }, - "created_at": { - "$ref": "#/$defs/timestamp" - }, - "eligible_after_slice_sequence": { - "$ref": "#/$defs/nonnegativeSequence" - }, - "triggered_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "triggered_slice_sequence": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/sequence" - } - ] - }, - "filled_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "filled_notional": { - "$ref": "#/$defs/unsignedDecimal" - }, - "status": { - "enum": [ - "working", - "partially_filled", - "filled", - "cancelled", - "rejected" - ] - }, - "rejection_reason": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "minLength": 1 - } - ] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "reason" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "reason": { - "enum": [ - "strategy_requested", - "target_replaced", - "market_ioc", - "immediate_or_cancel", - "fill_or_kill", - "day_expired", - "gtd_expired", - "margin_call", - "borrow_recall" - ] - } - } - }, - "splitApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "previous_quantity", - "adjusted_quantity" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "previous_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "adjusted_quantity": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "dividendApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "quantity", - "cash_amount" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "distributionApplied": { - "type": "object", - "additionalProperties": false, - "required": ["action", "source_quantity", "destination_quantity", "fractional_quantity", "allocated_basis", "fractional_basis", "cash_in_lieu"], - "properties": { - "action": { "$ref": "#/$defs/corporateAction" }, - "source_quantity": { "$ref": "#/$defs/signedDecimal" }, - "destination_quantity": { "$ref": "#/$defs/signedDecimal" }, - "fractional_quantity": { "$ref": "#/$defs/signedDecimal" }, - "allocated_basis": { "$ref": "#/$defs/signedDecimal" }, - "fractional_basis": { "$ref": "#/$defs/signedDecimal" }, - "cash_in_lieu": { "$ref": "#/$defs/signedDecimal" } - } - }, - "lifecycleApplied": { - "type": "object", - "additionalProperties": false, - "required": ["lifecycle_event", "listing", "liquidated_quantity", "cash_amount"], - "properties": { - "lifecycle_event": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/lifecycleEvent" }, - "listing": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "status", "provider_mappings"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "status": { "enum": ["tradable", "halted", "expired", "delisted"] }, - "provider_mappings": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["provider", "provider_instrument_id"], - "properties": { - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - } - } - } - }, - "liquidated_quantity": { "$ref": "#/$defs/signedDecimal" }, - "cash_amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "orderAdjusted": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "action_id" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "action_id": { - "$ref": "#/$defs/identifier" - } - } - }, - "executionPriceSelected": { - "type": "object", - "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "reference_price", "spread_adjustment", "impact_adjustment", "final_price"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "reference_price": { "$ref": "#/$defs/positiveDecimal" }, - "spread_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "impact_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "final_price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "quote_currency", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence", - "fee_components" - ], - "properties": { - "fill_id": { - "$ref": "#/$defs/identifier" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - }, - "notional": { - "$ref": "#/$defs/positiveDecimal" - }, - "fee": { - "$ref": "#/$defs/signedDecimal" - }, - "fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/calculatedFeeComponent" - } - }, - "executed_at": { - "$ref": "#/$defs/timestamp" - }, - "slice_sequence": { - "$ref": "#/$defs/sequence" - } - } - }, - "calculatedFeeComponent": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "feeComponentAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_currency", - "quote_amount", - "base_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "quantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "moneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "ratioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "basisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentQuantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "currencyMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "unit", "value"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "money" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "settlementPositionThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "unit", "value"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "quantity" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrumentBasisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentShortingThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "value": { - "const": false - } - } - }, - "groupMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "groupRatioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "fillClipReason": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_order_quantity" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_long_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_short_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/moneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_leverage" - }, - "threshold": { - "$ref": "#/$defs/ratioThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "initial_margin" - }, - "threshold": { - "$ref": "#/$defs/basisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_long_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_cash_buying_power" }, - "threshold": { "$ref": "#/$defs/currencyMoneyThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_position_availability" }, - "threshold": { "$ref": "#/$defs/settlementPositionThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_short_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_notional_exposure" - }, - "threshold": { - "$ref": "#/$defs/instrumentMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_shorting_disabled" - }, - "threshold": { - "$ref": "#/$defs/instrumentShortingThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_borrow_availability" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_initial_margin" - }, - "threshold": { - "$ref": "#/$defs/instrumentBasisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_long_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_short_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_absolute_net_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_concentration" - }, - "threshold": { - "$ref": "#/$defs/groupRatioThreshold" - } - } - } - ] - }, - "fillClipped": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason", - "order_id", - "instrument_id", - "proposed_quantity", - "permitted_quantity", - "price" - ], - "properties": { - "reason": { - "$ref": "#/$defs/fillClipReason" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "proposed_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "permitted_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowFee": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "short_quantity", - "reference_price", - "borrow_bps", - "period_start", - "period_end", - "fee" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "borrow_bps": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "fee": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowCharge": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "quote_currency", - "short_quantity", - "reference_price", - "day_count", - "compounding", - "period_start", - "period_end", - "amount" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/borrowObservation" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "borrowRecall": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "short_quantity", - "close_out_quantity" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/borrowObservation" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "close_out_quantity": { - "$ref": "#/$defs/unsignedDecimal" - } - } - }, - "cashInterest": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "opening_balance", - "applied_rate_bps", - "day_count", - "compounding", - "period_start", - "period_end", - "amount", - "closing_balance" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/cashRateObservation" - }, - "opening_balance": { - "$ref": "#/$defs/signedDecimal" - }, - "applied_rate_bps": { - "type": "integer", - "minimum": -1000000, - "maximum": 1000000 - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "closing_balance": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "cashAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "amount", - "fx_rate", - "base_value", - "interest", - "base_interest", - "settled_amount", - "unsettled_amount", - "base_settled_value", - "base_unsettled_value" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "base_value": { - "$ref": "#/$defs/signedDecimal" - }, - "interest": { - "$ref": "#/$defs/signedDecimal" - }, - "base_interest": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_settled_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unsettled_value": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "quantity", - "settled_quantity", - "unsettled_quantity", - "mark", - "fx_rate", - "market_value", - "base_market_value", - "cost_basis", - "base_cost_basis", - "realized_pnl", - "base_realized_pnl", - "unrealized_pnl", - "base_unrealized_pnl", - "dividend_pnl", - "base_dividend_pnl", - "execution_fees", - "base_execution_fees", - "borrow_fees", - "base_borrow_fees", - "total_fees", - "base_total_fees", - "execution_fee_components" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "mark": { - "$ref": "#/$defs/positiveDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "base_cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - } - } - }, - "margin": { - "type": "object", - "additionalProperties": false, - "required": [ - "initial_requirement", - "maintenance_requirement", - "initial_excess", - "maintenance_excess", - "margin_call" - ], - "properties": { - "initial_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "maintenance_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "initial_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "maintenance_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "margin_call": { - "type": "boolean" - } - } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "gross_exposure", - "net_exposure", - "long_exposure", - "short_exposure", - "concentration" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "net_exposure": { - "$ref": "#/$defs/signedDecimal" - }, - "long_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "concentration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "base_currency", - "cash", - "settled_cash", - "unsettled_cash", - "net_market_value", - "long_market_value", - "short_market_value", - "gross_exposure", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "dividend_pnl", - "execution_fees", - "borrow_fees", - "cash_interest", - "total_fees", - "cash_balances", - "positions", - "margin", - "group_exposures", - "execution_fee_components" - ], - "properties": { - "base_currency": { - "$ref": "#/$defs/identifier" - }, - "cash": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "net_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "long_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "equity": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/cashAttribution" - } - }, - "positions": { - "type": "array", - "items": { - "$ref": "#/$defs/positionAttribution" - } - }, - "margin": { - "$ref": "#/$defs/margin" - }, - "group_exposures": { - "type": "array", - "items": { - "$ref": "#/$defs/groupExposure" - } - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - }, - "cash_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "minLength": 1 - } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1"] - }, - "valuation": { - "$ref": "#/$defs/valuation" - }, - "order_counts": { - "type": "object", - "additionalProperties": false, - "required": [ - "total", - "active", - "filled", - "rejected", - "cancelled" - ], - "properties": { - "total": { - "type": "integer", - "minimum": 0 - }, - "active": { - "type": "integer", - "minimum": 0 - }, - "filled": { - "type": "integer", - "minimum": 0 - }, - "rejected": { - "type": "integer", - "minimum": 0 - }, - "cancelled": { - "type": "integer", - "minimum": 0 - } - } - } - } - } - } -} diff --git a/contracts/v13/scenario-stream.schema.json b/contracts/v13/scenario-stream.schema.json deleted file mode 100644 index 22d7003..0000000 --- a/contracts/v13/scenario-stream.schema.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v13/scenario-stream.schema.json", - "title": "Trading Engine v13 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "13" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "13" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "13" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v13/scenario.schema.json b/contracts/v13/scenario.schema.json deleted file mode 100644 index 0a072d1..0000000 --- a/contracts/v13/scenario.schema.json +++ /dev/null @@ -1,713 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v13/scenario.schema.json", - "title": "Trading Engine v13 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "13" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "financing": { "$ref": "#/$defs/financing" }, - "settlement": { "$ref": "#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "settlement": { - "type": "object", - "additionalProperties": false, - "required": ["cash_buying_power", "position_availability", "calendars", "rules"], - "properties": { - "cash_buying_power": { "enum": ["total_cash", "settled_cash"] }, - "position_availability": { "enum": ["total_positions", "settled_positions"] }, - "calendars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementCalendar" } }, - "rules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementRule" } } - } - }, - "settlementCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "version", "business_dates"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "version": { "const": "1" }, - "business_dates": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } - } - }, - "settlementRule": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "calendar_id", "lag_business_days"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "calendar_id": { "$ref": "#/$defs/identifier" }, - "lag_business_days": { "type": "integer", "minimum": 0, "maximum": 30 } - } - }, - "settlementFailure": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - }, - "financing": { - "type": "object", - "additionalProperties": false, - "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], - "properties": { - "day_count": { "enum": ["actual_365", "actual_360"] }, - "compounding": { "enum": ["simple", "daily"] }, - "borrow_missing_data": { "enum": ["reject", "zero"] }, - "cash_missing_data": { "enum": ["reject", "zero"] }, - "locate_policy": { "enum": ["reject_order", "clip_fill"] }, - "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } - } - }, - "borrowObservation": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, - "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "recalled": { "type": "boolean" } - } - }, - "cashRateObservation": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } - } - }, - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "enum": ["completed_bar_next_open_v1", "completed_bar_adverse_touch_v1"] }, - "configuration": { "$ref": "#/$defs/conservativeBarConfiguration" } - } - } - ] - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "conservativeBarConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules", "spread_model", "impact_model"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, - "spread_model": { "$ref": "#/$defs/fixedSpreadModel" }, - "impact_model": { "$ref": "#/$defs/linearImpactModel" } - } - }, - "fixedSpreadModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "half_spread_bps"], - "properties": { - "model": { "const": "fixed_half_spread_v1" }, - "half_spread_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "linearImpactModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "coefficient_bps", "missing_volume_policy"], - "properties": { - "model": { "const": "linear_participation_v1" }, - "coefficient_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "missing_volume_policy": { "enum": ["reject", "zero_impact"] } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations", "settlement_failures", "lifecycle_events"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, - "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, - "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } }, - "settlement_failures": { "type": "array", "items": { "$ref": "#/$defs/settlementFailure" } }, - "lifecycle_events": { "type": "array", "items": { "$ref": "#/$defs/lifecycleEvent" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "#/$defs/fractionalPolicy" } - } - } - ] - }, - "fractionalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "reject" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_in_lieu" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "terminalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "hold" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_out" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "lifecycleEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "reason"], - "properties": { - "type": { "const": "halt" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1 } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id"], - "properties": { - "type": { "const": "resume" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "symbol", "provider", "provider_instrument_id"], - "properties": { - "type": { "const": "identifier_change" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy"], - "properties": { - "type": { "const": "expiration" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy", "reason"], - "properties": { - "type": { "const": "delisting" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - } - } -} diff --git a/contracts/v14/README.md b/contracts/v14/README.md deleted file mode 100644 index cf247f4..0000000 --- a/contracts/v14/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# Trading Engine contract v14 - -This directory is the authoritative v14 process and file contract shared by Trading Engine and its -clients. Versions 13 through 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v14 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v14 scenario, stream record, and journal record carries `"contract_version": "14"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v10 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. - -Version 10 adds a required `financing` policy and effective-time observations on every market -slice. Borrow observations provide per-instrument locate availability, signed annual rates, and -recall state. Cash observations provide separate annual credit and debit rates per currency. -Policies select Actual/365 or Actual/360 day count, simple or daily compounding, missing-data -handling, locate rejection or fill clipping, and recall rejection or deterministic close-out. - -Borrow availability is enforced when a fill would create or increase a short. Recalls cancel -active sells and may submit priority IOC covers until the position is flat. Borrow charges and cash -interest use the exact slice interval, update native ledgers deterministically, and emit dedicated -journal records. Valuations report cash interest separately and include it in aggregate realized -P&L. Version 9 and earlier retain their frozen fixed-borrow behavior and wire shapes. - -Version 12 separates trade-date economic accounting from settlement-date availability. A required -settlement policy selects total or settled cash buying power and total or settled position -availability. Versioned calendars enumerate canonical business dates, and each instrument has an -explicit business-day lag. Every fill creates a deterministic settlement instruction containing -its cash and position movements, trade date, and due date. A due instruction either settles on the -first eligible slice or records a named failure supplied by that slice. - -Valuations and strategy contexts report settled and unsettled cash and quantities without changing -economic equity. Journals include instruction-created, completed, and failed events. Scenario v10 -and strategy protocol v8 retain their frozen immediate-settlement wire behavior. - -Version 12 adds exact stock-dividend, rights, and spin-off distributions. Each distribution names -its destination instrument, exact entitlement ratio, basis allocation in basis points, and either -rejects fractional entitlements or converts them to cash at an explicit price and currency. -Stock dividends adjust persistent targets and eligible working orders; every distribution journals -delivered quantity, fractional quantity, allocated basis, fractional basis, and cash in lieu. - -Lifecycle events keep stable instrument identity separate from mutable symbol and provider -mappings. Halt and resume transitions control tradability. Expiration and delisting are terminal, -cancel active orders, clear target exposure, and require an explicit hold or cash-out policy. -Cash-out specifies its terminal price and currency. Every transition journals the source event, -resulting listing state, provider provenance, liquidated quantity, and cash attribution. - -Version 13 adds `completed_bar_next_open_v1` and `completed_bar_adverse_touch_v1` without changing -the frozen `completed_bar_v1` semantics. Next-open limits require a marketable later open; -adverse-touch limits require a one-tick trade-through before a maker fill is eligible. Both models -declare fixed half-spread and linear participation-impact catalogs, including an explicit policy -for missing bar volume. Price costs round away from the reference price to instrument ticks and -cannot violate a limit. An `execution_price_selected` audit record attributes the reference price, -spread adjustment, impact adjustment, and final executable price before each fill. - -Version 14 adds `quote_trade_v1` and causally ordered `market_events`. Quotes expose bid/ask price -and displayed size. Trades expose price, size, and buy, sell, or unknown aggressor side. Each event -records economic, availability, and receipt timestamps plus a positive ingest sequence. Replay -orders events by availability, receipt, and ingest sequence. Marketable orders consume only -displayed quote liquidity; passive orders require appropriately aggressed trade evidence, and an -unknown aggressor never fills them. Event capacity is shared deterministically across order -priority and fills retain the event's economic timestamp. Completed bars remain the valuation -boundary. The `quote-trade` batch, stream, and journal fixtures demonstrate equivalent replay. diff --git a/contracts/v14/dune b/contracts/v14/dune deleted file mode 100644 index 17e522a..0000000 --- a/contracts/v14/dune +++ /dev/null @@ -1,27 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v14/journal.schema.json) - (scenario-stream.schema.json as contracts/v14/scenario-stream.schema.json) - (scenario.schema.json as contracts/v14/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v14/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v14/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl - as - contracts/v14/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v14/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v14/fixtures/fill-clipped.scenario.json) - (fixtures/quote-trade.journal.jsonl - as - contracts/v14/fixtures/quote-trade.journal.jsonl) - (fixtures/quote-trade.scenario.json - as - contracts/v14/fixtures/quote-trade.scenario.json) - (fixtures/quote-trade.scenario.jsonl - as - contracts/v14/fixtures/quote-trade.scenario.jsonl))) diff --git a/contracts/v14/fixtures/demo.journal.jsonl b/contracts/v14/fixtures/demo.journal.jsonl deleted file mode 100644 index 3f41591..0000000 --- a/contracts/v14/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,29 +0,0 @@ -{"contract_version":"14","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"49cac47b2abf617f1610d65a29984ab6cd848cd42c28b5d190fb34369365b18f","execution_model":"completed_bar_adverse_touch_v1"}} -{"contract_version":"14","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"14","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}} -{"contract_version":"14","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} -{"contract_version":"14","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"14","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"14","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"14","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000.074201","fx_rate":"1","base_value":"10000.074201","interest":"0.074201","base_interest":"0.074201","settled_amount":"10000.074201","unsettled_amount":"0","base_settled_value":"10000.074201","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.074201","settled_cash":"10000.074201","unsettled_cash":"0","margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"13"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}} -{"contract_version":"14","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} -{"contract_version":"14","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","reference_price":"103","spread_adjustment":"0.06","impact_adjustment":"0.13","final_price":"103.19"}} -{"contract_version":"14","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6.5","price":"103.19","notional":"670.735","fee":"0.920735","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_amount":"0.670735"}]}} -{"contract_version":"14","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6.5","filled_notional":"670.735","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"14","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"14","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9328.492667","net_market_value":"802.5","long_market_value":"802.5","short_market_value":"0","gross_exposure":"802.5","cost_basis":"761.655735","realized_pnl":"5.148402","unrealized_pnl":"40.844265","equity":"10130.992667","dividend_pnl":"1","execution_fees":"1.420735","borrow_fees":"0.25","total_fees":"1.670735","cash_balances":[{"currency":"USD","amount":"9328.492667","fx_rate":"1","base_value":"9328.492667","interest":"0.148402","base_interest":"0.148402","settled_amount":"9328.492667","unsettled_amount":"0","base_settled_value":"9328.492667","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7.5","mark":"107","fx_rate":"1","market_value":"802.5","base_market_value":"802.5","cost_basis":"761.655735","base_cost_basis":"761.655735","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.844265","base_unrealized_pnl":"40.844265","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.420735","base_execution_fees":"1.420735","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.670735","base_total_fees":"1.670735","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"settled_quantity":"7.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"cash_interest":"0.148402","settled_cash":"9328.492667","unsettled_cash":"0","margin":{"initial_requirement":"401.25","maintenance_requirement":"200.625","initial_excess":"9729.742667","maintenance_excess":"9930.367667","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}} -{"contract_version":"14","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9328.492667","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.069218","closing_balance":"9328.561885"}} -{"contract_version":"14","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","reference_price":"107","spread_adjustment":"0.06","impact_adjustment":"0.01","final_price":"107.07"}} -{"contract_version":"14","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.215","price":"107.07","notional":"237.16005","fee":"0.487161","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.237161","quote_amount":"0.237161"}]}} -{"contract_version":"14","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"14","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000017","demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000022","updated_event_id":"demo-event-000000000022","created_sequence":"22","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"14","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.914674","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.302946","realized_pnl":"5.21762","unrealized_pnl":"20.772054","equity":"10110.989674","dividend_pnl":"1","execution_fees":"1.907896","borrow_fees":"0.25","total_fees":"2.157896","cash_balances":[{"currency":"USD","amount":"9090.914674","fx_rate":"1","base_value":"9090.914674","interest":"0.21762","base_interest":"0.21762","settled_amount":"9090.914674","unsettled_amount":"0","base_settled_value":"9090.914674","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.302946","base_cost_basis":"999.302946","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.772054","base_unrealized_pnl":"20.772054","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.907896","base_execution_fees":"1.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.157896","base_total_fees":"2.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"settled_quantity":"9.715","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"cash_interest":"0.21762","settled_cash":"9090.914674","unsettled_cash":"0","margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.952174","maintenance_excess":"9855.970924","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}} -{"contract_version":"14","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.914674","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067455","closing_balance":"9090.982129"}} -{"contract_version":"14","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000022","demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","reference_price":"105","spread_adjustment":"0.06","impact_adjustment":"0.02","final_price":"104.92"}} -{"contract_version":"14","engine_sequence":"27","event_id":"demo-event-000000000027","causation_ids":["demo-event-000000000026"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"104.92","notional":"756.9978","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.756998","quote_amount":"0.756998"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_amount":"-0.006998"}]}} -{"contract_version":"14","engine_sequence":"28","event_id":"demo-event-000000000028","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"29","event_id":"demo-event-000000000029","causation_ids":["demo-event-000000000028"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"49cac47b2abf617f1610d65a29984ab6cd848cd42c28b5d190fb34369365b18f","execution_model":"completed_bar_adverse_touch_v1","valuation":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v14/fixtures/demo.scenario.json b/contracts/v14/fixtures/demo.scenario.json deleted file mode 100644 index 55e7f7b..0000000 --- a/contracts/v14/fixtures/demo.scenario.json +++ /dev/null @@ -1,461 +0,0 @@ -{ - "contract_version": "14", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_adverse_touch_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "taker" - }, - { - "name": "maker_rebate", - "currency": "USD", - "kind": "notional_bps", - "value": -2, - "rounding": "nearest", - "applies_to": "maker" - } - ] - } - ], - "spread_model": { - "model": "fixed_half_spread_v1", - "half_spread_bps": 5 - }, - "impact_model": { - "model": "linear_participation_v1", - "coefficient_bps": 25, - "missing_volume_policy": "reject" - } - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "13" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-06T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-06T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-07T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-07T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v14/fixtures/demo.scenario.jsonl b/contracts/v14/fixtures/demo.scenario.jsonl deleted file mode 100644 index ae6e155..0000000 --- a/contracts/v14/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"14","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_adverse_touch_v1","configuration":{"version":"1","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}],"spread_model":{"model":"fixed_half_spread_v1","half_spread_bps":5},"impact_model":{"model":"linear_participation_v1","coefficient_bps":25,"missing_volume_policy":"reject"}}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"14","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"14","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"13"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"14","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"14","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"14","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v14/fixtures/fill-clipped.journal.jsonl b/contracts/v14/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 1a1c149..0000000 --- a/contracts/v14/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"14","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"77457107873a439fdb669f03d65eaf3a7843e1649a4a0036e68a958c7a48baad","execution_model":"completed_bar_v1"}} -{"contract_version":"14","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"14","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}} -{"contract_version":"14","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} -{"contract_version":"14","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"14","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.004081","fx_rate":"1","base_value":"550.004081","interest":"0.004081","base_interest":"0.004081","settled_amount":"550.004081","unsettled_amount":"0","base_settled_value":"550.004081","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.004081","settled_cash":"550.004081","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}} -{"contract_version":"14","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} -{"contract_version":"14","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"14","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"14","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"77457107873a439fdb669f03d65eaf3a7843e1649a4a0036e68a958c7a48baad","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v14/fixtures/fill-clipped.scenario.json b/contracts/v14/fixtures/fill-clipped.scenario.json deleted file mode 100644 index afee413..0000000 --- a/contracts/v14/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,271 +0,0 @@ -{ - "contract_version": "14", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v14/fixtures/quote-trade.journal.jsonl b/contracts/v14/fixtures/quote-trade.journal.jsonl deleted file mode 100644 index 0f729da..0000000 --- a/contracts/v14/fixtures/quote-trade.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"14","engine_sequence":"1","event_id":"quote-trade-event-000000000001","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"fc4ba762e5464546c4ec601df566c99e6c5995928a18e5b72434775ed20b62ac","execution_model":"quote_trade_v1"}} -{"contract_version":"14","engine_sequence":"2","event_id":"quote-trade-event-000000000002","causation_ids":["quote-trade-event-000000000001"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}}} -{"contract_version":"14","engine_sequence":"3","event_id":"quote-trade-event-000000000003","causation_ids":["quote-trade-event-000000000002"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"4","event_id":"quote-trade-event-000000000004","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]}} -{"contract_version":"14","engine_sequence":"5","event_id":"quote-trade-event-000000000005","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.01484"}} -{"contract_version":"14","engine_sequence":"6","event_id":"quote-trade-event-000000000006","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"quote-trade-event-000000000006","updated_event_id":"quote-trade-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"14","engine_sequence":"7","event_id":"quote-trade-event-000000000007","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000.01484","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.01484","unrealized_pnl":"0","equity":"2000.01484","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000.01484","fx_rate":"1","base_value":"2000.01484","interest":"0.01484","base_interest":"0.01484","settled_amount":"2000.01484","unsettled_amount":"0","base_settled_value":"2000.01484","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.01484","settled_cash":"2000.01484","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000.01484","maintenance_excess":"2000.01484","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"8","event_id":"quote-trade-event-000000000008","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00.000000Z","available_at":"2026-02-03T14:31:01.000000Z","received_at":"2026-02-03T14:31:02.000000Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00.000000Z","available_at":"2026-02-03T14:32:01.000000Z","received_at":"2026-02-03T14:32:02.000000Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00.000000Z","available_at":"2026-02-03T14:33:01.000000Z","received_at":"2026-02-03T14:33:02.000000Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00.000000Z","available_at":"2026-02-03T14:34:01.000000Z","received_at":"2026-02-03T14:34:02.000000Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}]}} -{"contract_version":"14","engine_sequence":"9","event_id":"quote-trade-event-000000000009","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000.01484","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.02968"}} -{"contract_version":"14","engine_sequence":"10","event_id":"quote-trade-event-000000000010","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000001","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"4","price":"99","notional":"396","fee":"10","executed_at":"2026-02-03T14:33:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"14","engine_sequence":"11","event_id":"quote-trade-event-000000000011","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000002","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"6","price":"100","notional":"600","fee":"10","executed_at":"2026-02-03T14:34:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"14","engine_sequence":"12","event_id":"quote-trade-event-000000000012","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"984.02968","fx_rate":"1","base_value":"984.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"984.02968","unsettled_amount":"0","base_settled_value":"984.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"984.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]}} -{"contract_version":"14","engine_sequence":"13","event_id":"quote-trade-event-000000000013","causation_ids":["quote-trade-event-000000000012"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"fc4ba762e5464546c4ec601df566c99e6c5995928a18e5b72434775ed20b62ac","execution_model":"quote_trade_v1","valuation":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"984.02968","fx_rate":"1","base_value":"984.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"984.02968","unsettled_amount":"0","base_settled_value":"984.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"984.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":1,"rejected":0,"cancelled":0}}} diff --git a/contracts/v14/fixtures/quote-trade.scenario.json b/contracts/v14/fixtures/quote-trade.scenario.json deleted file mode 100644 index 230f846..0000000 --- a/contracts/v14/fixtures/quote-trade.scenario.json +++ /dev/null @@ -1,317 +0,0 @@ -{ - "contract_version": "14", - "metadata": { - "producer": "trading-engine", - "purpose": "bounded quote and trade replay fixture" - }, - "run_id": "quote-trade", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "2000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "quote_trade_v1", - "configuration": { - "version": "1", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "limit", - "trigger_price": null, - "limit_price": "100", - "time_in_force": "gtc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [ - { - "type": "quote", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:31:00Z", - "available_at": "2026-02-03T14:31:01Z", - "received_at": "2026-02-03T14:31:02Z", - "ingest_sequence": "1", - "bid_price": "99", - "bid_quantity": "20", - "ask_price": "101", - "ask_quantity": "20" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:32:00Z", - "available_at": "2026-02-03T14:32:01Z", - "received_at": "2026-02-03T14:32:02Z", - "ingest_sequence": "2", - "price": "100", - "quantity": "5", - "aggressor_side": "unknown" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:33:00Z", - "available_at": "2026-02-03T14:33:01Z", - "received_at": "2026-02-03T14:33:02Z", - "ingest_sequence": "3", - "price": "99", - "quantity": "4", - "aggressor_side": "sell" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:34:00Z", - "available_at": "2026-02-03T14:34:01Z", - "received_at": "2026-02-03T14:34:02Z", - "ingest_sequence": "4", - "price": "100", - "quantity": "10", - "aggressor_side": "sell" - } - ] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v14/fixtures/quote-trade.scenario.jsonl b/contracts/v14/fixtures/quote-trade.scenario.jsonl deleted file mode 100644 index b399827..0000000 --- a/contracts/v14/fixtures/quote-trade.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"14","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine","purpose":"bounded quote and trade replay fixture"},"run_id":"quote-trade","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"clip-equity","symbol":"CLIP","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"clip-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["clip-equity"],"sessions":[{"session_date":"2026-02-02","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-02T14:30:00Z","closes_at":"2026-02-02T21:00:00Z"}]},{"session_date":"2026-02-03","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-03T14:30:00Z","closes_at":"2026-02-03T21:00:00Z"}]},{"session_date":"2026-02-04","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-02-04T14:30:00Z","closes_at":"2026-02-04T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000000","max_leverage":"1","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"clip-equity","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"quote_trade_v1","configuration":{"version":"1","participation_bps":10000,"fee_schedules":[{"schedule_id":"clip-fees-v1","instrument_id":"clip-equity","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"10","rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"clip-equity","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"14","scenario_sequence":"2","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00Z","end_at":"2026-02-02T21:00:00Z","available_at":"2026-02-02T21:00:01Z","received_at":"2026-02-02T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[]},"intents":[{"type":"submit_order","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null}]}} -{"contract_version":"14","scenario_sequence":"3","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00Z","end_at":"2026-02-03T21:00:00Z","available_at":"2026-02-03T21:00:01Z","received_at":"2026-02-03T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00Z","available_at":"2026-02-03T14:31:01Z","received_at":"2026-02-03T14:31:02Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00Z","available_at":"2026-02-03T14:32:01Z","received_at":"2026-02-03T14:32:02Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00Z","available_at":"2026-02-03T14:33:01Z","received_at":"2026-02-03T14:33:02Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00Z","available_at":"2026-02-03T14:34:01Z","received_at":"2026-02-03T14:34:02Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}]},"intents":[]}} -{"contract_version":"14","scenario_sequence":"4","record_type":"scenario_end","payload":{"slice_count":"2"}} diff --git a/contracts/v14/journal.schema.json b/contracts/v14/journal.schema.json deleted file mode 100644 index 399e678..0000000 --- a/contracts/v14/journal.schema.json +++ /dev/null @@ -1,2420 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v14/journal.schema.json", - "title": "Trading Engine v14 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { - "const": "14" - }, - "engine_sequence": { - "$ref": "#/$defs/sequence" - }, - "event_id": { - "$ref": "#/$defs/identifier" - }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/$defs/identifier" - } - }, - "run_id": { - "$ref": "#/$defs/identifier" - }, - "recorded_at": { - "$ref": "#/$defs/timestamp" - }, - "event_type": { - "enum": [ - "run_started", - "initial_state", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_triggered", - "order_cancelled", - "split_applied", - "cash_dividend_applied", - "distribution_applied", - "lifecycle_applied", - "order_adjusted", - "execution_price_selected", - "fill_applied", - "settlement_instruction_created", - "settlement_completed", - "settlement_failed", - "fill_clipped", - "borrow_fee_applied", - "borrow_charge_applied", - "borrow_recall_received", - "cash_interest_applied", - "margin_call", - "margin_restored", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { - "type": "object" - } - }, - "allOf": [ - { - "if": { "properties": { "event_type": { "const": "execution_price_selected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/executionPriceSelected" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_started" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runStarted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "initial_state" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/initialState" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "market_slice_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/marketSlice" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "target_portfolio_requested" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/targetPortfolio" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "order_accepted", - "order_rejected", - "order_triggered" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/order" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_cancelled" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderCancelled" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "split_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/splitApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_dividend_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/dividendApplied" - } - } - } - }, - { - "if": { "properties": { "event_type": { "const": "distribution_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/distributionApplied" } } } - }, - { - "if": { "properties": { "event_type": { "const": "lifecycle_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/lifecycleApplied" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_adjusted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderAdjusted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fill" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "settlement_instruction_created", - "settlement_completed", - "settlement_failed" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/settlementInstruction" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_clipped" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fillClipped" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_fee_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowFee" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_charge_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowCharge" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_recall_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowRecall" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_interest_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/cashInterest" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "margin_call", - "margin_restored", - "valuation" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/valuation" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "intent_rejected" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/intentRejected" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "metric_emitted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/metric" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_completed" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runCompleted" - } - } - } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "nonnegativeSequence": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1"] - } - } - }, - "initialState": { - "type": "object", - "additionalProperties": false, - "required": [ - "portfolio", - "valuation" - ], - "properties": { - "portfolio": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/initialPortfolio" - }, - "valuation": { - "$ref": "#/$defs/valuation" - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "open", - "high", - "low", - "close", - "volume" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "open": { - "$ref": "#/$defs/positiveDecimal" - }, - "high": { - "$ref": "#/$defs/positiveDecimal" - }, - "low": { - "$ref": "#/$defs/positiveDecimal" - }, - "close": { - "$ref": "#/$defs/positiveDecimal" - }, - "volume": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/unsignedDecimal" - } - ] - } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "rate" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "rate": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "numerator", - "denominator" - ], - "properties": { - "type": { - "const": "split" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "numerator": { - "$ref": "#/$defs/sequence" - }, - "denominator": { - "$ref": "#/$defs/sequence" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "amount_per_unit" - ], - "properties": { - "type": { - "const": "cash_dividend" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "amount_per_unit": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/fractionalPolicy" } - } - } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars", - "fx_rates", - "corporate_actions", - "borrow_observations", - "cash_rate_observations", - "settlement_failures", - "lifecycle_events", - "market_events" - ], - "properties": { - "slice_sequence": { - "$ref": "#/$defs/sequence" - }, - "start_at": { - "$ref": "#/$defs/timestamp" - }, - "end_at": { - "$ref": "#/$defs/timestamp" - }, - "available_at": { - "$ref": "#/$defs/timestamp" - }, - "received_at": { - "$ref": "#/$defs/timestamp" - }, - "bars": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/bar" - } - }, - "fx_rates": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/fxRate" - } - }, - "corporate_actions": { - "type": "array", - "items": { - "$ref": "#/$defs/corporateAction" - } - }, - "borrow_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/borrowObservation" - } - }, - "cash_rate_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/cashRateObservation" - } - }, - "settlement_failures": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/settlementFailure" - } - }, - "lifecycle_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/lifecycleEvent" - } - }, - "market_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/marketEvent" - } - } - } - }, - "settlementInstruction": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "fill_id", "instrument_id", "currency", "cash_movement", "position_movement", "trade_date", "due_date", "status", "settled_at", "failed_at", "failure_reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "fill_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "cash_movement": { "$ref": "#/$defs/signedDecimal" }, - "position_movement": { "$ref": "#/$defs/signedDecimal" }, - "trade_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "due_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "status": { "enum": ["pending", "settled", "failed"] }, - "settled_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failed_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failure_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" }] } - } - }, - "targetPortfolio": { - "type": "object", - "additionalProperties": false, - "required": [ - "basis", - "targets" - ], - "properties": { - "basis": { - "enum": [ - "weights", - "quantities" - ] - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "weight", - "quantity", - "reference_price" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "weight": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "reference_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - } - } - } - } - } - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "trigger_price", - "limit_price", - "time_in_force", - "venue_id", - "calendar_id", - "expires_at", - "origin", - "created_event_id", - "updated_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "triggered_at", - "triggered_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "order_kind": { - "enum": [ - "market", - "limit", - "stop", - "stop_limit" - ] - }, - "trigger_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "limit_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "time_in_force": { - "enum": [ - "gtc", - "ioc", - "fok", - "day", - "gtd" - ] - }, - "venue_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "calendar_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "expires_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "origin": { - "enum": [ - "direct", - "target_rebalance", - "margin_liquidation", - "borrow_recall", - "instrument_halt", - "instrument_terminal" - ] - }, - "created_event_id": { - "$ref": "#/$defs/identifier" - }, - "updated_event_id": { - "$ref": "#/$defs/identifier" - }, - "created_sequence": { - "$ref": "#/$defs/sequence" - }, - "created_at": { - "$ref": "#/$defs/timestamp" - }, - "eligible_after_slice_sequence": { - "$ref": "#/$defs/nonnegativeSequence" - }, - "triggered_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "triggered_slice_sequence": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/sequence" - } - ] - }, - "filled_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "filled_notional": { - "$ref": "#/$defs/unsignedDecimal" - }, - "status": { - "enum": [ - "working", - "partially_filled", - "filled", - "cancelled", - "rejected" - ] - }, - "rejection_reason": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "minLength": 1 - } - ] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "reason" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "reason": { - "enum": [ - "strategy_requested", - "target_replaced", - "market_ioc", - "immediate_or_cancel", - "fill_or_kill", - "day_expired", - "gtd_expired", - "margin_call", - "borrow_recall" - ] - } - } - }, - "splitApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "previous_quantity", - "adjusted_quantity" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "previous_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "adjusted_quantity": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "dividendApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "quantity", - "cash_amount" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "distributionApplied": { - "type": "object", - "additionalProperties": false, - "required": ["action", "source_quantity", "destination_quantity", "fractional_quantity", "allocated_basis", "fractional_basis", "cash_in_lieu"], - "properties": { - "action": { "$ref": "#/$defs/corporateAction" }, - "source_quantity": { "$ref": "#/$defs/signedDecimal" }, - "destination_quantity": { "$ref": "#/$defs/signedDecimal" }, - "fractional_quantity": { "$ref": "#/$defs/signedDecimal" }, - "allocated_basis": { "$ref": "#/$defs/signedDecimal" }, - "fractional_basis": { "$ref": "#/$defs/signedDecimal" }, - "cash_in_lieu": { "$ref": "#/$defs/signedDecimal" } - } - }, - "lifecycleApplied": { - "type": "object", - "additionalProperties": false, - "required": ["lifecycle_event", "listing", "liquidated_quantity", "cash_amount"], - "properties": { - "lifecycle_event": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/lifecycleEvent" }, - "listing": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "status", "provider_mappings"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "status": { "enum": ["tradable", "halted", "expired", "delisted"] }, - "provider_mappings": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["provider", "provider_instrument_id"], - "properties": { - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - } - } - } - }, - "liquidated_quantity": { "$ref": "#/$defs/signedDecimal" }, - "cash_amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "orderAdjusted": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "action_id" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "action_id": { - "$ref": "#/$defs/identifier" - } - } - }, - "executionPriceSelected": { - "type": "object", - "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "reference_price", "spread_adjustment", "impact_adjustment", "final_price"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "reference_price": { "$ref": "#/$defs/positiveDecimal" }, - "spread_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "impact_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "final_price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "quote_currency", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence", - "fee_components" - ], - "properties": { - "fill_id": { - "$ref": "#/$defs/identifier" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - }, - "notional": { - "$ref": "#/$defs/positiveDecimal" - }, - "fee": { - "$ref": "#/$defs/signedDecimal" - }, - "fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/calculatedFeeComponent" - } - }, - "executed_at": { - "$ref": "#/$defs/timestamp" - }, - "slice_sequence": { - "$ref": "#/$defs/sequence" - } - } - }, - "calculatedFeeComponent": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "feeComponentAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_currency", - "quote_amount", - "base_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "quantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "moneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "ratioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "basisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentQuantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "currencyMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "unit", "value"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "money" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "settlementPositionThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "unit", "value"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "quantity" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrumentBasisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentShortingThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "value": { - "const": false - } - } - }, - "groupMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "groupRatioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "fillClipReason": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_order_quantity" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_long_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_short_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/moneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_leverage" - }, - "threshold": { - "$ref": "#/$defs/ratioThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "initial_margin" - }, - "threshold": { - "$ref": "#/$defs/basisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_long_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_cash_buying_power" }, - "threshold": { "$ref": "#/$defs/currencyMoneyThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_position_availability" }, - "threshold": { "$ref": "#/$defs/settlementPositionThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_short_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_notional_exposure" - }, - "threshold": { - "$ref": "#/$defs/instrumentMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_shorting_disabled" - }, - "threshold": { - "$ref": "#/$defs/instrumentShortingThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_borrow_availability" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_initial_margin" - }, - "threshold": { - "$ref": "#/$defs/instrumentBasisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_long_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_short_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_absolute_net_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_concentration" - }, - "threshold": { - "$ref": "#/$defs/groupRatioThreshold" - } - } - } - ] - }, - "fillClipped": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason", - "order_id", - "instrument_id", - "proposed_quantity", - "permitted_quantity", - "price" - ], - "properties": { - "reason": { - "$ref": "#/$defs/fillClipReason" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "proposed_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "permitted_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowFee": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "short_quantity", - "reference_price", - "borrow_bps", - "period_start", - "period_end", - "fee" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "borrow_bps": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "fee": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowCharge": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "quote_currency", - "short_quantity", - "reference_price", - "day_count", - "compounding", - "period_start", - "period_end", - "amount" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/borrowObservation" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "borrowRecall": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "short_quantity", - "close_out_quantity" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/borrowObservation" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "close_out_quantity": { - "$ref": "#/$defs/unsignedDecimal" - } - } - }, - "cashInterest": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "opening_balance", - "applied_rate_bps", - "day_count", - "compounding", - "period_start", - "period_end", - "amount", - "closing_balance" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/cashRateObservation" - }, - "opening_balance": { - "$ref": "#/$defs/signedDecimal" - }, - "applied_rate_bps": { - "type": "integer", - "minimum": -1000000, - "maximum": 1000000 - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "closing_balance": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "cashAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "amount", - "fx_rate", - "base_value", - "interest", - "base_interest", - "settled_amount", - "unsettled_amount", - "base_settled_value", - "base_unsettled_value" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "base_value": { - "$ref": "#/$defs/signedDecimal" - }, - "interest": { - "$ref": "#/$defs/signedDecimal" - }, - "base_interest": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_settled_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unsettled_value": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "quantity", - "settled_quantity", - "unsettled_quantity", - "mark", - "fx_rate", - "market_value", - "base_market_value", - "cost_basis", - "base_cost_basis", - "realized_pnl", - "base_realized_pnl", - "unrealized_pnl", - "base_unrealized_pnl", - "dividend_pnl", - "base_dividend_pnl", - "execution_fees", - "base_execution_fees", - "borrow_fees", - "base_borrow_fees", - "total_fees", - "base_total_fees", - "execution_fee_components" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "mark": { - "$ref": "#/$defs/positiveDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "base_cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - } - } - }, - "margin": { - "type": "object", - "additionalProperties": false, - "required": [ - "initial_requirement", - "maintenance_requirement", - "initial_excess", - "maintenance_excess", - "margin_call" - ], - "properties": { - "initial_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "maintenance_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "initial_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "maintenance_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "margin_call": { - "type": "boolean" - } - } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "gross_exposure", - "net_exposure", - "long_exposure", - "short_exposure", - "concentration" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "net_exposure": { - "$ref": "#/$defs/signedDecimal" - }, - "long_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "concentration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "base_currency", - "cash", - "settled_cash", - "unsettled_cash", - "net_market_value", - "long_market_value", - "short_market_value", - "gross_exposure", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "dividend_pnl", - "execution_fees", - "borrow_fees", - "cash_interest", - "total_fees", - "cash_balances", - "positions", - "margin", - "group_exposures", - "execution_fee_components" - ], - "properties": { - "base_currency": { - "$ref": "#/$defs/identifier" - }, - "cash": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "net_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "long_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "equity": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/cashAttribution" - } - }, - "positions": { - "type": "array", - "items": { - "$ref": "#/$defs/positionAttribution" - } - }, - "margin": { - "$ref": "#/$defs/margin" - }, - "group_exposures": { - "type": "array", - "items": { - "$ref": "#/$defs/groupExposure" - } - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - }, - "cash_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "minLength": 1 - } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1"] - }, - "valuation": { - "$ref": "#/$defs/valuation" - }, - "order_counts": { - "type": "object", - "additionalProperties": false, - "required": [ - "total", - "active", - "filled", - "rejected", - "cancelled" - ], - "properties": { - "total": { - "type": "integer", - "minimum": 0 - }, - "active": { - "type": "integer", - "minimum": 0 - }, - "filled": { - "type": "integer", - "minimum": 0 - }, - "rejected": { - "type": "integer", - "minimum": 0 - }, - "cancelled": { - "type": "integer", - "minimum": 0 - } - } - } - } - } - } -} diff --git a/contracts/v14/scenario-stream.schema.json b/contracts/v14/scenario-stream.schema.json deleted file mode 100644 index 6093644..0000000 --- a/contracts/v14/scenario-stream.schema.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v14/scenario-stream.schema.json", - "title": "Trading Engine v14 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "14" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "14" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "14" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v14/scenario.schema.json b/contracts/v14/scenario.schema.json deleted file mode 100644 index f4117b5..0000000 --- a/contracts/v14/scenario.schema.json +++ /dev/null @@ -1,770 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v14/scenario.schema.json", - "title": "Trading Engine v14 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "14" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "financing": { "$ref": "#/$defs/financing" }, - "settlement": { "$ref": "#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "settlement": { - "type": "object", - "additionalProperties": false, - "required": ["cash_buying_power", "position_availability", "calendars", "rules"], - "properties": { - "cash_buying_power": { "enum": ["total_cash", "settled_cash"] }, - "position_availability": { "enum": ["total_positions", "settled_positions"] }, - "calendars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementCalendar" } }, - "rules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementRule" } } - } - }, - "settlementCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "version", "business_dates"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "version": { "const": "1" }, - "business_dates": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } - } - }, - "settlementRule": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "calendar_id", "lag_business_days"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "calendar_id": { "$ref": "#/$defs/identifier" }, - "lag_business_days": { "type": "integer", "minimum": 0, "maximum": 30 } - } - }, - "settlementFailure": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - }, - "financing": { - "type": "object", - "additionalProperties": false, - "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], - "properties": { - "day_count": { "enum": ["actual_365", "actual_360"] }, - "compounding": { "enum": ["simple", "daily"] }, - "borrow_missing_data": { "enum": ["reject", "zero"] }, - "cash_missing_data": { "enum": ["reject", "zero"] }, - "locate_policy": { "enum": ["reject_order", "clip_fill"] }, - "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } - } - }, - "borrowObservation": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, - "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "recalled": { "type": "boolean" } - } - }, - "cashRateObservation": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } - } - }, - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "enum": ["completed_bar_next_open_v1", "completed_bar_adverse_touch_v1"] }, - "configuration": { "$ref": "#/$defs/conservativeBarConfiguration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "quote_trade_v1" }, - "configuration": { "$ref": "#/$defs/quoteTradeConfiguration" } - } - } - ] - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "conservativeBarConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules", "spread_model", "impact_model"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, - "spread_model": { "$ref": "#/$defs/fixedSpreadModel" }, - "impact_model": { "$ref": "#/$defs/linearImpactModel" } - } - }, - "quoteTradeConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "fixedSpreadModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "half_spread_bps"], - "properties": { - "model": { "const": "fixed_half_spread_v1" }, - "half_spread_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "linearImpactModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "coefficient_bps", "missing_volume_policy"], - "properties": { - "model": { "const": "linear_participation_v1" }, - "coefficient_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "missing_volume_policy": { "enum": ["reject", "zero_impact"] } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "market_events", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations", "settlement_failures", "lifecycle_events"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "market_events": { "type": "array", "items": { "$ref": "#/$defs/marketEvent" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, - "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, - "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } }, - "settlement_failures": { "type": "array", "items": { "$ref": "#/$defs/settlementFailure" } }, - "lifecycle_events": { "type": "array", "items": { "$ref": "#/$defs/lifecycleEvent" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "marketEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "bid_price", "bid_quantity", "ask_price", "ask_quantity"], - "properties": { - "type": { "const": "quote" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "bid_price": { "$ref": "#/$defs/positiveDecimal" }, - "bid_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "ask_price": { "$ref": "#/$defs/positiveDecimal" }, - "ask_quantity": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "price", "quantity", "aggressor_side"], - "properties": { - "type": { "const": "trade" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "aggressor_side": { "enum": ["buy", "sell", "unknown"] } - } - } - ] - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "#/$defs/fractionalPolicy" } - } - } - ] - }, - "fractionalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "reject" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_in_lieu" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "terminalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "hold" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_out" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "lifecycleEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "reason"], - "properties": { - "type": { "const": "halt" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1 } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id"], - "properties": { - "type": { "const": "resume" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "symbol", "provider", "provider_instrument_id"], - "properties": { - "type": { "const": "identifier_change" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy"], - "properties": { - "type": { "const": "expiration" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy", "reason"], - "properties": { - "type": { "const": "delisting" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - } - } -} diff --git a/contracts/v15/README.md b/contracts/v15/README.md deleted file mode 100644 index a1917b8..0000000 --- a/contracts/v15/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# Trading Engine contract v15 - -This directory is the authoritative v15 process and file contract shared by Trading Engine and its -clients. Versions 14 through 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v15 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v15 scenario, stream record, and journal record carries `"contract_version": "15"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v10 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. - -Version 10 adds a required `financing` policy and effective-time observations on every market -slice. Borrow observations provide per-instrument locate availability, signed annual rates, and -recall state. Cash observations provide separate annual credit and debit rates per currency. -Policies select Actual/365 or Actual/360 day count, simple or daily compounding, missing-data -handling, locate rejection or fill clipping, and recall rejection or deterministic close-out. - -Borrow availability is enforced when a fill would create or increase a short. Recalls cancel -active sells and may submit priority IOC covers until the position is flat. Borrow charges and cash -interest use the exact slice interval, update native ledgers deterministically, and emit dedicated -journal records. Valuations report cash interest separately and include it in aggregate realized -P&L. Version 9 and earlier retain their frozen fixed-borrow behavior and wire shapes. - -Version 12 separates trade-date economic accounting from settlement-date availability. A required -settlement policy selects total or settled cash buying power and total or settled position -availability. Versioned calendars enumerate canonical business dates, and each instrument has an -explicit business-day lag. Every fill creates a deterministic settlement instruction containing -its cash and position movements, trade date, and due date. A due instruction either settles on the -first eligible slice or records a named failure supplied by that slice. - -Valuations and strategy contexts report settled and unsettled cash and quantities without changing -economic equity. Journals include instruction-created, completed, and failed events. Scenario v10 -and strategy protocol v8 retain their frozen immediate-settlement wire behavior. - -Version 12 adds exact stock-dividend, rights, and spin-off distributions. Each distribution names -its destination instrument, exact entitlement ratio, basis allocation in basis points, and either -rejects fractional entitlements or converts them to cash at an explicit price and currency. -Stock dividends adjust persistent targets and eligible working orders; every distribution journals -delivered quantity, fractional quantity, allocated basis, fractional basis, and cash in lieu. - -Lifecycle events keep stable instrument identity separate from mutable symbol and provider -mappings. Halt and resume transitions control tradability. Expiration and delisting are terminal, -cancel active orders, clear target exposure, and require an explicit hold or cash-out policy. -Cash-out specifies its terminal price and currency. Every transition journals the source event, -resulting listing state, provider provenance, liquidated quantity, and cash attribution. - -Version 13 adds `completed_bar_next_open_v1` and `completed_bar_adverse_touch_v1` without changing -the frozen `completed_bar_v1` semantics. Next-open limits require a marketable later open; -adverse-touch limits require a one-tick trade-through before a maker fill is eligible. Both models -declare fixed half-spread and linear participation-impact catalogs, including an explicit policy -for missing bar volume. Price costs round away from the reference price to instrument ticks and -cannot violate a limit. An `execution_price_selected` audit record attributes the reference price, -spread adjustment, impact adjustment, and final executable price before each fill. - -Version 14 adds `quote_trade_v1` and causally ordered `market_events`. Quotes expose bid/ask price -and displayed size. Trades expose price, size, and buy, sell, or unknown aggressor side. Each event -records economic, availability, and receipt timestamps plus a positive ingest sequence. Replay -orders events by availability, receipt, and ingest sequence. Marketable orders consume only -displayed quote liquidity; passive orders require appropriately aggressed trade evidence, and an -unknown aggressor never fills them. Event capacity is shared deterministically across order -priority and fills retain the event's economic timestamp. Completed bars remain the valuation -boundary. The `quote-trade` batch, stream, and journal fixtures demonstrate equivalent replay. - -Version 15 adds `order_book_v1` and bounded level-two `order_book_events`. Every per-instrument -slice bundle starts with a complete snapshot and continues with contiguous absolute set, delete, -and aggressor-classified trade updates. Snapshots and updates reject crossed books, missing -deletes, sequence gaps, tick or lot misalignment, and depth beyond the configured limit; locked -books are valid. State is rebuilt from each slice snapshot, so replay never depends on hidden data -from a prior slice. - -Marketable orders walk observable opposite-side depth in price priority. Passive limit orders join -behind displayed same-price quantity and earlier engine orders. Reductions decrease quantity ahead, -adds join behind, and only appropriately aggressed trades consume the queue and fill the order. -Partial fills and cancellations therefore remain deterministic. Book liquidity is independent of -bar and quote/trade execution semantics, while completed bars remain the valuation boundary. The -`order-book` batch, stream, and journal fixtures demonstrate cancellation, queue depletion, maker -fills, bounded state, and batch/stream equivalence. diff --git a/contracts/v15/dune b/contracts/v15/dune deleted file mode 100644 index d1742ac..0000000 --- a/contracts/v15/dune +++ /dev/null @@ -1,36 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v15/journal.schema.json) - (scenario-stream.schema.json as contracts/v15/scenario-stream.schema.json) - (scenario.schema.json as contracts/v15/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v15/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v15/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl - as - contracts/v15/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v15/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v15/fixtures/fill-clipped.scenario.json) - (fixtures/quote-trade.journal.jsonl - as - contracts/v15/fixtures/quote-trade.journal.jsonl) - (fixtures/quote-trade.scenario.json - as - contracts/v15/fixtures/quote-trade.scenario.json) - (fixtures/quote-trade.scenario.jsonl - as - contracts/v15/fixtures/quote-trade.scenario.jsonl) - (fixtures/order-book.journal.jsonl - as - contracts/v15/fixtures/order-book.journal.jsonl) - (fixtures/order-book.scenario.json - as - contracts/v15/fixtures/order-book.scenario.json) - (fixtures/order-book.scenario.jsonl - as - contracts/v15/fixtures/order-book.scenario.jsonl))) diff --git a/contracts/v15/fixtures/demo.journal.jsonl b/contracts/v15/fixtures/demo.journal.jsonl deleted file mode 100644 index c14e704..0000000 --- a/contracts/v15/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,29 +0,0 @@ -{"contract_version":"15","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"068f28c64905f5847ed3ecfac808940c3f1ba43e0d198d96f11929ba234703bc","execution_model":"completed_bar_adverse_touch_v1"}} -{"contract_version":"15","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"15","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} -{"contract_version":"15","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"15","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"15","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"15","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000.074201","fx_rate":"1","base_value":"10000.074201","interest":"0.074201","base_interest":"0.074201","settled_amount":"10000.074201","unsettled_amount":"0","base_settled_value":"10000.074201","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.074201","settled_cash":"10000.074201","unsettled_cash":"0","margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"13"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} -{"contract_version":"15","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","reference_price":"103","spread_adjustment":"0.06","impact_adjustment":"0.13","final_price":"103.19"}} -{"contract_version":"15","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6.5","price":"103.19","notional":"670.735","fee":"0.920735","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_amount":"0.670735"}]}} -{"contract_version":"15","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6.5","filled_notional":"670.735","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"15","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"15","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9328.492667","net_market_value":"802.5","long_market_value":"802.5","short_market_value":"0","gross_exposure":"802.5","cost_basis":"761.655735","realized_pnl":"5.148402","unrealized_pnl":"40.844265","equity":"10130.992667","dividend_pnl":"1","execution_fees":"1.420735","borrow_fees":"0.25","total_fees":"1.670735","cash_balances":[{"currency":"USD","amount":"9328.492667","fx_rate":"1","base_value":"9328.492667","interest":"0.148402","base_interest":"0.148402","settled_amount":"9328.492667","unsettled_amount":"0","base_settled_value":"9328.492667","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7.5","mark":"107","fx_rate":"1","market_value":"802.5","base_market_value":"802.5","cost_basis":"761.655735","base_cost_basis":"761.655735","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.844265","base_unrealized_pnl":"40.844265","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.420735","base_execution_fees":"1.420735","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.670735","base_total_fees":"1.670735","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"settled_quantity":"7.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"cash_interest":"0.148402","settled_cash":"9328.492667","unsettled_cash":"0","margin":{"initial_requirement":"401.25","maintenance_requirement":"200.625","initial_excess":"9729.742667","maintenance_excess":"9930.367667","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9328.492667","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.069218","closing_balance":"9328.561885"}} -{"contract_version":"15","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","reference_price":"107","spread_adjustment":"0.06","impact_adjustment":"0.01","final_price":"107.07"}} -{"contract_version":"15","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.215","price":"107.07","notional":"237.16005","fee":"0.487161","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.237161","quote_amount":"0.237161"}]}} -{"contract_version":"15","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"15","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000017","demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000022","updated_event_id":"demo-event-000000000022","created_sequence":"22","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"15","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.914674","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.302946","realized_pnl":"5.21762","unrealized_pnl":"20.772054","equity":"10110.989674","dividend_pnl":"1","execution_fees":"1.907896","borrow_fees":"0.25","total_fees":"2.157896","cash_balances":[{"currency":"USD","amount":"9090.914674","fx_rate":"1","base_value":"9090.914674","interest":"0.21762","base_interest":"0.21762","settled_amount":"9090.914674","unsettled_amount":"0","base_settled_value":"9090.914674","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.302946","base_cost_basis":"999.302946","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.772054","base_unrealized_pnl":"20.772054","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.907896","base_execution_fees":"1.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.157896","base_total_fees":"2.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"settled_quantity":"9.715","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"cash_interest":"0.21762","settled_cash":"9090.914674","unsettled_cash":"0","margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.952174","maintenance_excess":"9855.970924","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.914674","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067455","closing_balance":"9090.982129"}} -{"contract_version":"15","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000022","demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","reference_price":"105","spread_adjustment":"0.06","impact_adjustment":"0.02","final_price":"104.92"}} -{"contract_version":"15","engine_sequence":"27","event_id":"demo-event-000000000027","causation_ids":["demo-event-000000000026"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"104.92","notional":"756.9978","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.756998","quote_amount":"0.756998"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_amount":"-0.006998"}]}} -{"contract_version":"15","engine_sequence":"28","event_id":"demo-event-000000000028","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"29","event_id":"demo-event-000000000029","causation_ids":["demo-event-000000000028"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"068f28c64905f5847ed3ecfac808940c3f1ba43e0d198d96f11929ba234703bc","execution_model":"completed_bar_adverse_touch_v1","valuation":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v15/fixtures/demo.scenario.json b/contracts/v15/fixtures/demo.scenario.json deleted file mode 100644 index b2f17e1..0000000 --- a/contracts/v15/fixtures/demo.scenario.json +++ /dev/null @@ -1,465 +0,0 @@ -{ - "contract_version": "15", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_adverse_touch_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "taker" - }, - { - "name": "maker_rebate", - "currency": "USD", - "kind": "notional_bps", - "value": -2, - "rounding": "nearest", - "applies_to": "maker" - } - ] - } - ], - "spread_model": { - "model": "fixed_half_spread_v1", - "half_spread_bps": 5 - }, - "impact_model": { - "model": "linear_participation_v1", - "coefficient_bps": 25, - "missing_volume_policy": "reject" - } - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "13" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-06T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-06T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-07T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-07T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v15/fixtures/demo.scenario.jsonl b/contracts/v15/fixtures/demo.scenario.jsonl deleted file mode 100644 index 251ded8..0000000 --- a/contracts/v15/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"15","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_adverse_touch_v1","configuration":{"version":"1","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}],"spread_model":{"model":"fixed_half_spread_v1","half_spread_bps":5},"impact_model":{"model":"linear_participation_v1","coefficient_bps":25,"missing_volume_policy":"reject"}}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"15","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"15","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"13"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"15","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"15","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"15","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v15/fixtures/fill-clipped.journal.jsonl b/contracts/v15/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 133c789..0000000 --- a/contracts/v15/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"15","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"02138360b4f18f05c851efd2c16fecc1adb49ae668f6f7e72c3d903bea561002","execution_model":"completed_bar_v1"}} -{"contract_version":"15","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"15","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} -{"contract_version":"15","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"15","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.004081","fx_rate":"1","base_value":"550.004081","interest":"0.004081","base_interest":"0.004081","settled_amount":"550.004081","unsettled_amount":"0","base_settled_value":"550.004081","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.004081","settled_cash":"550.004081","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} -{"contract_version":"15","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"15","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"15","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"02138360b4f18f05c851efd2c16fecc1adb49ae668f6f7e72c3d903bea561002","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v15/fixtures/order-book.journal.jsonl b/contracts/v15/fixtures/order-book.journal.jsonl deleted file mode 100644 index 7c9fded..0000000 --- a/contracts/v15/fixtures/order-book.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"15","engine_sequence":"1","event_id":"order-book-event-000000000001","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"f330f2a12a85e8b24bd3bc1bbb7fdf9a08654ed0d7dd8f0a3c712e031ef80128","execution_model":"order_book_v1"}} -{"contract_version":"15","engine_sequence":"2","event_id":"order-book-event-000000000002","causation_ids":["order-book-event-000000000001"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}}} -{"contract_version":"15","engine_sequence":"3","event_id":"order-book-event-000000000003","causation_ids":["order-book-event-000000000002"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"4","event_id":"order-book-event-000000000004","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-02T14:31:00.000000Z","available_at":"2026-02-02T14:31:01.000000Z","received_at":"2026-02-02T14:31:02.000000Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"49","quantity":"20"}],"asks":[{"price":"51","quantity":"20"}]}]}} -{"contract_version":"15","engine_sequence":"5","event_id":"order-book-event-000000000005","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.01484"}} -{"contract_version":"15","engine_sequence":"6","event_id":"order-book-event-000000000006","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"order-book-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"order-book-event-000000000006","updated_event_id":"order-book-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"15","engine_sequence":"7","event_id":"order-book-event-000000000007","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000.01484","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.01484","unrealized_pnl":"0","equity":"2000.01484","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000.01484","fx_rate":"1","base_value":"2000.01484","interest":"0.01484","base_interest":"0.01484","settled_amount":"2000.01484","unsettled_amount":"0","base_settled_value":"2000.01484","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.01484","settled_cash":"2000.01484","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000.01484","maintenance_excess":"2000.01484","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"8","event_id":"order-book-event-000000000008","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00.000000Z","available_at":"2026-02-03T14:31:01.000000Z","received_at":"2026-02-03T14:31:02.000000Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"100","quantity":"5"}],"asks":[{"price":"101","quantity":"20"}]},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00.000000Z","available_at":"2026-02-03T14:32:01.000000Z","received_at":"2026-02-03T14:32:02.000000Z","ingest_sequence":"2","book_sequence":"2","side":"bid","price":"100","quantity":"3"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00.000000Z","available_at":"2026-02-03T14:33:01.000000Z","received_at":"2026-02-03T14:33:02.000000Z","ingest_sequence":"3","book_sequence":"3","price":"100","quantity":"3","aggressor_side":"sell"},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00.000000Z","available_at":"2026-02-03T14:34:01.000000Z","received_at":"2026-02-03T14:34:02.000000Z","ingest_sequence":"4","book_sequence":"4","side":"bid","price":"100","quantity":"10"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:35:00.000000Z","available_at":"2026-02-03T14:35:01.000000Z","received_at":"2026-02-03T14:35:02.000000Z","ingest_sequence":"5","book_sequence":"5","price":"100","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:36:00.000000Z","available_at":"2026-02-03T14:36:01.000000Z","received_at":"2026-02-03T14:36:02.000000Z","ingest_sequence":"6","book_sequence":"6","price":"100","quantity":"6","aggressor_side":"sell"}]}} -{"contract_version":"15","engine_sequence":"9","event_id":"order-book-event-000000000009","causation_ids":["order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000.01484","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.02968"}} -{"contract_version":"15","engine_sequence":"10","event_id":"order-book-event-000000000010","causation_ids":["order-book-event-000000000006","order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"order-book-fill-000000000001","order_id":"order-book-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"4","price":"100","notional":"400","fee":"10","executed_at":"2026-02-03T14:35:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"15","engine_sequence":"11","event_id":"order-book-event-000000000011","causation_ids":["order-book-event-000000000006","order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"order-book-fill-000000000002","order_id":"order-book-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"6","price":"100","notional":"600","fee":"10","executed_at":"2026-02-03T14:36:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"15","engine_sequence":"12","event_id":"order-book-event-000000000012","causation_ids":["order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"980.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1020","realized_pnl":"0.02968","unrealized_pnl":"-20","equity":"1980.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"980.02968","fx_rate":"1","base_value":"980.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"980.02968","unsettled_amount":"0","base_settled_value":"980.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1020","base_cost_basis":"1020","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-20","base_unrealized_pnl":"-20","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"980.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1480.02968","maintenance_excess":"1730.02968","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"13","event_id":"order-book-event-000000000013","causation_ids":["order-book-event-000000000012"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"f330f2a12a85e8b24bd3bc1bbb7fdf9a08654ed0d7dd8f0a3c712e031ef80128","execution_model":"order_book_v1","valuation":{"base_currency":"USD","cash":"980.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1020","realized_pnl":"0.02968","unrealized_pnl":"-20","equity":"1980.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"980.02968","fx_rate":"1","base_value":"980.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"980.02968","unsettled_amount":"0","base_settled_value":"980.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1020","base_cost_basis":"1020","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-20","base_unrealized_pnl":"-20","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"980.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1480.02968","maintenance_excess":"1730.02968","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":1,"rejected":0,"cancelled":0}}} diff --git a/contracts/v15/fixtures/order-book.scenario.json b/contracts/v15/fixtures/order-book.scenario.json deleted file mode 100644 index 7e27ab1..0000000 --- a/contracts/v15/fixtures/order-book.scenario.json +++ /dev/null @@ -1,378 +0,0 @@ -{ - "contract_version": "15", - "metadata": { - "producer": "trading-engine", - "purpose": "bounded order-book replay conformance fixture" - }, - "run_id": "order-book", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "2000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "order_book_v1", - "configuration": { - "version": "1", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ], - "max_depth_levels": 10 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "limit", - "trigger_price": null, - "limit_price": "100", - "time_in_force": "gtc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [ - { - "type": "snapshot", - "instrument_id": "clip-equity", - "event_at": "2026-02-02T14:31:00Z", - "available_at": "2026-02-02T14:31:01Z", - "received_at": "2026-02-02T14:31:02Z", - "ingest_sequence": "1", - "book_sequence": "1", - "bids": [ - { - "price": "49", - "quantity": "20" - } - ], - "asks": [ - { - "price": "51", - "quantity": "20" - } - ] - } - ] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [ - { - "type": "snapshot", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:31:00Z", - "available_at": "2026-02-03T14:31:01Z", - "received_at": "2026-02-03T14:31:02Z", - "ingest_sequence": "1", - "book_sequence": "1", - "bids": [ - { - "price": "100", - "quantity": "5" - } - ], - "asks": [ - { - "price": "101", - "quantity": "20" - } - ] - }, - { - "type": "set", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:32:00Z", - "available_at": "2026-02-03T14:32:01Z", - "received_at": "2026-02-03T14:32:02Z", - "ingest_sequence": "2", - "book_sequence": "2", - "side": "bid", - "price": "100", - "quantity": "3" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:33:00Z", - "available_at": "2026-02-03T14:33:01Z", - "received_at": "2026-02-03T14:33:02Z", - "ingest_sequence": "3", - "book_sequence": "3", - "price": "100", - "quantity": "3", - "aggressor_side": "sell" - }, - { - "type": "set", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:34:00Z", - "available_at": "2026-02-03T14:34:01Z", - "received_at": "2026-02-03T14:34:02Z", - "ingest_sequence": "4", - "book_sequence": "4", - "side": "bid", - "price": "100", - "quantity": "10" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:35:00Z", - "available_at": "2026-02-03T14:35:01Z", - "received_at": "2026-02-03T14:35:02Z", - "ingest_sequence": "5", - "book_sequence": "5", - "price": "100", - "quantity": "4", - "aggressor_side": "sell" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:36:00Z", - "available_at": "2026-02-03T14:36:01Z", - "received_at": "2026-02-03T14:36:02Z", - "ingest_sequence": "6", - "book_sequence": "6", - "price": "100", - "quantity": "6", - "aggressor_side": "sell" - } - ] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v15/fixtures/order-book.scenario.jsonl b/contracts/v15/fixtures/order-book.scenario.jsonl deleted file mode 100644 index ef9c90e..0000000 --- a/contracts/v15/fixtures/order-book.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"15","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine","purpose":"bounded order-book replay conformance fixture"},"run_id":"order-book","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"clip-equity","symbol":"CLIP","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"clip-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["clip-equity"],"sessions":[{"session_date":"2026-02-02","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-02T14:30:00Z","closes_at":"2026-02-02T21:00:00Z"}]},{"session_date":"2026-02-03","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-03T14:30:00Z","closes_at":"2026-02-03T21:00:00Z"}]},{"session_date":"2026-02-04","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-02-04T14:30:00Z","closes_at":"2026-02-04T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000000","max_leverage":"1","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"clip-equity","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"order_book_v1","configuration":{"version":"1","participation_bps":10000,"fee_schedules":[{"schedule_id":"clip-fees-v1","instrument_id":"clip-equity","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"10","rounding":"up","applies_to":"any"}]}],"max_depth_levels":10}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"clip-equity","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"15","scenario_sequence":"2","record_type":"market_slice","payload":{"intents":[{"type":"submit_order","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null}],"market_slice":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00Z","end_at":"2026-02-02T21:00:00Z","available_at":"2026-02-02T21:00:01Z","received_at":"2026-02-02T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-02T14:31:00Z","available_at":"2026-02-02T14:31:01Z","received_at":"2026-02-02T14:31:02Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"49","quantity":"20"}],"asks":[{"price":"51","quantity":"20"}]}]}}} -{"contract_version":"15","scenario_sequence":"3","record_type":"market_slice","payload":{"intents":[],"market_slice":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00Z","end_at":"2026-02-03T21:00:00Z","available_at":"2026-02-03T21:00:01Z","received_at":"2026-02-03T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00Z","available_at":"2026-02-03T14:31:01Z","received_at":"2026-02-03T14:31:02Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"100","quantity":"5"}],"asks":[{"price":"101","quantity":"20"}]},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00Z","available_at":"2026-02-03T14:32:01Z","received_at":"2026-02-03T14:32:02Z","ingest_sequence":"2","book_sequence":"2","side":"bid","price":"100","quantity":"3"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00Z","available_at":"2026-02-03T14:33:01Z","received_at":"2026-02-03T14:33:02Z","ingest_sequence":"3","book_sequence":"3","price":"100","quantity":"3","aggressor_side":"sell"},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00Z","available_at":"2026-02-03T14:34:01Z","received_at":"2026-02-03T14:34:02Z","ingest_sequence":"4","book_sequence":"4","side":"bid","price":"100","quantity":"10"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:35:00Z","available_at":"2026-02-03T14:35:01Z","received_at":"2026-02-03T14:35:02Z","ingest_sequence":"5","book_sequence":"5","price":"100","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:36:00Z","available_at":"2026-02-03T14:36:01Z","received_at":"2026-02-03T14:36:02Z","ingest_sequence":"6","book_sequence":"6","price":"100","quantity":"6","aggressor_side":"sell"}]}}} -{"contract_version":"15","scenario_sequence":"4","record_type":"scenario_end","payload":{"slice_count":"2"}} diff --git a/contracts/v15/fixtures/quote-trade.journal.jsonl b/contracts/v15/fixtures/quote-trade.journal.jsonl deleted file mode 100644 index 20bc174..0000000 --- a/contracts/v15/fixtures/quote-trade.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"15","engine_sequence":"1","event_id":"quote-trade-event-000000000001","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"b062a14acf0722c6d77e0e81985e12bf3a2a150dd7e493e1a811a393032c8d7f","execution_model":"quote_trade_v1"}} -{"contract_version":"15","engine_sequence":"2","event_id":"quote-trade-event-000000000002","causation_ids":["quote-trade-event-000000000001"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}}} -{"contract_version":"15","engine_sequence":"3","event_id":"quote-trade-event-000000000003","causation_ids":["quote-trade-event-000000000002"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"4","event_id":"quote-trade-event-000000000004","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"5","event_id":"quote-trade-event-000000000005","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.01484"}} -{"contract_version":"15","engine_sequence":"6","event_id":"quote-trade-event-000000000006","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"quote-trade-event-000000000006","updated_event_id":"quote-trade-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"15","engine_sequence":"7","event_id":"quote-trade-event-000000000007","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000.01484","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.01484","unrealized_pnl":"0","equity":"2000.01484","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000.01484","fx_rate":"1","base_value":"2000.01484","interest":"0.01484","base_interest":"0.01484","settled_amount":"2000.01484","unsettled_amount":"0","base_settled_value":"2000.01484","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.01484","settled_cash":"2000.01484","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000.01484","maintenance_excess":"2000.01484","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"8","event_id":"quote-trade-event-000000000008","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00.000000Z","available_at":"2026-02-03T14:31:01.000000Z","received_at":"2026-02-03T14:31:02.000000Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00.000000Z","available_at":"2026-02-03T14:32:01.000000Z","received_at":"2026-02-03T14:32:02.000000Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00.000000Z","available_at":"2026-02-03T14:33:01.000000Z","received_at":"2026-02-03T14:33:02.000000Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00.000000Z","available_at":"2026-02-03T14:34:01.000000Z","received_at":"2026-02-03T14:34:02.000000Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}],"order_book_events":[]}} -{"contract_version":"15","engine_sequence":"9","event_id":"quote-trade-event-000000000009","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000.01484","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.02968"}} -{"contract_version":"15","engine_sequence":"10","event_id":"quote-trade-event-000000000010","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000001","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"4","price":"99","notional":"396","fee":"10","executed_at":"2026-02-03T14:33:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"15","engine_sequence":"11","event_id":"quote-trade-event-000000000011","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000002","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"6","price":"100","notional":"600","fee":"10","executed_at":"2026-02-03T14:34:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"15","engine_sequence":"12","event_id":"quote-trade-event-000000000012","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"984.02968","fx_rate":"1","base_value":"984.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"984.02968","unsettled_amount":"0","base_settled_value":"984.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"984.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]}} -{"contract_version":"15","engine_sequence":"13","event_id":"quote-trade-event-000000000013","causation_ids":["quote-trade-event-000000000012"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"b062a14acf0722c6d77e0e81985e12bf3a2a150dd7e493e1a811a393032c8d7f","execution_model":"quote_trade_v1","valuation":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"984.02968","fx_rate":"1","base_value":"984.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"984.02968","unsettled_amount":"0","base_settled_value":"984.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"984.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":1,"rejected":0,"cancelled":0}}} diff --git a/contracts/v15/fixtures/quote-trade.scenario.jsonl b/contracts/v15/fixtures/quote-trade.scenario.jsonl deleted file mode 100644 index 6c2b50d..0000000 --- a/contracts/v15/fixtures/quote-trade.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"15","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine","purpose":"bounded quote and trade replay fixture"},"run_id":"quote-trade","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"clip-equity","symbol":"CLIP","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"clip-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["clip-equity"],"sessions":[{"session_date":"2026-02-02","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-02T14:30:00Z","closes_at":"2026-02-02T21:00:00Z"}]},{"session_date":"2026-02-03","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-03T14:30:00Z","closes_at":"2026-02-03T21:00:00Z"}]},{"session_date":"2026-02-04","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-02-04T14:30:00Z","closes_at":"2026-02-04T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000000","max_leverage":"1","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"clip-equity","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"quote_trade_v1","configuration":{"version":"1","participation_bps":10000,"fee_schedules":[{"schedule_id":"clip-fees-v1","instrument_id":"clip-equity","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"10","rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"clip-equity","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"15","scenario_sequence":"2","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00Z","end_at":"2026-02-02T21:00:00Z","available_at":"2026-02-02T21:00:01Z","received_at":"2026-02-02T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]},"intents":[{"type":"submit_order","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null}]}} -{"contract_version":"15","scenario_sequence":"3","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00Z","end_at":"2026-02-03T21:00:00Z","available_at":"2026-02-03T21:00:01Z","received_at":"2026-02-03T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00Z","available_at":"2026-02-03T14:31:01Z","received_at":"2026-02-03T14:31:02Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00Z","available_at":"2026-02-03T14:32:01Z","received_at":"2026-02-03T14:32:02Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00Z","available_at":"2026-02-03T14:33:01Z","received_at":"2026-02-03T14:33:02Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00Z","available_at":"2026-02-03T14:34:01Z","received_at":"2026-02-03T14:34:02Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}],"order_book_events":[]},"intents":[]}} -{"contract_version":"15","scenario_sequence":"4","record_type":"scenario_end","payload":{"slice_count":"2"}} diff --git a/contracts/v15/journal.schema.json b/contracts/v15/journal.schema.json deleted file mode 100644 index d9360c0..0000000 --- a/contracts/v15/journal.schema.json +++ /dev/null @@ -1,2427 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v15/journal.schema.json", - "title": "Trading Engine v15 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { - "const": "15" - }, - "engine_sequence": { - "$ref": "#/$defs/sequence" - }, - "event_id": { - "$ref": "#/$defs/identifier" - }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/$defs/identifier" - } - }, - "run_id": { - "$ref": "#/$defs/identifier" - }, - "recorded_at": { - "$ref": "#/$defs/timestamp" - }, - "event_type": { - "enum": [ - "run_started", - "initial_state", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_triggered", - "order_cancelled", - "split_applied", - "cash_dividend_applied", - "distribution_applied", - "lifecycle_applied", - "order_adjusted", - "execution_price_selected", - "fill_applied", - "settlement_instruction_created", - "settlement_completed", - "settlement_failed", - "fill_clipped", - "borrow_fee_applied", - "borrow_charge_applied", - "borrow_recall_received", - "cash_interest_applied", - "margin_call", - "margin_restored", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { - "type": "object" - } - }, - "allOf": [ - { - "if": { "properties": { "event_type": { "const": "execution_price_selected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/executionPriceSelected" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_started" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runStarted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "initial_state" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/initialState" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "market_slice_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/marketSlice" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "target_portfolio_requested" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/targetPortfolio" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "order_accepted", - "order_rejected", - "order_triggered" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/order" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_cancelled" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderCancelled" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "split_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/splitApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_dividend_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/dividendApplied" - } - } - } - }, - { - "if": { "properties": { "event_type": { "const": "distribution_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/distributionApplied" } } } - }, - { - "if": { "properties": { "event_type": { "const": "lifecycle_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/lifecycleApplied" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_adjusted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderAdjusted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fill" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "settlement_instruction_created", - "settlement_completed", - "settlement_failed" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/settlementInstruction" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_clipped" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fillClipped" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_fee_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowFee" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_charge_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowCharge" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_recall_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowRecall" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_interest_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/cashInterest" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "margin_call", - "margin_restored", - "valuation" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/valuation" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "intent_rejected" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/intentRejected" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "metric_emitted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/metric" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_completed" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runCompleted" - } - } - } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "nonnegativeSequence": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1", "order_book_v1"] - } - } - }, - "initialState": { - "type": "object", - "additionalProperties": false, - "required": [ - "portfolio", - "valuation" - ], - "properties": { - "portfolio": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/initialPortfolio" - }, - "valuation": { - "$ref": "#/$defs/valuation" - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "open", - "high", - "low", - "close", - "volume" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "open": { - "$ref": "#/$defs/positiveDecimal" - }, - "high": { - "$ref": "#/$defs/positiveDecimal" - }, - "low": { - "$ref": "#/$defs/positiveDecimal" - }, - "close": { - "$ref": "#/$defs/positiveDecimal" - }, - "volume": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/unsignedDecimal" - } - ] - } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "rate" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "rate": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "numerator", - "denominator" - ], - "properties": { - "type": { - "const": "split" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "numerator": { - "$ref": "#/$defs/sequence" - }, - "denominator": { - "$ref": "#/$defs/sequence" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "amount_per_unit" - ], - "properties": { - "type": { - "const": "cash_dividend" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "amount_per_unit": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/fractionalPolicy" } - } - } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars", - "fx_rates", - "corporate_actions", - "borrow_observations", - "cash_rate_observations", - "settlement_failures", - "lifecycle_events", - "market_events", - "order_book_events" - ], - "properties": { - "slice_sequence": { - "$ref": "#/$defs/sequence" - }, - "start_at": { - "$ref": "#/$defs/timestamp" - }, - "end_at": { - "$ref": "#/$defs/timestamp" - }, - "available_at": { - "$ref": "#/$defs/timestamp" - }, - "received_at": { - "$ref": "#/$defs/timestamp" - }, - "bars": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/bar" - } - }, - "fx_rates": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/fxRate" - } - }, - "corporate_actions": { - "type": "array", - "items": { - "$ref": "#/$defs/corporateAction" - } - }, - "borrow_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/borrowObservation" - } - }, - "cash_rate_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/cashRateObservation" - } - }, - "settlement_failures": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/settlementFailure" - } - }, - "lifecycle_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/lifecycleEvent" - } - }, - "market_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/marketEvent" - } - }, - "order_book_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/orderBookEvent" - } - } - } - }, - "settlementInstruction": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "fill_id", "instrument_id", "currency", "cash_movement", "position_movement", "trade_date", "due_date", "status", "settled_at", "failed_at", "failure_reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "fill_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "cash_movement": { "$ref": "#/$defs/signedDecimal" }, - "position_movement": { "$ref": "#/$defs/signedDecimal" }, - "trade_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "due_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "status": { "enum": ["pending", "settled", "failed"] }, - "settled_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failed_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failure_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" }] } - } - }, - "targetPortfolio": { - "type": "object", - "additionalProperties": false, - "required": [ - "basis", - "targets" - ], - "properties": { - "basis": { - "enum": [ - "weights", - "quantities" - ] - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "weight", - "quantity", - "reference_price" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "weight": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "reference_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - } - } - } - } - } - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "trigger_price", - "limit_price", - "time_in_force", - "venue_id", - "calendar_id", - "expires_at", - "origin", - "created_event_id", - "updated_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "triggered_at", - "triggered_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "order_kind": { - "enum": [ - "market", - "limit", - "stop", - "stop_limit" - ] - }, - "trigger_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "limit_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "time_in_force": { - "enum": [ - "gtc", - "ioc", - "fok", - "day", - "gtd" - ] - }, - "venue_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "calendar_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "expires_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "origin": { - "enum": [ - "direct", - "target_rebalance", - "margin_liquidation", - "borrow_recall", - "instrument_halt", - "instrument_terminal" - ] - }, - "created_event_id": { - "$ref": "#/$defs/identifier" - }, - "updated_event_id": { - "$ref": "#/$defs/identifier" - }, - "created_sequence": { - "$ref": "#/$defs/sequence" - }, - "created_at": { - "$ref": "#/$defs/timestamp" - }, - "eligible_after_slice_sequence": { - "$ref": "#/$defs/nonnegativeSequence" - }, - "triggered_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "triggered_slice_sequence": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/sequence" - } - ] - }, - "filled_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "filled_notional": { - "$ref": "#/$defs/unsignedDecimal" - }, - "status": { - "enum": [ - "working", - "partially_filled", - "filled", - "cancelled", - "rejected" - ] - }, - "rejection_reason": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "minLength": 1 - } - ] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "reason" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "reason": { - "enum": [ - "strategy_requested", - "target_replaced", - "market_ioc", - "immediate_or_cancel", - "fill_or_kill", - "day_expired", - "gtd_expired", - "margin_call", - "borrow_recall" - ] - } - } - }, - "splitApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "previous_quantity", - "adjusted_quantity" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "previous_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "adjusted_quantity": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "dividendApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "quantity", - "cash_amount" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "distributionApplied": { - "type": "object", - "additionalProperties": false, - "required": ["action", "source_quantity", "destination_quantity", "fractional_quantity", "allocated_basis", "fractional_basis", "cash_in_lieu"], - "properties": { - "action": { "$ref": "#/$defs/corporateAction" }, - "source_quantity": { "$ref": "#/$defs/signedDecimal" }, - "destination_quantity": { "$ref": "#/$defs/signedDecimal" }, - "fractional_quantity": { "$ref": "#/$defs/signedDecimal" }, - "allocated_basis": { "$ref": "#/$defs/signedDecimal" }, - "fractional_basis": { "$ref": "#/$defs/signedDecimal" }, - "cash_in_lieu": { "$ref": "#/$defs/signedDecimal" } - } - }, - "lifecycleApplied": { - "type": "object", - "additionalProperties": false, - "required": ["lifecycle_event", "listing", "liquidated_quantity", "cash_amount"], - "properties": { - "lifecycle_event": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/lifecycleEvent" }, - "listing": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "status", "provider_mappings"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "status": { "enum": ["tradable", "halted", "expired", "delisted"] }, - "provider_mappings": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["provider", "provider_instrument_id"], - "properties": { - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - } - } - } - }, - "liquidated_quantity": { "$ref": "#/$defs/signedDecimal" }, - "cash_amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "orderAdjusted": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "action_id" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "action_id": { - "$ref": "#/$defs/identifier" - } - } - }, - "executionPriceSelected": { - "type": "object", - "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "reference_price", "spread_adjustment", "impact_adjustment", "final_price"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "reference_price": { "$ref": "#/$defs/positiveDecimal" }, - "spread_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "impact_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "final_price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "quote_currency", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence", - "fee_components" - ], - "properties": { - "fill_id": { - "$ref": "#/$defs/identifier" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - }, - "notional": { - "$ref": "#/$defs/positiveDecimal" - }, - "fee": { - "$ref": "#/$defs/signedDecimal" - }, - "fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/calculatedFeeComponent" - } - }, - "executed_at": { - "$ref": "#/$defs/timestamp" - }, - "slice_sequence": { - "$ref": "#/$defs/sequence" - } - } - }, - "calculatedFeeComponent": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "feeComponentAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_currency", - "quote_amount", - "base_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "quantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "moneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "ratioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "basisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentQuantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "currencyMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "unit", "value"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "money" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "settlementPositionThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "unit", "value"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "quantity" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrumentBasisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentShortingThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "value": { - "const": false - } - } - }, - "groupMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "groupRatioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "fillClipReason": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_order_quantity" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_long_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_short_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/moneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_leverage" - }, - "threshold": { - "$ref": "#/$defs/ratioThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "initial_margin" - }, - "threshold": { - "$ref": "#/$defs/basisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_long_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_cash_buying_power" }, - "threshold": { "$ref": "#/$defs/currencyMoneyThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_position_availability" }, - "threshold": { "$ref": "#/$defs/settlementPositionThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_short_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_notional_exposure" - }, - "threshold": { - "$ref": "#/$defs/instrumentMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_shorting_disabled" - }, - "threshold": { - "$ref": "#/$defs/instrumentShortingThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_borrow_availability" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_initial_margin" - }, - "threshold": { - "$ref": "#/$defs/instrumentBasisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_long_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_short_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_absolute_net_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_concentration" - }, - "threshold": { - "$ref": "#/$defs/groupRatioThreshold" - } - } - } - ] - }, - "fillClipped": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason", - "order_id", - "instrument_id", - "proposed_quantity", - "permitted_quantity", - "price" - ], - "properties": { - "reason": { - "$ref": "#/$defs/fillClipReason" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "proposed_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "permitted_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowFee": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "short_quantity", - "reference_price", - "borrow_bps", - "period_start", - "period_end", - "fee" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "borrow_bps": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "fee": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowCharge": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "quote_currency", - "short_quantity", - "reference_price", - "day_count", - "compounding", - "period_start", - "period_end", - "amount" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/borrowObservation" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "borrowRecall": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "short_quantity", - "close_out_quantity" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/borrowObservation" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "close_out_quantity": { - "$ref": "#/$defs/unsignedDecimal" - } - } - }, - "cashInterest": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "opening_balance", - "applied_rate_bps", - "day_count", - "compounding", - "period_start", - "period_end", - "amount", - "closing_balance" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/cashRateObservation" - }, - "opening_balance": { - "$ref": "#/$defs/signedDecimal" - }, - "applied_rate_bps": { - "type": "integer", - "minimum": -1000000, - "maximum": 1000000 - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "closing_balance": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "cashAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "amount", - "fx_rate", - "base_value", - "interest", - "base_interest", - "settled_amount", - "unsettled_amount", - "base_settled_value", - "base_unsettled_value" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "base_value": { - "$ref": "#/$defs/signedDecimal" - }, - "interest": { - "$ref": "#/$defs/signedDecimal" - }, - "base_interest": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_settled_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unsettled_value": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "quantity", - "settled_quantity", - "unsettled_quantity", - "mark", - "fx_rate", - "market_value", - "base_market_value", - "cost_basis", - "base_cost_basis", - "realized_pnl", - "base_realized_pnl", - "unrealized_pnl", - "base_unrealized_pnl", - "dividend_pnl", - "base_dividend_pnl", - "execution_fees", - "base_execution_fees", - "borrow_fees", - "base_borrow_fees", - "total_fees", - "base_total_fees", - "execution_fee_components" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "mark": { - "$ref": "#/$defs/positiveDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "base_cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - } - } - }, - "margin": { - "type": "object", - "additionalProperties": false, - "required": [ - "initial_requirement", - "maintenance_requirement", - "initial_excess", - "maintenance_excess", - "margin_call" - ], - "properties": { - "initial_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "maintenance_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "initial_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "maintenance_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "margin_call": { - "type": "boolean" - } - } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "gross_exposure", - "net_exposure", - "long_exposure", - "short_exposure", - "concentration" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "net_exposure": { - "$ref": "#/$defs/signedDecimal" - }, - "long_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "concentration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "base_currency", - "cash", - "settled_cash", - "unsettled_cash", - "net_market_value", - "long_market_value", - "short_market_value", - "gross_exposure", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "dividend_pnl", - "execution_fees", - "borrow_fees", - "cash_interest", - "total_fees", - "cash_balances", - "positions", - "margin", - "group_exposures", - "execution_fee_components" - ], - "properties": { - "base_currency": { - "$ref": "#/$defs/identifier" - }, - "cash": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "net_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "long_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "equity": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/cashAttribution" - } - }, - "positions": { - "type": "array", - "items": { - "$ref": "#/$defs/positionAttribution" - } - }, - "margin": { - "$ref": "#/$defs/margin" - }, - "group_exposures": { - "type": "array", - "items": { - "$ref": "#/$defs/groupExposure" - } - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - }, - "cash_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "minLength": 1 - } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "value" - ], - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1", "order_book_v1"] - }, - "valuation": { - "$ref": "#/$defs/valuation" - }, - "order_counts": { - "type": "object", - "additionalProperties": false, - "required": [ - "total", - "active", - "filled", - "rejected", - "cancelled" - ], - "properties": { - "total": { - "type": "integer", - "minimum": 0 - }, - "active": { - "type": "integer", - "minimum": 0 - }, - "filled": { - "type": "integer", - "minimum": 0 - }, - "rejected": { - "type": "integer", - "minimum": 0 - }, - "cancelled": { - "type": "integer", - "minimum": 0 - } - } - } - } - } - } -} diff --git a/contracts/v15/scenario-stream.schema.json b/contracts/v15/scenario-stream.schema.json deleted file mode 100644 index 5af7c61..0000000 --- a/contracts/v15/scenario-stream.schema.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v15/scenario-stream.schema.json", - "title": "Trading Engine v15 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "15" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "15" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "15" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v15/scenario.schema.json b/contracts/v15/scenario.schema.json deleted file mode 100644 index ffab82b..0000000 --- a/contracts/v15/scenario.schema.json +++ /dev/null @@ -1,870 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v15/scenario.schema.json", - "title": "Trading Engine v15 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "15" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "financing": { "$ref": "#/$defs/financing" }, - "settlement": { "$ref": "#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "settlement": { - "type": "object", - "additionalProperties": false, - "required": ["cash_buying_power", "position_availability", "calendars", "rules"], - "properties": { - "cash_buying_power": { "enum": ["total_cash", "settled_cash"] }, - "position_availability": { "enum": ["total_positions", "settled_positions"] }, - "calendars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementCalendar" } }, - "rules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementRule" } } - } - }, - "settlementCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "version", "business_dates"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "version": { "const": "1" }, - "business_dates": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } - } - }, - "settlementRule": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "calendar_id", "lag_business_days"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "calendar_id": { "$ref": "#/$defs/identifier" }, - "lag_business_days": { "type": "integer", "minimum": 0, "maximum": 30 } - } - }, - "settlementFailure": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - }, - "financing": { - "type": "object", - "additionalProperties": false, - "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], - "properties": { - "day_count": { "enum": ["actual_365", "actual_360"] }, - "compounding": { "enum": ["simple", "daily"] }, - "borrow_missing_data": { "enum": ["reject", "zero"] }, - "cash_missing_data": { "enum": ["reject", "zero"] }, - "locate_policy": { "enum": ["reject_order", "clip_fill"] }, - "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } - } - }, - "borrowObservation": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, - "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "recalled": { "type": "boolean" } - } - }, - "cashRateObservation": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } - } - }, - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "enum": ["completed_bar_next_open_v1", "completed_bar_adverse_touch_v1"] }, - "configuration": { "$ref": "#/$defs/conservativeBarConfiguration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "quote_trade_v1" }, - "configuration": { "$ref": "#/$defs/quoteTradeConfiguration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "order_book_v1" }, - "configuration": { "$ref": "#/$defs/orderBookConfiguration" } - } - } - ] - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "conservativeBarConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules", "spread_model", "impact_model"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, - "spread_model": { "$ref": "#/$defs/fixedSpreadModel" }, - "impact_model": { "$ref": "#/$defs/linearImpactModel" } - } - }, - "quoteTradeConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "orderBookConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules", "max_depth_levels"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, - "max_depth_levels": { "type": "integer", "minimum": 1, "maximum": 1024 } - } - }, - "fixedSpreadModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "half_spread_bps"], - "properties": { - "model": { "const": "fixed_half_spread_v1" }, - "half_spread_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "linearImpactModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "coefficient_bps", "missing_volume_policy"], - "properties": { - "model": { "const": "linear_participation_v1" }, - "coefficient_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "missing_volume_policy": { "enum": ["reject", "zero_impact"] } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "market_events", "order_book_events", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations", "settlement_failures", "lifecycle_events"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "market_events": { "type": "array", "items": { "$ref": "#/$defs/marketEvent" } }, - "order_book_events": { "type": "array", "items": { "$ref": "#/$defs/orderBookEvent" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, - "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, - "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } }, - "settlement_failures": { "type": "array", "items": { "$ref": "#/$defs/settlementFailure" } }, - "lifecycle_events": { "type": "array", "items": { "$ref": "#/$defs/lifecycleEvent" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "marketEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "bid_price", "bid_quantity", "ask_price", "ask_quantity"], - "properties": { - "type": { "const": "quote" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "bid_price": { "$ref": "#/$defs/positiveDecimal" }, - "bid_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "ask_price": { "$ref": "#/$defs/positiveDecimal" }, - "ask_quantity": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "price", "quantity", "aggressor_side"], - "properties": { - "type": { "const": "trade" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "aggressor_side": { "enum": ["buy", "sell", "unknown"] } - } - } - ] - }, - "orderBookLevel": { - "type": "object", - "additionalProperties": false, - "required": ["price", "quantity"], - "properties": { - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "orderBookEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "bids", "asks"], - "properties": { - "type": { "const": "snapshot" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "bids": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/orderBookLevel" } }, - "asks": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/orderBookLevel" } } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "side", "price", "quantity"], - "properties": { - "type": { "const": "set" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "side": { "enum": ["bid", "ask"] }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "side", "price"], - "properties": { - "type": { "const": "delete" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "side": { "enum": ["bid", "ask"] }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "price", "quantity", "aggressor_side"], - "properties": { - "type": { "const": "trade" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "aggressor_side": { "enum": ["buy", "sell", "unknown"] } - } - } - ] - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "#/$defs/fractionalPolicy" } - } - } - ] - }, - "fractionalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "reject" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_in_lieu" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "terminalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "hold" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_out" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "lifecycleEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "reason"], - "properties": { - "type": { "const": "halt" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1 } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id"], - "properties": { - "type": { "const": "resume" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "symbol", "provider", "provider_instrument_id"], - "properties": { - "type": { "const": "identifier_change" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy"], - "properties": { - "type": { "const": "expiration" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy", "reason"], - "properties": { - "type": { "const": "delisting" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - } - } -} diff --git a/contracts/v16/README.md b/contracts/v16/README.md deleted file mode 100644 index 03ac9da..0000000 --- a/contracts/v16/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# Trading Engine contract v16 - -This directory is the authoritative v16 process and file contract shared by Trading Engine and its -clients. Versions 14 through 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v16 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v16 scenario, stream record, and journal record carries `"contract_version": "16"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v10 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. - -Version 10 adds a required `financing` policy and effective-time observations on every market -slice. Borrow observations provide per-instrument locate availability, signed annual rates, and -recall state. Cash observations provide separate annual credit and debit rates per currency. -Policies select Actual/365 or Actual/360 day count, simple or daily compounding, missing-data -handling, locate rejection or fill clipping, and recall rejection or deterministic close-out. - -Borrow availability is enforced when a fill would create or increase a short. Recalls cancel -active sells and may submit priority IOC covers until the position is flat. Borrow charges and cash -interest use the exact slice interval, update native ledgers deterministically, and emit dedicated -journal records. Valuations report cash interest separately and include it in aggregate realized -P&L. Version 9 and earlier retain their frozen fixed-borrow behavior and wire shapes. - -Version 12 separates trade-date economic accounting from settlement-date availability. A required -settlement policy selects total or settled cash buying power and total or settled position -availability. Versioned calendars enumerate canonical business dates, and each instrument has an -explicit business-day lag. Every fill creates a deterministic settlement instruction containing -its cash and position movements, trade date, and due date. A due instruction either settles on the -first eligible slice or records a named failure supplied by that slice. - -Valuations and strategy contexts report settled and unsettled cash and quantities without changing -economic equity. Journals include instruction-created, completed, and failed events. Scenario v10 -and strategy protocol v8 retain their frozen immediate-settlement wire behavior. - -Version 12 adds exact stock-dividend, rights, and spin-off distributions. Each distribution names -its destination instrument, exact entitlement ratio, basis allocation in basis points, and either -rejects fractional entitlements or converts them to cash at an explicit price and currency. -Stock dividends adjust persistent targets and eligible working orders; every distribution journals -delivered quantity, fractional quantity, allocated basis, fractional basis, and cash in lieu. - -Lifecycle events keep stable instrument identity separate from mutable symbol and provider -mappings. Halt and resume transitions control tradability. Expiration and delisting are terminal, -cancel active orders, clear target exposure, and require an explicit hold or cash-out policy. -Cash-out specifies its terminal price and currency. Every transition journals the source event, -resulting listing state, provider provenance, liquidated quantity, and cash attribution. - -Version 14 adds `completed_bar_next_open_v1` and `completed_bar_adverse_touch_v1` without changing -the frozen `completed_bar_v1` semantics. Next-open limits require a marketable later open; -adverse-touch limits require a one-tick trade-through before a maker fill is eligible. Both models -declare fixed half-spread and linear participation-impact catalogs, including an explicit policy -for missing bar volume. Price costs round away from the reference price to instrument ticks and -cannot violate a limit. An `execution_price_selected` audit record attributes the reference price, -spread adjustment, impact adjustment, and final executable price before each fill. - -Version 14 adds `quote_trade_v1` and causally ordered `market_events`. Quotes expose bid/ask price -and displayed size. Trades expose price, size, and buy, sell, or unknown aggressor side. Each event -records economic, availability, and receipt timestamps plus a positive ingest sequence. Replay -orders events by availability, receipt, and ingest sequence. Marketable orders consume only -displayed quote liquidity; passive orders require appropriately aggressed trade evidence, and an -unknown aggressor never fills them. Event capacity is shared deterministically across order -priority and fills retain the event's economic timestamp. Completed bars remain the valuation -boundary. The `quote-trade` batch, stream, and journal fixtures demonstrate equivalent replay. - -Version 15 added `order_book_v1` and bounded level-two `order_book_events`. Every per-instrument -slice bundle starts with a complete snapshot and continues with contiguous absolute set, delete, -and aggressor-classified trade updates. Snapshots and updates reject crossed books, missing -deletes, sequence gaps, tick or lot misalignment, and depth beyond the configured limit; locked -books are valid. State is rebuilt from each slice snapshot, so replay never depends on hidden data -from a prior slice. - -Marketable orders walk observable opposite-side depth in price priority. Passive limit orders join -behind displayed same-price quantity and earlier engine orders. Reductions decrease quantity ahead, -adds join behind, and only appropriately aggressed trades consume the queue and fill the order. -Partial fills and cancellations therefore remain deterministic. Book liquidity is independent of -bar and quote/trade execution semantics, while completed bars remain the valuation boundary. The -`order-book` batch, stream, and journal fixtures demonstrate cancellation, queue depletion, maker -fills, bounded state, and batch/stream equivalence. - -Version 16 replaces string-only metrics with typed observations. Numeric values use canonical -decimal strings; string and boolean values retain their JSON types. Optional units, a closed -aggregation enum, and up to 16 unique dimensions are bounded at ingestion. Dimension keys are -sorted before journal encoding for deterministic downstream reconciliation. diff --git a/contracts/v16/dune b/contracts/v16/dune deleted file mode 100644 index 0e7e927..0000000 --- a/contracts/v16/dune +++ /dev/null @@ -1,36 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v16/journal.schema.json) - (scenario-stream.schema.json as contracts/v16/scenario-stream.schema.json) - (scenario.schema.json as contracts/v16/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v16/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v16/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl - as - contracts/v16/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v16/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v16/fixtures/fill-clipped.scenario.json) - (fixtures/quote-trade.journal.jsonl - as - contracts/v16/fixtures/quote-trade.journal.jsonl) - (fixtures/quote-trade.scenario.json - as - contracts/v16/fixtures/quote-trade.scenario.json) - (fixtures/quote-trade.scenario.jsonl - as - contracts/v16/fixtures/quote-trade.scenario.jsonl) - (fixtures/order-book.journal.jsonl - as - contracts/v16/fixtures/order-book.journal.jsonl) - (fixtures/order-book.scenario.json - as - contracts/v16/fixtures/order-book.scenario.json) - (fixtures/order-book.scenario.jsonl - as - contracts/v16/fixtures/order-book.scenario.jsonl))) diff --git a/contracts/v16/fixtures/demo.journal.jsonl b/contracts/v16/fixtures/demo.journal.jsonl deleted file mode 100644 index 2590d37..0000000 --- a/contracts/v16/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,29 +0,0 @@ -{"contract_version":"16","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"a56b9b38f18d93e2953f90c8b052026d174e91c01a9465f8070a22040820a78d","execution_model":"completed_bar_adverse_touch_v1"}} -{"contract_version":"16","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"16","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000","interest":"0","base_interest":"0","settled_amount":"10000","unsettled_amount":"0","base_settled_value":"10000","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0","settled_cash":"10000","unsettled_cash":"0","margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-02T14:30:00.000000Z","period_end":"2026-01-02T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.074201"}} -{"contract_version":"16","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"16","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":{"type":"numeric","value":"0.1"},"unit":"ratio","dimensions":{"instrument":"demo-equity-acme","source":"strategy"},"aggregation":"last"}} -{"contract_version":"16","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004","demo-event-000000000006"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"16","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000.074201","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5.074201","unrealized_pnl":"14","equity":"10104.074201","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000.074201","fx_rate":"1","base_value":"10000.074201","interest":"0.074201","base_interest":"0.074201","settled_amount":"10000.074201","unsettled_amount":"0","base_settled_value":"10000.074201","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[],"settled_quantity":"1","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.074201","settled_cash":"10000.074201","unsettled_cash":"0","margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052.074201","maintenance_excess":"10078.074201","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"13"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-05T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"10000.074201","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-05T14:30:00.000000Z","period_end":"2026-01-05T21:00:00.000000Z","amount":"0.074201","closing_balance":"10000.148402"}} -{"contract_version":"16","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","reference_price":"103","spread_adjustment":"0.06","impact_adjustment":"0.13","final_price":"103.19"}} -{"contract_version":"16","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6.5","price":"103.19","notional":"670.735","fee":"0.920735","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_amount":"0.670735"}]}} -{"contract_version":"16","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000008","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000008","updated_event_id":"demo-event-000000000008","created_sequence":"8","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6.5","filled_notional":"670.735","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"16","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000006","demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"16","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000010"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9328.492667","net_market_value":"802.5","long_market_value":"802.5","short_market_value":"0","gross_exposure":"802.5","cost_basis":"761.655735","realized_pnl":"5.148402","unrealized_pnl":"40.844265","equity":"10130.992667","dividend_pnl":"1","execution_fees":"1.420735","borrow_fees":"0.25","total_fees":"1.670735","cash_balances":[{"currency":"USD","amount":"9328.492667","fx_rate":"1","base_value":"9328.492667","interest":"0.148402","base_interest":"0.148402","settled_amount":"9328.492667","unsettled_amount":"0","base_settled_value":"9328.492667","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7.5","mark":"107","fx_rate":"1","market_value":"802.5","base_market_value":"802.5","cost_basis":"761.655735","base_cost_basis":"761.655735","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.844265","base_unrealized_pnl":"40.844265","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.420735","base_execution_fees":"1.420735","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.670735","base_total_fees":"1.670735","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"settled_quantity":"7.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.670735","quote_currency":"USD","quote_amount":"0.670735","base_amount":"0.670735"}],"cash_interest":"0.148402","settled_cash":"9328.492667","unsettled_cash":"0","margin":{"initial_requirement":"401.25","maintenance_requirement":"200.625","initial_excess":"9729.742667","maintenance_excess":"9930.367667","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-06T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9328.492667","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-06T14:30:00.000000Z","period_end":"2026-01-06T21:00:00.000000Z","amount":"0.069218","closing_balance":"9328.561885"}} -{"contract_version":"16","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","reference_price":"107","spread_adjustment":"0.06","impact_adjustment":"0.01","final_price":"107.07"}} -{"contract_version":"16","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.215","price":"107.07","notional":"237.16005","fee":"0.487161","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.237161","quote_amount":"0.237161"}]}} -{"contract_version":"16","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"16","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000017","demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000022","updated_event_id":"demo-event-000000000022","created_sequence":"22","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"16","engine_sequence":"23","event_id":"demo-event-000000000023","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.914674","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.302946","realized_pnl":"5.21762","unrealized_pnl":"20.772054","equity":"10110.989674","dividend_pnl":"1","execution_fees":"1.907896","borrow_fees":"0.25","total_fees":"2.157896","cash_balances":[{"currency":"USD","amount":"9090.914674","fx_rate":"1","base_value":"9090.914674","interest":"0.21762","base_interest":"0.21762","settled_amount":"9090.914674","unsettled_amount":"0","base_settled_value":"9090.914674","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.302946","base_cost_basis":"999.302946","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.772054","base_unrealized_pnl":"20.772054","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.907896","base_execution_fees":"1.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.157896","base_total_fees":"2.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"settled_quantity":"9.715","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.907896","quote_currency":"USD","quote_amount":"0.907896","base_amount":"0.907896"}],"cash_interest":"0.21762","settled_cash":"9090.914674","unsettled_cash":"0","margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.952174","maintenance_excess":"9855.970924","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"24","event_id":"demo-event-000000000024","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"25","event_id":"demo-event-000000000025","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-01-07T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"9090.914674","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-01-07T14:30:00.000000Z","period_end":"2026-01-07T21:00:00.000000Z","amount":"0.067455","closing_balance":"9090.982129"}} -{"contract_version":"16","engine_sequence":"26","event_id":"demo-event-000000000026","causation_ids":["demo-event-000000000022","demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"execution_price_selected","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","reference_price":"105","spread_adjustment":"0.06","impact_adjustment":"0.02","final_price":"104.92"}} -{"contract_version":"16","engine_sequence":"27","event_id":"demo-event-000000000027","causation_ids":["demo-event-000000000026"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"104.92","notional":"756.9978","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.756998","quote_amount":"0.756998"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_amount":"-0.006998"}]}} -{"contract_version":"16","engine_sequence":"28","event_id":"demo-event-000000000028","causation_ids":["demo-event-000000000024"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"29","event_id":"demo-event-000000000029","causation_ids":["demo-event-000000000028"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"a56b9b38f18d93e2953f90c8b052026d174e91c01a9465f8070a22040820a78d","execution_model":"completed_bar_adverse_touch_v1","valuation":{"base_currency":"USD","cash":"9846.979929","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.154644","realized_pnl":"19.134573","unrealized_pnl":"7.845356","equity":"10111.979929","dividend_pnl":"1","execution_fees":"2.907896","borrow_fees":"0.25","total_fees":"3.157896","cash_balances":[{"currency":"USD","amount":"9846.979929","fx_rate":"1","base_value":"9846.979929","interest":"0.285075","base_interest":"0.285075","settled_amount":"9846.979929","unsettled_amount":"0","base_settled_value":"9846.979929","base_unsettled_value":"0"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.154644","base_cost_basis":"257.154644","realized_pnl":"18.849498","base_realized_pnl":"18.849498","unrealized_pnl":"7.845356","base_unrealized_pnl":"7.845356","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.907896","base_execution_fees":"2.907896","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.157896","base_total_fees":"3.157896","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"settled_quantity":"2.5","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.664894","quote_currency":"USD","quote_amount":"1.664894","base_amount":"1.664894"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.006998","quote_currency":"USD","quote_amount":"-0.006998","base_amount":"-0.006998"}],"cash_interest":"0.285075","settled_cash":"9846.979929","unsettled_cash":"0","margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.479929","maintenance_excess":"10045.729929","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v16/fixtures/demo.scenario.json b/contracts/v16/fixtures/demo.scenario.json deleted file mode 100644 index b8b8fb3..0000000 --- a/contracts/v16/fixtures/demo.scenario.json +++ /dev/null @@ -1,468 +0,0 @@ -{ - "contract_version": "16", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_adverse_touch_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "0.25", - "rounding": "up", - "applies_to": "any" - }, - { - "name": "exchange", - "currency": "USD", - "kind": "notional_bps", - "value": 10, - "rounding": "up", - "applies_to": "taker" - }, - { - "name": "maker_rebate", - "currency": "USD", - "kind": "notional_bps", - "value": -2, - "rounding": "nearest", - "applies_to": "maker" - } - ] - } - ], - "spread_model": { - "model": "fixed_half_spread_v1", - "half_spread_bps": 5 - }, - "impact_model": { - "model": "linear_participation_v1", - "coefficient_bps": 25, - "missing_volume_policy": "reject" - } - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": { "type": "numeric", "value": "0.1" }, - "unit": "ratio", - "dimensions": { "source": "strategy", "instrument": "demo-equity-acme" }, - "aggregation": "last" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "13" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-05T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-05T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-06T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-06T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "demo-equity-acme", - "effective_at": "2026-01-07T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-01-07T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "demo-equity-acme", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v16/fixtures/demo.scenario.jsonl b/contracts/v16/fixtures/demo.scenario.jsonl deleted file mode 100644 index 28012c0..0000000 --- a/contracts/v16/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"16","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_adverse_touch_v1","configuration":{"version":"1","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}],"spread_model":{"model":"fixed_half_spread_v1","half_spread_bps":5},"impact_model":{"model":"linear_participation_v1","coefficient_bps":25,"missing_volume_policy":"reject"}}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"demo-equity-acme","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"16","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"aggregation":"last","dimensions":{"instrument":"demo-equity-acme","source":"strategy"},"name":"desired_weight","type":"emit_metric","unit":"ratio","value":{"type":"numeric","value":"0.1"}}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"16","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"13"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-05T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-05T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"16","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-06T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-06T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"16","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z","borrow_observations":[{"instrument_id":"demo-equity-acme","effective_at":"2026-01-07T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-01-07T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"16","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v16/fixtures/fill-clipped.journal.jsonl b/contracts/v16/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 3419c5a..0000000 --- a/contracts/v16/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"16","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"dd1ca1913eb2ef4e0070887065763fb75e81a1e27b4497bf2afd09546975bd07","execution_model":"completed_bar_v1"}} -{"contract_version":"16","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"16","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550","interest":"0","base_interest":"0","settled_amount":"550","unsettled_amount":"0","base_settled_value":"550","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"550","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.004081"}} -{"contract_version":"16","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"16","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.004081","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.004081","unrealized_pnl":"0","equity":"550.004081","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.004081","fx_rate":"1","base_value":"550.004081","interest":"0.004081","base_interest":"0.004081","settled_amount":"550.004081","unsettled_amount":"0","base_settled_value":"550.004081","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.004081","settled_cash":"550.004081","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.004081","maintenance_excess":"550.004081","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"550.004081","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.004081","closing_balance":"550.008162"}} -{"contract_version":"16","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"16","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000006","fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000006","updated_event_id":"fill-clipped-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"16","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000008"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"13","event_id":"fill-clipped-event-000000000013","causation_ids":["fill-clipped-event-000000000012"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"dd1ca1913eb2ef4e0070887065763fb75e81a1e27b4497bf2afd09546975bd07","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550.008162","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.008162","unrealized_pnl":"0","equity":"550.008162","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550.008162","fx_rate":"1","base_value":"550.008162","interest":"0.008162","base_interest":"0.008162","settled_amount":"550.008162","unsettled_amount":"0","base_settled_value":"550.008162","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.008162","settled_cash":"550.008162","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550.008162","maintenance_excess":"550.008162","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v16/fixtures/fill-clipped.scenario.json b/contracts/v16/fixtures/fill-clipped.scenario.json deleted file mode 100644 index eea4e6d..0000000 --- a/contracts/v16/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "contract_version": "16", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v16/fixtures/order-book.journal.jsonl b/contracts/v16/fixtures/order-book.journal.jsonl deleted file mode 100644 index 684543d..0000000 --- a/contracts/v16/fixtures/order-book.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"16","engine_sequence":"1","event_id":"order-book-event-000000000001","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"10f1592feb856e3acc16a2eb3ebd23ff2c7641e092b88307e44efcd9f2072d74","execution_model":"order_book_v1"}} -{"contract_version":"16","engine_sequence":"2","event_id":"order-book-event-000000000002","causation_ids":["order-book-event-000000000001"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}}} -{"contract_version":"16","engine_sequence":"3","event_id":"order-book-event-000000000003","causation_ids":["order-book-event-000000000002"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"4","event_id":"order-book-event-000000000004","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-02T14:31:00.000000Z","available_at":"2026-02-02T14:31:01.000000Z","received_at":"2026-02-02T14:31:02.000000Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"49","quantity":"20"}],"asks":[{"price":"51","quantity":"20"}]}]}} -{"contract_version":"16","engine_sequence":"5","event_id":"order-book-event-000000000005","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.01484"}} -{"contract_version":"16","engine_sequence":"6","event_id":"order-book-event-000000000006","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"order-book-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"order-book-event-000000000006","updated_event_id":"order-book-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"16","engine_sequence":"7","event_id":"order-book-event-000000000007","causation_ids":["order-book-event-000000000004"],"run_id":"order-book","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000.01484","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.01484","unrealized_pnl":"0","equity":"2000.01484","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000.01484","fx_rate":"1","base_value":"2000.01484","interest":"0.01484","base_interest":"0.01484","settled_amount":"2000.01484","unsettled_amount":"0","base_settled_value":"2000.01484","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.01484","settled_cash":"2000.01484","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000.01484","maintenance_excess":"2000.01484","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"8","event_id":"order-book-event-000000000008","causation_ids":[],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00.000000Z","available_at":"2026-02-03T14:31:01.000000Z","received_at":"2026-02-03T14:31:02.000000Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"100","quantity":"5"}],"asks":[{"price":"101","quantity":"20"}]},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00.000000Z","available_at":"2026-02-03T14:32:01.000000Z","received_at":"2026-02-03T14:32:02.000000Z","ingest_sequence":"2","book_sequence":"2","side":"bid","price":"100","quantity":"3"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00.000000Z","available_at":"2026-02-03T14:33:01.000000Z","received_at":"2026-02-03T14:33:02.000000Z","ingest_sequence":"3","book_sequence":"3","price":"100","quantity":"3","aggressor_side":"sell"},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00.000000Z","available_at":"2026-02-03T14:34:01.000000Z","received_at":"2026-02-03T14:34:02.000000Z","ingest_sequence":"4","book_sequence":"4","side":"bid","price":"100","quantity":"10"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:35:00.000000Z","available_at":"2026-02-03T14:35:01.000000Z","received_at":"2026-02-03T14:35:02.000000Z","ingest_sequence":"5","book_sequence":"5","price":"100","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:36:00.000000Z","available_at":"2026-02-03T14:36:01.000000Z","received_at":"2026-02-03T14:36:02.000000Z","ingest_sequence":"6","book_sequence":"6","price":"100","quantity":"6","aggressor_side":"sell"}]}} -{"contract_version":"16","engine_sequence":"9","event_id":"order-book-event-000000000009","causation_ids":["order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000.01484","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.02968"}} -{"contract_version":"16","engine_sequence":"10","event_id":"order-book-event-000000000010","causation_ids":["order-book-event-000000000006","order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"order-book-fill-000000000001","order_id":"order-book-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"4","price":"100","notional":"400","fee":"10","executed_at":"2026-02-03T14:35:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"16","engine_sequence":"11","event_id":"order-book-event-000000000011","causation_ids":["order-book-event-000000000006","order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"order-book-fill-000000000002","order_id":"order-book-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"6","price":"100","notional":"600","fee":"10","executed_at":"2026-02-03T14:36:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"16","engine_sequence":"12","event_id":"order-book-event-000000000012","causation_ids":["order-book-event-000000000008"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"980.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1020","realized_pnl":"0.02968","unrealized_pnl":"-20","equity":"1980.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"980.02968","fx_rate":"1","base_value":"980.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"980.02968","unsettled_amount":"0","base_settled_value":"980.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1020","base_cost_basis":"1020","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-20","base_unrealized_pnl":"-20","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"980.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1480.02968","maintenance_excess":"1730.02968","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"13","event_id":"order-book-event-000000000013","causation_ids":["order-book-event-000000000012"],"run_id":"order-book","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"10f1592feb856e3acc16a2eb3ebd23ff2c7641e092b88307e44efcd9f2072d74","execution_model":"order_book_v1","valuation":{"base_currency":"USD","cash":"980.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1020","realized_pnl":"0.02968","unrealized_pnl":"-20","equity":"1980.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"980.02968","fx_rate":"1","base_value":"980.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"980.02968","unsettled_amount":"0","base_settled_value":"980.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1020","base_cost_basis":"1020","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-20","base_unrealized_pnl":"-20","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"980.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1480.02968","maintenance_excess":"1730.02968","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":1,"rejected":0,"cancelled":0}}} diff --git a/contracts/v16/fixtures/order-book.scenario.jsonl b/contracts/v16/fixtures/order-book.scenario.jsonl deleted file mode 100644 index e8aa5d3..0000000 --- a/contracts/v16/fixtures/order-book.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"16","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine","purpose":"bounded order-book replay conformance fixture"},"run_id":"order-book","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"clip-equity","symbol":"CLIP","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"clip-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["clip-equity"],"sessions":[{"session_date":"2026-02-02","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-02T14:30:00Z","closes_at":"2026-02-02T21:00:00Z"}]},{"session_date":"2026-02-03","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-03T14:30:00Z","closes_at":"2026-02-03T21:00:00Z"}]},{"session_date":"2026-02-04","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-02-04T14:30:00Z","closes_at":"2026-02-04T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000000","max_leverage":"1","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"clip-equity","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"order_book_v1","configuration":{"version":"1","participation_bps":10000,"fee_schedules":[{"schedule_id":"clip-fees-v1","instrument_id":"clip-equity","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"10","rounding":"up","applies_to":"any"}]}],"max_depth_levels":10}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"clip-equity","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"16","scenario_sequence":"2","record_type":"market_slice","payload":{"intents":[{"type":"submit_order","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null}],"market_slice":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00Z","end_at":"2026-02-02T21:00:00Z","available_at":"2026-02-02T21:00:01Z","received_at":"2026-02-02T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-02T14:31:00Z","available_at":"2026-02-02T14:31:01Z","received_at":"2026-02-02T14:31:02Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"49","quantity":"20"}],"asks":[{"price":"51","quantity":"20"}]}]}}} -{"contract_version":"16","scenario_sequence":"3","record_type":"market_slice","payload":{"intents":[],"market_slice":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00Z","end_at":"2026-02-03T21:00:00Z","available_at":"2026-02-03T21:00:01Z","received_at":"2026-02-03T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[{"type":"snapshot","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00Z","available_at":"2026-02-03T14:31:01Z","received_at":"2026-02-03T14:31:02Z","ingest_sequence":"1","book_sequence":"1","bids":[{"price":"100","quantity":"5"}],"asks":[{"price":"101","quantity":"20"}]},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00Z","available_at":"2026-02-03T14:32:01Z","received_at":"2026-02-03T14:32:02Z","ingest_sequence":"2","book_sequence":"2","side":"bid","price":"100","quantity":"3"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00Z","available_at":"2026-02-03T14:33:01Z","received_at":"2026-02-03T14:33:02Z","ingest_sequence":"3","book_sequence":"3","price":"100","quantity":"3","aggressor_side":"sell"},{"type":"set","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00Z","available_at":"2026-02-03T14:34:01Z","received_at":"2026-02-03T14:34:02Z","ingest_sequence":"4","book_sequence":"4","side":"bid","price":"100","quantity":"10"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:35:00Z","available_at":"2026-02-03T14:35:01Z","received_at":"2026-02-03T14:35:02Z","ingest_sequence":"5","book_sequence":"5","price":"100","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:36:00Z","available_at":"2026-02-03T14:36:01Z","received_at":"2026-02-03T14:36:02Z","ingest_sequence":"6","book_sequence":"6","price":"100","quantity":"6","aggressor_side":"sell"}]}}} -{"contract_version":"16","scenario_sequence":"4","record_type":"scenario_end","payload":{"slice_count":"2"}} diff --git a/contracts/v16/fixtures/quote-trade.journal.jsonl b/contracts/v16/fixtures/quote-trade.journal.jsonl deleted file mode 100644 index b6e48b2..0000000 --- a/contracts/v16/fixtures/quote-trade.journal.jsonl +++ /dev/null @@ -1,13 +0,0 @@ -{"contract_version":"16","engine_sequence":"1","event_id":"quote-trade-event-000000000001","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"0e57b52243f3fc9fe37b94dc8fbde9a8b69c6c680bd5369e4d77c63060b853e8","execution_model":"quote_trade_v1"}} -{"contract_version":"16","engine_sequence":"2","event_id":"quote-trade-event-000000000002","causation_ids":["quote-trade-event-000000000001"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}}} -{"contract_version":"16","engine_sequence":"3","event_id":"quote-trade-event-000000000003","causation_ids":["quote-trade-event-000000000002"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"2000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000","fx_rate":"1","base_value":"2000","interest":"0","base_interest":"0","settled_amount":"2000","unsettled_amount":"0","base_settled_value":"2000","base_unsettled_value":"0"}],"positions":[],"execution_fee_components":[],"cash_interest":"0","settled_cash":"2000","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000","maintenance_excess":"2000","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"4","event_id":"quote-trade-event-000000000004","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"5","event_id":"quote-trade-event-000000000005","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-02T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-02T14:30:00.000000Z","period_end":"2026-02-02T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.01484"}} -{"contract_version":"16","engine_sequence":"6","event_id":"quote-trade-event-000000000006","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"quote-trade-event-000000000006","updated_event_id":"quote-trade-event-000000000006","created_sequence":"6","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"16","engine_sequence":"7","event_id":"quote-trade-event-000000000007","causation_ids":["quote-trade-event-000000000004"],"run_id":"quote-trade","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"2000.01484","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0.01484","unrealized_pnl":"0","equity":"2000.01484","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"2000.01484","fx_rate":"1","base_value":"2000.01484","interest":"0.01484","base_interest":"0.01484","settled_amount":"2000.01484","unsettled_amount":"0","base_settled_value":"2000.01484","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[],"settled_quantity":"0","unsettled_quantity":"0"}],"execution_fee_components":[],"cash_interest":"0.01484","settled_cash":"2000.01484","unsettled_cash":"0","margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"2000.01484","maintenance_excess":"2000.01484","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"8","event_id":"quote-trade-event-000000000008","causation_ids":[],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00.000000Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00.000000Z","available_at":"2026-02-03T14:31:01.000000Z","received_at":"2026-02-03T14:31:02.000000Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00.000000Z","available_at":"2026-02-03T14:32:01.000000Z","received_at":"2026-02-03T14:32:02.000000Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00.000000Z","available_at":"2026-02-03T14:33:01.000000Z","received_at":"2026-02-03T14:33:02.000000Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00.000000Z","available_at":"2026-02-03T14:34:01.000000Z","received_at":"2026-02-03T14:34:02.000000Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}],"order_book_events":[]}} -{"contract_version":"16","engine_sequence":"9","event_id":"quote-trade-event-000000000009","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"cash_interest_applied","payload":{"observation":{"currency":"USD","effective_at":"2026-02-03T14:30:00.000000Z","credit_rate_bps":100,"debit_rate_bps":200},"opening_balance":"2000.01484","applied_rate_bps":100,"day_count":"actual_365","compounding":"simple","period_start":"2026-02-03T14:30:00.000000Z","period_end":"2026-02-03T21:00:00.000000Z","amount":"0.01484","closing_balance":"2000.02968"}} -{"contract_version":"16","engine_sequence":"10","event_id":"quote-trade-event-000000000010","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000001","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"4","price":"99","notional":"396","fee":"10","executed_at":"2026-02-03T14:33:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"16","engine_sequence":"11","event_id":"quote-trade-event-000000000011","causation_ids":["quote-trade-event-000000000006","quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"quote-trade-fill-000000000002","order_id":"quote-trade-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"6","price":"100","notional":"600","fee":"10","executed_at":"2026-02-03T14:34:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"10","quote_amount":"10"}]}} -{"contract_version":"16","engine_sequence":"12","event_id":"quote-trade-event-000000000012","causation_ids":["quote-trade-event-000000000008"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"984.02968","fx_rate":"1","base_value":"984.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"984.02968","unsettled_amount":"0","base_settled_value":"984.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"984.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]}} -{"contract_version":"16","engine_sequence":"13","event_id":"quote-trade-event-000000000013","causation_ids":["quote-trade-event-000000000012"],"run_id":"quote-trade","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"0e57b52243f3fc9fe37b94dc8fbde9a8b69c6c680bd5369e4d77c63060b853e8","execution_model":"quote_trade_v1","valuation":{"base_currency":"USD","cash":"984.02968","net_market_value":"1000","long_market_value":"1000","short_market_value":"0","gross_exposure":"1000","cost_basis":"1016","realized_pnl":"0.02968","unrealized_pnl":"-16","equity":"1984.02968","dividend_pnl":"0","execution_fees":"20","borrow_fees":"0","total_fees":"20","cash_balances":[{"currency":"USD","amount":"984.02968","fx_rate":"1","base_value":"984.02968","interest":"0.02968","base_interest":"0.02968","settled_amount":"984.02968","unsettled_amount":"0","base_settled_value":"984.02968","base_unsettled_value":"0"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"10","mark":"100","fx_rate":"1","market_value":"1000","base_market_value":"1000","cost_basis":"1016","base_cost_basis":"1016","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-16","base_unrealized_pnl":"-16","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"20","base_execution_fees":"20","borrow_fees":"0","base_borrow_fees":"0","total_fees":"20","base_total_fees":"20","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"settled_quantity":"10","unsettled_quantity":"0"}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"20","quote_currency":"USD","quote_amount":"20","base_amount":"20"}],"cash_interest":"0.02968","settled_cash":"984.02968","unsettled_cash":"0","margin":{"initial_requirement":"500","maintenance_requirement":"250","initial_excess":"1484.02968","maintenance_excess":"1734.02968","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":1,"rejected":0,"cancelled":0}}} diff --git a/contracts/v16/fixtures/quote-trade.scenario.json b/contracts/v16/fixtures/quote-trade.scenario.json deleted file mode 100644 index baf05f8..0000000 --- a/contracts/v16/fixtures/quote-trade.scenario.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "contract_version": "16", - "metadata": { - "producer": "trading-engine", - "purpose": "bounded quote and trade replay fixture" - }, - "run_id": "quote-trade", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "2000" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "quote_trade_v1", - "configuration": { - "version": "1", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { - "name": "broker", - "currency": "USD", - "kind": "fixed", - "value": "10", - "rounding": "up", - "applies_to": "any" - } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "limit", - "trigger_price": null, - "limit_price": "100", - "time_in_force": "gtc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-02T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-02T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [], - "order_book_events": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [], - "borrow_observations": [ - { - "instrument_id": "clip-equity", - "effective_at": "2026-02-03T14:30:00Z", - "available_quantity": "1000", - "annual_rate_bps": 100, - "recalled": false - } - ], - "cash_rate_observations": [ - { - "currency": "USD", - "effective_at": "2026-02-03T14:30:00Z", - "credit_rate_bps": 100, - "debit_rate_bps": 200 - } - ], - "settlement_failures": [], - "lifecycle_events": [], - "market_events": [ - { - "type": "quote", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:31:00Z", - "available_at": "2026-02-03T14:31:01Z", - "received_at": "2026-02-03T14:31:02Z", - "ingest_sequence": "1", - "bid_price": "99", - "bid_quantity": "20", - "ask_price": "101", - "ask_quantity": "20" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:32:00Z", - "available_at": "2026-02-03T14:32:01Z", - "received_at": "2026-02-03T14:32:02Z", - "ingest_sequence": "2", - "price": "100", - "quantity": "5", - "aggressor_side": "unknown" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:33:00Z", - "available_at": "2026-02-03T14:33:01Z", - "received_at": "2026-02-03T14:33:02Z", - "ingest_sequence": "3", - "price": "99", - "quantity": "4", - "aggressor_side": "sell" - }, - { - "type": "trade", - "instrument_id": "clip-equity", - "event_at": "2026-02-03T14:34:00Z", - "available_at": "2026-02-03T14:34:01Z", - "received_at": "2026-02-03T14:34:02Z", - "ingest_sequence": "4", - "price": "100", - "quantity": "10", - "aggressor_side": "sell" - } - ], - "order_book_events": [] - } - ], - "financing": { - "day_count": "actual_365", - "compounding": "simple", - "borrow_missing_data": "reject", - "cash_missing_data": "reject", - "locate_policy": "clip_fill", - "recall_policy": "close_out" - }, - "settlement": { - "cash_buying_power": "total_cash", - "position_availability": "total_positions", - "calendars": [ - { - "calendar_id": "default-settlement", - "version": "1", - "business_dates": [ - "2026-01-02", - "2026-01-05", - "2026-01-06", - "2026-01-07", - "2026-01-08", - "2026-01-09", - "2026-02-02", - "2026-02-03", - "2026-02-04", - "2026-02-05" - ] - } - ], - "rules": [ - { - "instrument_id": "clip-equity", - "calendar_id": "default-settlement", - "lag_business_days": 1 - } - ] - } -} diff --git a/contracts/v16/fixtures/quote-trade.scenario.jsonl b/contracts/v16/fixtures/quote-trade.scenario.jsonl deleted file mode 100644 index 842d0e7..0000000 --- a/contracts/v16/fixtures/quote-trade.scenario.jsonl +++ /dev/null @@ -1,4 +0,0 @@ -{"contract_version":"16","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine","purpose":"bounded quote and trade replay fixture"},"run_id":"quote-trade","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"2000"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"clip-equity","symbol":"CLIP","quote_currency":"USD","tick_size":"0.01","lot_size":"1"}],"venue_calendars":[{"calendar_id":"clip-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["clip-equity"],"sessions":[{"session_date":"2026-02-02","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-02T14:30:00Z","closes_at":"2026-02-02T21:00:00Z"}]},{"session_date":"2026-02-03","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-02-03T14:30:00Z","closes_at":"2026-02-03T21:00:00Z"}]},{"session_date":"2026-02-04","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-02-04T14:30:00Z","closes_at":"2026-02-04T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000000","max_leverage":"1","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"clip-equity","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"quote_trade_v1","configuration":{"version":"1","participation_bps":10000,"fee_schedules":[{"schedule_id":"clip-fees-v1","instrument_id":"clip-equity","settlement_currency":"USD","minimum":null,"maximum":null,"components":[{"name":"broker","currency":"USD","kind":"fixed","value":"10","rounding":"up","applies_to":"any"}]}]}},"max_internal_events":1000,"financing":{"day_count":"actual_365","compounding":"simple","borrow_missing_data":"reject","cash_missing_data":"reject","locate_policy":"clip_fill","recall_policy":"close_out"},"settlement":{"cash_buying_power":"total_cash","position_availability":"total_positions","calendars":[{"calendar_id":"default-settlement","version":"1","business_dates":["2026-01-02","2026-01-05","2026-01-06","2026-01-07","2026-01-08","2026-01-09","2026-02-02","2026-02-03","2026-02-04","2026-02-05"]}],"rules":[{"instrument_id":"clip-equity","calendar_id":"default-settlement","lag_business_days":1}]}}} -{"contract_version":"16","scenario_sequence":"2","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00Z","end_at":"2026-02-02T21:00:00Z","available_at":"2026-02-02T21:00:01Z","received_at":"2026-02-02T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-02T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-02T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[],"order_book_events":[]},"intents":[{"type":"submit_order","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"limit","trigger_price":null,"limit_price":"100","time_in_force":"gtc","venue_id":null,"calendar_id":null,"expires_at":null}]}} -{"contract_version":"16","scenario_sequence":"3","record_type":"market_slice","payload":{"market_slice":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00Z","end_at":"2026-02-03T21:00:00Z","available_at":"2026-02-03T21:00:01Z","received_at":"2026-02-03T21:00:02Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[],"borrow_observations":[{"instrument_id":"clip-equity","effective_at":"2026-02-03T14:30:00Z","available_quantity":"1000","annual_rate_bps":100,"recalled":false}],"cash_rate_observations":[{"currency":"USD","effective_at":"2026-02-03T14:30:00Z","credit_rate_bps":100,"debit_rate_bps":200}],"settlement_failures":[],"lifecycle_events":[],"market_events":[{"type":"quote","instrument_id":"clip-equity","event_at":"2026-02-03T14:31:00Z","available_at":"2026-02-03T14:31:01Z","received_at":"2026-02-03T14:31:02Z","ingest_sequence":"1","bid_price":"99","bid_quantity":"20","ask_price":"101","ask_quantity":"20"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:32:00Z","available_at":"2026-02-03T14:32:01Z","received_at":"2026-02-03T14:32:02Z","ingest_sequence":"2","price":"100","quantity":"5","aggressor_side":"unknown"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:33:00Z","available_at":"2026-02-03T14:33:01Z","received_at":"2026-02-03T14:33:02Z","ingest_sequence":"3","price":"99","quantity":"4","aggressor_side":"sell"},{"type":"trade","instrument_id":"clip-equity","event_at":"2026-02-03T14:34:00Z","available_at":"2026-02-03T14:34:01Z","received_at":"2026-02-03T14:34:02Z","ingest_sequence":"4","price":"100","quantity":"10","aggressor_side":"sell"}],"order_book_events":[]},"intents":[]}} -{"contract_version":"16","scenario_sequence":"4","record_type":"scenario_end","payload":{"slice_count":"2"}} diff --git a/contracts/v16/journal.schema.json b/contracts/v16/journal.schema.json deleted file mode 100644 index 2315fa1..0000000 --- a/contracts/v16/journal.schema.json +++ /dev/null @@ -1,2441 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v16/journal.schema.json", - "title": "Trading Engine v16 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { - "const": "16" - }, - "engine_sequence": { - "$ref": "#/$defs/sequence" - }, - "event_id": { - "$ref": "#/$defs/identifier" - }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { - "$ref": "#/$defs/identifier" - } - }, - "run_id": { - "$ref": "#/$defs/identifier" - }, - "recorded_at": { - "$ref": "#/$defs/timestamp" - }, - "event_type": { - "enum": [ - "run_started", - "initial_state", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_triggered", - "order_cancelled", - "split_applied", - "cash_dividend_applied", - "distribution_applied", - "lifecycle_applied", - "order_adjusted", - "execution_price_selected", - "fill_applied", - "settlement_instruction_created", - "settlement_completed", - "settlement_failed", - "fill_clipped", - "borrow_fee_applied", - "borrow_charge_applied", - "borrow_recall_received", - "cash_interest_applied", - "margin_call", - "margin_restored", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { - "type": "object" - } - }, - "allOf": [ - { - "if": { "properties": { "event_type": { "const": "execution_price_selected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/executionPriceSelected" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_started" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runStarted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "initial_state" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/initialState" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "market_slice_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/marketSlice" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "target_portfolio_requested" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/targetPortfolio" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "order_accepted", - "order_rejected", - "order_triggered" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/order" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_cancelled" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderCancelled" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "split_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/splitApplied" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_dividend_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/dividendApplied" - } - } - } - }, - { - "if": { "properties": { "event_type": { "const": "distribution_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/distributionApplied" } } } - }, - { - "if": { "properties": { "event_type": { "const": "lifecycle_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/lifecycleApplied" } } } - }, - { - "if": { - "properties": { - "event_type": { - "const": "order_adjusted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/orderAdjusted" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fill" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "settlement_instruction_created", - "settlement_completed", - "settlement_failed" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/settlementInstruction" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "fill_clipped" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/fillClipped" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_fee_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowFee" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_charge_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowCharge" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "borrow_recall_received" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/borrowRecall" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "cash_interest_applied" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/cashInterest" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "enum": [ - "margin_call", - "margin_restored", - "valuation" - ] - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/valuation" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "intent_rejected" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/intentRejected" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "metric_emitted" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/metric" - } - } - } - }, - { - "if": { - "properties": { - "event_type": { - "const": "run_completed" - } - } - }, - "then": { - "properties": { - "payload": { - "$ref": "#/$defs/runCompleted" - } - } - } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "nonnegativeSequence": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1", "order_book_v1"] - } - } - }, - "initialState": { - "type": "object", - "additionalProperties": false, - "required": [ - "portfolio", - "valuation" - ], - "properties": { - "portfolio": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/initialPortfolio" - }, - "valuation": { - "$ref": "#/$defs/valuation" - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "open", - "high", - "low", - "close", - "volume" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "open": { - "$ref": "#/$defs/positiveDecimal" - }, - "high": { - "$ref": "#/$defs/positiveDecimal" - }, - "low": { - "$ref": "#/$defs/positiveDecimal" - }, - "close": { - "$ref": "#/$defs/positiveDecimal" - }, - "volume": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/unsignedDecimal" - } - ] - } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "rate" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "rate": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "numerator", - "denominator" - ], - "properties": { - "type": { - "const": "split" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "numerator": { - "$ref": "#/$defs/sequence" - }, - "denominator": { - "$ref": "#/$defs/sequence" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "action_id", - "instrument_id", - "amount_per_unit" - ], - "properties": { - "type": { - "const": "cash_dividend" - }, - "action_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "amount_per_unit": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/fractionalPolicy" } - } - } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars", - "fx_rates", - "corporate_actions", - "borrow_observations", - "cash_rate_observations", - "settlement_failures", - "lifecycle_events", - "market_events", - "order_book_events" - ], - "properties": { - "slice_sequence": { - "$ref": "#/$defs/sequence" - }, - "start_at": { - "$ref": "#/$defs/timestamp" - }, - "end_at": { - "$ref": "#/$defs/timestamp" - }, - "available_at": { - "$ref": "#/$defs/timestamp" - }, - "received_at": { - "$ref": "#/$defs/timestamp" - }, - "bars": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/bar" - } - }, - "fx_rates": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/fxRate" - } - }, - "corporate_actions": { - "type": "array", - "items": { - "$ref": "#/$defs/corporateAction" - } - }, - "borrow_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/borrowObservation" - } - }, - "cash_rate_observations": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/cashRateObservation" - } - }, - "settlement_failures": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/settlementFailure" - } - }, - "lifecycle_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/lifecycleEvent" - } - }, - "market_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/marketEvent" - } - }, - "order_book_events": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/orderBookEvent" - } - } - } - }, - "settlementInstruction": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "fill_id", "instrument_id", "currency", "cash_movement", "position_movement", "trade_date", "due_date", "status", "settled_at", "failed_at", "failure_reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "fill_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "cash_movement": { "$ref": "#/$defs/signedDecimal" }, - "position_movement": { "$ref": "#/$defs/signedDecimal" }, - "trade_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "due_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "status": { "enum": ["pending", "settled", "failed"] }, - "settled_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failed_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, - "failure_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" }] } - } - }, - "targetPortfolio": { - "type": "object", - "additionalProperties": false, - "required": [ - "basis", - "targets" - ], - "properties": { - "basis": { - "enum": [ - "weights", - "quantities" - ] - }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "weight", - "quantity", - "reference_price" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "weight": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "reference_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - } - } - } - } - } - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "trigger_price", - "limit_price", - "time_in_force", - "venue_id", - "calendar_id", - "expires_at", - "origin", - "created_event_id", - "updated_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "triggered_at", - "triggered_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "order_kind": { - "enum": [ - "market", - "limit", - "stop", - "stop_limit" - ] - }, - "trigger_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "limit_price": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/positiveDecimal" - } - ] - }, - "time_in_force": { - "enum": [ - "gtc", - "ioc", - "fok", - "day", - "gtd" - ] - }, - "venue_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "calendar_id": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/identifier" - } - ] - }, - "expires_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "origin": { - "enum": [ - "direct", - "target_rebalance", - "margin_liquidation", - "borrow_recall", - "instrument_halt", - "instrument_terminal" - ] - }, - "created_event_id": { - "$ref": "#/$defs/identifier" - }, - "updated_event_id": { - "$ref": "#/$defs/identifier" - }, - "created_sequence": { - "$ref": "#/$defs/sequence" - }, - "created_at": { - "$ref": "#/$defs/timestamp" - }, - "eligible_after_slice_sequence": { - "$ref": "#/$defs/nonnegativeSequence" - }, - "triggered_at": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/timestamp" - } - ] - }, - "triggered_slice_sequence": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/sequence" - } - ] - }, - "filled_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "filled_notional": { - "$ref": "#/$defs/unsignedDecimal" - }, - "status": { - "enum": [ - "working", - "partially_filled", - "filled", - "cancelled", - "rejected" - ] - }, - "rejection_reason": { - "oneOf": [ - { - "type": "null" - }, - { - "type": "string", - "minLength": 1 - } - ] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "reason" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "reason": { - "enum": [ - "strategy_requested", - "target_replaced", - "market_ioc", - "immediate_or_cancel", - "fill_or_kill", - "day_expired", - "gtd_expired", - "margin_call", - "borrow_recall" - ] - } - } - }, - "splitApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "previous_quantity", - "adjusted_quantity" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "previous_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "adjusted_quantity": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "dividendApplied": { - "type": "object", - "additionalProperties": false, - "required": [ - "action", - "quantity", - "cash_amount" - ], - "properties": { - "action": { - "$ref": "#/$defs/corporateAction" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "distributionApplied": { - "type": "object", - "additionalProperties": false, - "required": ["action", "source_quantity", "destination_quantity", "fractional_quantity", "allocated_basis", "fractional_basis", "cash_in_lieu"], - "properties": { - "action": { "$ref": "#/$defs/corporateAction" }, - "source_quantity": { "$ref": "#/$defs/signedDecimal" }, - "destination_quantity": { "$ref": "#/$defs/signedDecimal" }, - "fractional_quantity": { "$ref": "#/$defs/signedDecimal" }, - "allocated_basis": { "$ref": "#/$defs/signedDecimal" }, - "fractional_basis": { "$ref": "#/$defs/signedDecimal" }, - "cash_in_lieu": { "$ref": "#/$defs/signedDecimal" } - } - }, - "lifecycleApplied": { - "type": "object", - "additionalProperties": false, - "required": ["lifecycle_event", "listing", "liquidated_quantity", "cash_amount"], - "properties": { - "lifecycle_event": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/lifecycleEvent" }, - "listing": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "status", "provider_mappings"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "status": { "enum": ["tradable", "halted", "expired", "delisted"] }, - "provider_mappings": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["provider", "provider_instrument_id"], - "properties": { - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - } - } - } - }, - "liquidated_quantity": { "$ref": "#/$defs/signedDecimal" }, - "cash_amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "orderAdjusted": { - "type": "object", - "additionalProperties": false, - "required": [ - "order", - "action_id" - ], - "properties": { - "order": { - "$ref": "#/$defs/order" - }, - "action_id": { - "$ref": "#/$defs/identifier" - } - } - }, - "executionPriceSelected": { - "type": "object", - "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "reference_price", "spread_adjustment", "impact_adjustment", "final_price"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "reference_price": { "$ref": "#/$defs/positiveDecimal" }, - "spread_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "impact_adjustment": { "$ref": "#/$defs/unsignedDecimal" }, - "final_price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "quote_currency", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence", - "fee_components" - ], - "properties": { - "fill_id": { - "$ref": "#/$defs/identifier" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "side": { - "enum": [ - "buy", - "sell" - ] - }, - "quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - }, - "notional": { - "$ref": "#/$defs/positiveDecimal" - }, - "fee": { - "$ref": "#/$defs/signedDecimal" - }, - "fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/calculatedFeeComponent" - } - }, - "executed_at": { - "$ref": "#/$defs/timestamp" - }, - "slice_sequence": { - "$ref": "#/$defs/sequence" - } - } - }, - "calculatedFeeComponent": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "feeComponentAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "kind", - "currency", - "amount", - "quote_currency", - "quote_amount", - "base_amount" - ], - "properties": { - "name": { - "$ref": "#/$defs/identifier" - }, - "kind": { - "enum": [ - "fixed", - "notional_bps", - "per_unit", - "minimum_adjustment", - "maximum_adjustment" - ] - }, - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quote_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "quantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "moneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "ratioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "basisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "unit", - "value" - ], - "properties": { - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentQuantityThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "quantity" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "instrumentMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "currencyMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "unit", "value"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "money" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "settlementPositionThreshold": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "unit", "value"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "unit": { "const": "quantity" }, - "value": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrumentBasisPointsThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "unit", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "basis_points" - }, - "value": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - } - } - }, - "instrumentShortingThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "value" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "value": { - "const": false - } - } - }, - "groupMoneyThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "money" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "groupRatioThreshold": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "unit", - "value" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "unit": { - "const": "ratio" - }, - "value": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "fillClipReason": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_order_quantity" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_long_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_short_position" - }, - "threshold": { - "$ref": "#/$defs/quantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/moneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "max_leverage" - }, - "threshold": { - "$ref": "#/$defs/ratioThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "initial_margin" - }, - "threshold": { - "$ref": "#/$defs/basisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_long_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_cash_buying_power" }, - "threshold": { "$ref": "#/$defs/currencyMoneyThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["version", "policy", "threshold"], - "properties": { - "version": { "const": "1" }, - "policy": { "const": "settlement_position_availability" }, - "threshold": { "$ref": "#/$defs/settlementPositionThreshold" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_short_position" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_max_notional_exposure" - }, - "threshold": { - "$ref": "#/$defs/instrumentMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_shorting_disabled" - }, - "threshold": { - "$ref": "#/$defs/instrumentShortingThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_borrow_availability" - }, - "threshold": { - "$ref": "#/$defs/instrumentQuantityThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "instrument_initial_margin" - }, - "threshold": { - "$ref": "#/$defs/instrumentBasisPointsThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_gross_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_long_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_short_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_absolute_net_exposure" - }, - "threshold": { - "$ref": "#/$defs/groupMoneyThreshold" - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "version", - "policy", - "threshold" - ], - "properties": { - "version": { - "const": "1" - }, - "policy": { - "const": "group_max_concentration" - }, - "threshold": { - "$ref": "#/$defs/groupRatioThreshold" - } - } - } - ] - }, - "fillClipped": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason", - "order_id", - "instrument_id", - "proposed_quantity", - "permitted_quantity", - "price" - ], - "properties": { - "reason": { - "$ref": "#/$defs/fillClipReason" - }, - "order_id": { - "$ref": "#/$defs/identifier" - }, - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "proposed_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "permitted_quantity": { - "$ref": "#/$defs/unsignedDecimal" - }, - "price": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowFee": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "short_quantity", - "reference_price", - "borrow_bps", - "period_start", - "period_end", - "fee" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "borrow_bps": { - "type": "integer", - "minimum": 1, - "maximum": 10000 - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "fee": { - "$ref": "#/$defs/positiveDecimal" - } - } - }, - "borrowCharge": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "quote_currency", - "short_quantity", - "reference_price", - "day_count", - "compounding", - "period_start", - "period_end", - "amount" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/borrowObservation" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "reference_price": { - "$ref": "#/$defs/positiveDecimal" - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "borrowRecall": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "short_quantity", - "close_out_quantity" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/borrowObservation" - }, - "short_quantity": { - "$ref": "#/$defs/positiveDecimal" - }, - "close_out_quantity": { - "$ref": "#/$defs/unsignedDecimal" - } - } - }, - "cashInterest": { - "type": "object", - "additionalProperties": false, - "required": [ - "observation", - "opening_balance", - "applied_rate_bps", - "day_count", - "compounding", - "period_start", - "period_end", - "amount", - "closing_balance" - ], - "properties": { - "observation": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/cashRateObservation" - }, - "opening_balance": { - "$ref": "#/$defs/signedDecimal" - }, - "applied_rate_bps": { - "type": "integer", - "minimum": -1000000, - "maximum": 1000000 - }, - "day_count": { - "enum": [ - "actual_365", - "actual_360" - ] - }, - "compounding": { - "enum": [ - "simple", - "daily" - ] - }, - "period_start": { - "$ref": "#/$defs/timestamp" - }, - "period_end": { - "$ref": "#/$defs/timestamp" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "closing_balance": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "cashAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "currency", - "amount", - "fx_rate", - "base_value", - "interest", - "base_interest", - "settled_amount", - "unsettled_amount", - "base_settled_value", - "base_unsettled_value" - ], - "properties": { - "currency": { - "$ref": "#/$defs/identifier" - }, - "amount": { - "$ref": "#/$defs/signedDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "base_value": { - "$ref": "#/$defs/signedDecimal" - }, - "interest": { - "$ref": "#/$defs/signedDecimal" - }, - "base_interest": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_amount": { - "$ref": "#/$defs/signedDecimal" - }, - "base_settled_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unsettled_value": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quote_currency", - "quantity", - "settled_quantity", - "unsettled_quantity", - "mark", - "fx_rate", - "market_value", - "base_market_value", - "cost_basis", - "base_cost_basis", - "realized_pnl", - "base_realized_pnl", - "unrealized_pnl", - "base_unrealized_pnl", - "dividend_pnl", - "base_dividend_pnl", - "execution_fees", - "base_execution_fees", - "borrow_fees", - "base_borrow_fees", - "total_fees", - "base_total_fees", - "execution_fee_components" - ], - "properties": { - "instrument_id": { - "$ref": "#/$defs/identifier" - }, - "quote_currency": { - "$ref": "#/$defs/identifier" - }, - "quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_quantity": { - "$ref": "#/$defs/signedDecimal" - }, - "mark": { - "$ref": "#/$defs/positiveDecimal" - }, - "fx_rate": { - "$ref": "#/$defs/positiveDecimal" - }, - "market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "base_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "base_cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "base_dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "base_total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - } - } - }, - "margin": { - "type": "object", - "additionalProperties": false, - "required": [ - "initial_requirement", - "maintenance_requirement", - "initial_excess", - "maintenance_excess", - "margin_call" - ], - "properties": { - "initial_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "maintenance_requirement": { - "$ref": "#/$defs/unsignedDecimal" - }, - "initial_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "maintenance_excess": { - "$ref": "#/$defs/signedDecimal" - }, - "margin_call": { - "type": "boolean" - } - } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": [ - "group_id", - "gross_exposure", - "net_exposure", - "long_exposure", - "short_exposure", - "concentration" - ], - "properties": { - "group_id": { - "$ref": "#/$defs/identifier" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "net_exposure": { - "$ref": "#/$defs/signedDecimal" - }, - "long_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "concentration": { - "oneOf": [ - { - "type": "null" - }, - { - "$ref": "#/$defs/signedDecimal" - } - ] - } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "base_currency", - "cash", - "settled_cash", - "unsettled_cash", - "net_market_value", - "long_market_value", - "short_market_value", - "gross_exposure", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "dividend_pnl", - "execution_fees", - "borrow_fees", - "cash_interest", - "total_fees", - "cash_balances", - "positions", - "margin", - "group_exposures", - "execution_fee_components" - ], - "properties": { - "base_currency": { - "$ref": "#/$defs/identifier" - }, - "cash": { - "$ref": "#/$defs/signedDecimal" - }, - "settled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "unsettled_cash": { - "$ref": "#/$defs/signedDecimal" - }, - "net_market_value": { - "$ref": "#/$defs/signedDecimal" - }, - "long_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "short_market_value": { - "$ref": "#/$defs/unsignedDecimal" - }, - "gross_exposure": { - "$ref": "#/$defs/unsignedDecimal" - }, - "cost_basis": { - "$ref": "#/$defs/signedDecimal" - }, - "realized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "unrealized_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "equity": { - "$ref": "#/$defs/signedDecimal" - }, - "dividend_pnl": { - "$ref": "#/$defs/signedDecimal" - }, - "execution_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "borrow_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "total_fees": { - "$ref": "#/$defs/signedDecimal" - }, - "cash_balances": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#/$defs/cashAttribution" - } - }, - "positions": { - "type": "array", - "items": { - "$ref": "#/$defs/positionAttribution" - } - }, - "margin": { - "$ref": "#/$defs/margin" - }, - "group_exposures": { - "type": "array", - "items": { - "$ref": "#/$defs/groupExposure" - } - }, - "execution_fee_components": { - "type": "array", - "items": { - "$ref": "#/$defs/feeComponentAttribution" - } - }, - "cash_interest": { - "$ref": "#/$defs/signedDecimal" - } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": [ - "reason" - ], - "properties": { - "reason": { - "type": "string", - "minLength": 1 - } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": [ - "name", - "value" - ], - "properties": { - "name": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^\\S(?:.*\\S)?$" }, - "value": { "$ref": "#/$defs/metricValue" }, - "unit": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, - "dimensions": { - "type": "object", - "maxProperties": 16, - "propertyNames": { "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, - "additionalProperties": { "type": "string", "maxLength": 128 } - }, - "aggregation": { "enum": ["last", "sum", "minimum", "maximum", "mean"] } - }, - "allOf": [ - { "if": { "properties": { "value": { "properties": { "type": { "enum": ["string", "boolean"] } } } } }, "then": { "properties": { "aggregation": { "enum": ["last"] } } } } - ] - }, - "metricValue": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "numeric" }, "value": { "type": "string", "pattern": "^(0|[1-9][0-9]*|-[1-9][0-9]*)(\\.[0-9]*[1-9])?$|^-0\\.[0-9]*[1-9]$" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "string" }, "value": { "type": "string", "maxLength": 1024 } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "boolean" }, "value": { "type": "boolean" } } } - ] - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { - "type": "string", - "pattern": "^[0-9a-f]{64}$" - }, - "execution_model": { - "enum": ["completed_bar_v1", "completed_bar_next_open_v1", "completed_bar_adverse_touch_v1", "quote_trade_v1", "order_book_v1"] - }, - "valuation": { - "$ref": "#/$defs/valuation" - }, - "order_counts": { - "type": "object", - "additionalProperties": false, - "required": [ - "total", - "active", - "filled", - "rejected", - "cancelled" - ], - "properties": { - "total": { - "type": "integer", - "minimum": 0 - }, - "active": { - "type": "integer", - "minimum": 0 - }, - "filled": { - "type": "integer", - "minimum": 0 - }, - "rejected": { - "type": "integer", - "minimum": 0 - }, - "cancelled": { - "type": "integer", - "minimum": 0 - } - } - } - } - } - } -} diff --git a/contracts/v16/scenario-stream.schema.json b/contracts/v16/scenario-stream.schema.json deleted file mode 100644 index e3b1694..0000000 --- a/contracts/v16/scenario-stream.schema.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v16/scenario-stream.schema.json", - "title": "Trading Engine v16 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "16" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "16" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "16" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/execution" }, - "financing": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/financing" }, - "settlement": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v16/scenario.schema.json b/contracts/v16/scenario.schema.json deleted file mode 100644 index 1af81e1..0000000 --- a/contracts/v16/scenario.schema.json +++ /dev/null @@ -1,888 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v16/scenario.schema.json", - "title": "Trading Engine v16 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "financing", "settlement", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "16" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "financing": { "$ref": "#/$defs/financing" }, - "settlement": { "$ref": "#/$defs/settlement" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "settlement": { - "type": "object", - "additionalProperties": false, - "required": ["cash_buying_power", "position_availability", "calendars", "rules"], - "properties": { - "cash_buying_power": { "enum": ["total_cash", "settled_cash"] }, - "position_availability": { "enum": ["total_positions", "settled_positions"] }, - "calendars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementCalendar" } }, - "rules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/settlementRule" } } - } - }, - "settlementCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "version", "business_dates"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "version": { "const": "1" }, - "business_dates": { "type": "array", "minItems": 1, "uniqueItems": true, "items": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" } } - } - }, - "settlementRule": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "calendar_id", "lag_business_days"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "calendar_id": { "$ref": "#/$defs/identifier" }, - "lag_business_days": { "type": "integer", "minimum": 0, "maximum": 30 } - } - }, - "settlementFailure": { - "type": "object", - "additionalProperties": false, - "required": ["instruction_id", "reason"], - "properties": { - "instruction_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1, "pattern": "^\\S(?:.*\\S)?$" } - } - }, - "financing": { - "type": "object", - "additionalProperties": false, - "required": ["day_count", "compounding", "borrow_missing_data", "cash_missing_data", "locate_policy", "recall_policy"], - "properties": { - "day_count": { "enum": ["actual_365", "actual_360"] }, - "compounding": { "enum": ["simple", "daily"] }, - "borrow_missing_data": { "enum": ["reject", "zero"] }, - "cash_missing_data": { "enum": ["reject", "zero"] }, - "locate_policy": { "enum": ["reject_order", "clip_fill"] }, - "recall_policy": { "enum": ["reject_new_shorts", "close_out"] } - } - }, - "borrowObservation": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "effective_at", "available_quantity", "annual_rate_bps", "recalled"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "available_quantity": { "$ref": "#/$defs/unsignedDecimal" }, - "annual_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "recalled": { "type": "boolean" } - } - }, - "cashRateObservation": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "effective_at", "credit_rate_bps", "debit_rate_bps"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "effective_at": { "$ref": "#/$defs/timestamp" }, - "credit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 }, - "debit_rate_bps": { "type": "integer", "minimum": -1000000, "maximum": 1000000 } - } - }, - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "enum": ["completed_bar_next_open_v1", "completed_bar_adverse_touch_v1"] }, - "configuration": { "$ref": "#/$defs/conservativeBarConfiguration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "quote_trade_v1" }, - "configuration": { "$ref": "#/$defs/quoteTradeConfiguration" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "order_book_v1" }, - "configuration": { "$ref": "#/$defs/orderBookConfiguration" } - } - } - ] - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "conservativeBarConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules", "spread_model", "impact_model"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, - "spread_model": { "$ref": "#/$defs/fixedSpreadModel" }, - "impact_model": { "$ref": "#/$defs/linearImpactModel" } - } - }, - "quoteTradeConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "orderBookConfiguration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules", "max_depth_levels"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } }, - "max_depth_levels": { "type": "integer", "minimum": 1, "maximum": 1024 } - } - }, - "fixedSpreadModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "half_spread_bps"], - "properties": { - "model": { "const": "fixed_half_spread_v1" }, - "half_spread_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "linearImpactModel": { - "type": "object", - "additionalProperties": false, - "required": ["model", "coefficient_bps", "missing_volume_policy"], - "properties": { - "model": { "const": "linear_participation_v1" }, - "coefficient_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "missing_volume_policy": { "enum": ["reject", "zero_impact"] } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^\\S(?:.*\\S)?$" }, - "value": { "$ref": "#/$defs/metricValue" }, - "unit": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, - "dimensions": { - "type": "object", - "maxProperties": 16, - "propertyNames": { "minLength": 1, "maxLength": 64, "pattern": "^\\S(?:.*\\S)?$" }, - "additionalProperties": { "type": "string", "maxLength": 128 } - }, - "aggregation": { "enum": ["last", "sum", "minimum", "maximum", "mean"] } - }, - "allOf": [ - { "if": { "properties": { "value": { "properties": { "type": { "enum": ["string", "boolean"] } } } } }, "then": { "properties": { "aggregation": { "enum": ["last"] } } } } - ] - }, - "metricValue": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "numeric" }, "value": { "type": "string", "pattern": "^(0|[1-9][0-9]*|-[1-9][0-9]*)(\\.[0-9]*[1-9])?$|^-0\\.[0-9]*[1-9]$" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "string" }, "value": { "type": "string", "maxLength": 1024 } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "value"], "properties": { "type": { "const": "boolean" }, "value": { "type": "boolean" } } } - ] - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "market_events", "order_book_events", "fx_rates", "corporate_actions", "borrow_observations", "cash_rate_observations", "settlement_failures", "lifecycle_events"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "market_events": { "type": "array", "items": { "$ref": "#/$defs/marketEvent" } }, - "order_book_events": { "type": "array", "items": { "$ref": "#/$defs/orderBookEvent" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }, - "borrow_observations": { "type": "array", "items": { "$ref": "#/$defs/borrowObservation" } }, - "cash_rate_observations": { "type": "array", "items": { "$ref": "#/$defs/cashRateObservation" } }, - "settlement_failures": { "type": "array", "items": { "$ref": "#/$defs/settlementFailure" } }, - "lifecycle_events": { "type": "array", "items": { "$ref": "#/$defs/lifecycleEvent" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "marketEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "bid_price", "bid_quantity", "ask_price", "ask_quantity"], - "properties": { - "type": { "const": "quote" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "bid_price": { "$ref": "#/$defs/positiveDecimal" }, - "bid_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "ask_price": { "$ref": "#/$defs/positiveDecimal" }, - "ask_quantity": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "price", "quantity", "aggressor_side"], - "properties": { - "type": { "const": "trade" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "aggressor_side": { "enum": ["buy", "sell", "unknown"] } - } - } - ] - }, - "orderBookLevel": { - "type": "object", - "additionalProperties": false, - "required": ["price", "quantity"], - "properties": { - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "orderBookEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "bids", "asks"], - "properties": { - "type": { "const": "snapshot" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "bids": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/orderBookLevel" } }, - "asks": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/orderBookLevel" } } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "side", "price", "quantity"], - "properties": { - "type": { "const": "set" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "side": { "enum": ["bid", "ask"] }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "side", "price"], - "properties": { - "type": { "const": "delete" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "side": { "enum": ["bid", "ask"] }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "event_at", "available_at", "received_at", "ingest_sequence", "book_sequence", "price", "quantity", "aggressor_side"], - "properties": { - "type": { "const": "trade" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "event_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "ingest_sequence": { "$ref": "#/$defs/sequence" }, - "book_sequence": { "$ref": "#/$defs/sequence" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "aggressor_side": { "enum": ["buy", "sell", "unknown"] } - } - } - ] - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "destination_instrument_id", "numerator", "denominator", "basis_allocation_bps", "fractional_policy"], - "properties": { - "type": { "enum": ["stock_dividend", "rights", "spin_off"] }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "destination_instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" }, - "basis_allocation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fractional_policy": { "$ref": "#/$defs/fractionalPolicy" } - } - } - ] - }, - "fractionalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "reject" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_in_lieu" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "terminalPolicy": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["policy"], - "properties": { "policy": { "const": "hold" } } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["policy", "price", "currency"], - "properties": { - "policy": { "const": "cash_out" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "currency": { "$ref": "#/$defs/identifier" } - } - } - ] - }, - "lifecycleEvent": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "reason"], - "properties": { - "type": { "const": "halt" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "reason": { "type": "string", "minLength": 1 } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id"], - "properties": { - "type": { "const": "resume" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "symbol", "provider", "provider_instrument_id"], - "properties": { - "type": { "const": "identifier_change" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "provider": { "$ref": "#/$defs/identifier" }, - "provider_instrument_id": { "$ref": "#/$defs/identifier" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy"], - "properties": { - "type": { "const": "expiration" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "event_id", "instrument_id", "terminal_policy", "reason"], - "properties": { - "type": { "const": "delisting" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "terminal_policy": { "$ref": "#/$defs/terminalPolicy" }, - "reason": { "type": "string", "minLength": 1 } - } - } - ] - } - } -} diff --git a/contracts/v2/README.md b/contracts/v2/README.md deleted file mode 100644 index 06dd6f3..0000000 --- a/contracts/v2/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Trading Engine contract v2 - -This frozen directory preserves the historical v2 process and file contract. The current runtime -advertises v4 and v3 only; these artifacts remain available for provenance and schema-only -compatibility testing by older consumers. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- `fixtures/demo.scenario.json`, `fixtures/demo.scenario.jsonl`, and - `fixtures/demo.journal.jsonl` form the canonical valid conformance corpus. - -Every batch scenario, scenario-stream record, and journal record carries -`"contract_version": "2"`. Consumers must reject missing or unsupported versions before -interpreting the rest of a document. - -Version 2 adds an explicit scenario execution-model selection. Every audit record also carries a -deterministic `event_id` and an ordered list of prior `causation_ids`. Valuations contain -per-instrument position attribution that reconciles exactly to their aggregate market value, cost -basis, realized and unrealized P&L, and fees. diff --git a/contracts/v2/dune b/contracts/v2/dune deleted file mode 100644 index 3ec9298..0000000 --- a/contracts/v2/dune +++ /dev/null @@ -1,10 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v2/journal.schema.json) - (scenario-stream.schema.json as contracts/v2/scenario-stream.schema.json) - (scenario.schema.json as contracts/v2/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v2/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v2/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v2/fixtures/demo.scenario.jsonl))) diff --git a/contracts/v2/fixtures/demo.journal.jsonl b/contracts/v2/fixtures/demo.journal.jsonl deleted file mode 100644 index a6232a7..0000000 --- a/contracts/v2/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,20 +0,0 @@ -{"contract_version":"2","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"21834e964dd6daab292e6285924384970b3341f7166ead1d38f8edb284541e44","execution_model":"completed_bar_v1"}} -{"contract_version":"2","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}]}} -{"contract_version":"2","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9","reference_price":"104"}]}} -{"contract_version":"2","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"2","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000002","demo-event-000000000003"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"2","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"10000","market_value":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"10000","total_fees":"0","positions":[{"instrument_id":"demo-equity-acme","quantity":"0","mark":"104","market_value":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","total_fees":"0"}]}} -{"contract_version":"2","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}]}} -{"contract_version":"2","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"2","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"2","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000003","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"3","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000010","created_sequence":"10","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"2","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"9381.132","market_value":"642","cost_basis":"618.868","realized_pnl":"0","unrealized_pnl":"23.132","equity":"10023.132","total_fees":"0.868","positions":[{"instrument_id":"demo-equity-acme","quantity":"6","mark":"107","market_value":"642","cost_basis":"618.868","realized_pnl":"0","unrealized_pnl":"23.132","total_fees":"0.868"}]}} -{"contract_version":"2","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}]}} -{"contract_version":"2","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000010","demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"3","price":"107","notional":"321","fee":"0.571","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"2","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2","reference_price":null}]}} -{"contract_version":"2","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"2","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"9059.561","market_value":"945","cost_basis":"940.439","realized_pnl":"0","unrealized_pnl":"4.561","equity":"10004.561","total_fees":"1.439","positions":[{"instrument_id":"demo-equity-acme","quantity":"9","mark":"105","market_value":"945","cost_basis":"940.439","realized_pnl":"0","unrealized_pnl":"4.561","total_fees":"1.439"}]}} -{"contract_version":"2","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}]}} -{"contract_version":"2","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7","price":"105","notional":"735","fee":"0.985","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"2","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"cash":"9793.576","market_value":"212","cost_basis":"208.986445","realized_pnl":"2.562445","unrealized_pnl":"3.013555","equity":"10005.576","total_fees":"2.424","positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"106","market_value":"212","cost_basis":"208.986445","realized_pnl":"2.562445","unrealized_pnl":"3.013555","total_fees":"2.424"}]}} -{"contract_version":"2","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"21834e964dd6daab292e6285924384970b3341f7166ead1d38f8edb284541e44","execution_model":"completed_bar_v1","valuation":{"cash":"9793.576","market_value":"212","cost_basis":"208.986445","realized_pnl":"2.562445","unrealized_pnl":"3.013555","equity":"10005.576","total_fees":"2.424","positions":[{"instrument_id":"demo-equity-acme","quantity":"2","mark":"106","market_value":"212","cost_basis":"208.986445","realized_pnl":"2.562445","unrealized_pnl":"3.013555","total_fees":"2.424"}]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v2/fixtures/demo.scenario.json b/contracts/v2/fixtures/demo.scenario.json deleted file mode 100644 index 898011a..0000000 --- a/contracts/v2/fixtures/demo.scenario.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "contract_version": "2", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_cash": "10000", - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "risk": { - "max_order_quantity": "1000", - "max_position": "1000" - }, - "execution": { - "model": "completed_bar_v1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ] - } - ] -} diff --git a/contracts/v2/fixtures/demo.scenario.jsonl b/contracts/v2/fixtures/demo.scenario.jsonl deleted file mode 100644 index 399b062..0000000 --- a/contracts/v2/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"2","payload":{"base_currency":"USD","execution":{"fee_bps":10,"fixed_fee":"0.25","model":"completed_bar_v1","participation_bps":5000},"initial_cash":"10000","instruments":[{"instrument_id":"demo-equity-acme","lot_size":"1","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"max_internal_events":1000,"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"risk":{"max_order_quantity":"1000","max_position":"1000"},"run_id":"demo"},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"2","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"end_at":"2026-01-02T21:00:00Z","received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"2","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"end_at":"2026-01-05T21:00:00Z","received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"2","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"end_at":"2026-01-06T21:00:00Z","received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"2","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"end_at":"2026-01-07T21:00:00Z","received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"2","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v2/journal.schema.json b/contracts/v2/journal.schema.json deleted file mode 100644 index b2f9327..0000000 --- a/contracts/v2/journal.schema.json +++ /dev/null @@ -1,431 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v2/journal.schema.json", - "title": "Trading Engine v2 audit journal record", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "engine_sequence", - "event_id", - "causation_ids", - "run_id", - "recorded_at", - "event_type", - "payload" - ], - "properties": { - "contract_version": { "const": "2" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { - "type": "array", - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": [ - "run_started", - "market_slice_received", - "target_portfolio_requested", - "order_accepted", - "order_rejected", - "order_cancelled", - "fill_applied", - "cash_limited", - "intent_rejected", - "metric_emitted", - "valuation", - "run_completed" - ] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { - "if": { "properties": { "event_type": { "const": "run_started" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } - }, - { - "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } - }, - { - "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } - }, - { - "if": { "properties": { "event_type": { "const": "order_accepted" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } - }, - { - "if": { "properties": { "event_type": { "const": "order_rejected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } - }, - { - "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } - }, - { - "if": { "properties": { "event_type": { "const": "fill_applied" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } - }, - { - "if": { "properties": { "event_type": { "const": "cash_limited" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/cashLimited" } } } - }, - { - "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } - }, - { - "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } - }, - { - "if": { "properties": { "event_type": { "const": "valuation" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } - }, - { - "if": { "properties": { "event_type": { "const": "run_completed" } } }, - "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } - } - ], - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)(?:[.][0-9]{0,5}[1-9])?$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0(?:[.][0-9]{0,5}[1-9])?|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?|-(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "weight": { - "type": "string", - "pattern": "^(?:0(?:[.][0-9]{0,5}[1-9])?|1)$" - }, - "quantity": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "positiveQuantity": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, - "executionModel": { "const": "completed_bar_v1" }, - "runStarted": { - "type": "object", - "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { - "scenario_sha256": { "$ref": "#/$defs/sha256" }, - "execution_model": { "$ref": "#/$defs/executionModel" } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { - "oneOf": [ - { "$ref": "#/$defs/quantity" }, - { "type": "null" } - ] - } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars" - ], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/bar" } - } - } - }, - "requestedWeightTarget": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight", "quantity", "reference_price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/weight" }, - "quantity": { "$ref": "#/$defs/quantity" }, - "reference_price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "requestedQuantityTarget": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight", "quantity", "reference_price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "type": "null" }, - "quantity": { "$ref": "#/$defs/quantity" }, - "reference_price": { "type": "null" } - } - }, - "targetPortfolio": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["basis", "targets"], - "properties": { - "basis": { "const": "weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/requestedWeightTarget" } - } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["basis", "targets"], - "properties": { - "basis": { "const": "quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/requestedQuantityTarget" } - } - } - } - ] - }, - "order": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "side", - "quantity", - "order_kind", - "limit_price", - "origin", - "created_event_id", - "created_sequence", - "created_at", - "eligible_after_slice_sequence", - "filled_quantity", - "filled_notional", - "status", - "rejection_reason" - ], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveQuantity" }, - "order_kind": { "enum": ["market", "limit"] }, - "limit_price": { - "oneOf": [ - { "$ref": "#/$defs/positiveDecimal" }, - { "type": "null" } - ] - }, - "origin": { "enum": ["direct", "target_rebalance"] }, - "created_event_id": { "$ref": "#/$defs/identifier" }, - "created_sequence": { "$ref": "#/$defs/sequence" }, - "created_at": { "$ref": "#/$defs/timestamp" }, - "eligible_after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "filled_quantity": { "$ref": "#/$defs/quantity" }, - "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, - "status": { - "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] - }, - "rejection_reason": { - "oneOf": [{ "type": "string" }, { "type": "null" }] - } - } - }, - "orderCancelled": { - "type": "object", - "additionalProperties": false, - "required": ["order", "reason"], - "properties": { - "order": { "$ref": "#/$defs/order" }, - "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc"] } - } - }, - "fill": { - "type": "object", - "additionalProperties": false, - "required": [ - "fill_id", - "order_id", - "instrument_id", - "side", - "quantity", - "price", - "notional", - "fee", - "executed_at", - "slice_sequence" - ], - "properties": { - "fill_id": { "$ref": "#/$defs/identifier" }, - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveQuantity" }, - "price": { "$ref": "#/$defs/positiveDecimal" }, - "notional": { "$ref": "#/$defs/unsignedDecimal" }, - "fee": { "$ref": "#/$defs/unsignedDecimal" }, - "executed_at": { "$ref": "#/$defs/timestamp" }, - "slice_sequence": { "$ref": "#/$defs/sequence" } - } - }, - "cashLimited": { - "type": "object", - "additionalProperties": false, - "required": [ - "order_id", - "instrument_id", - "requested_quantity", - "affordable_quantity", - "price" - ], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "requested_quantity": { "$ref": "#/$defs/positiveQuantity" }, - "affordable_quantity": { "$ref": "#/$defs/quantity" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "intentRejected": { - "type": "object", - "additionalProperties": false, - "required": ["reason"], - "properties": { "reason": { "type": "string", "minLength": 1 } } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["name", "value"], - "properties": { - "name": { "type": "string", "minLength": 1 }, - "value": { "type": "string" } - } - }, - "positionAttribution": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "quantity", - "mark", - "market_value", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "total_fees" - ], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/quantity" }, - "mark": { "$ref": "#/$defs/positiveDecimal" }, - "market_value": { "$ref": "#/$defs/unsignedDecimal" }, - "cost_basis": { "$ref": "#/$defs/unsignedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "total_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "valuation": { - "type": "object", - "additionalProperties": false, - "required": [ - "cash", - "market_value", - "cost_basis", - "realized_pnl", - "unrealized_pnl", - "equity", - "total_fees", - "positions" - ], - "properties": { - "cash": { "$ref": "#/$defs/unsignedDecimal" }, - "market_value": { "$ref": "#/$defs/unsignedDecimal" }, - "cost_basis": { "$ref": "#/$defs/unsignedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "equity": { "$ref": "#/$defs/unsignedDecimal" }, - "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "positions": { - "type": "array", - "items": { "$ref": "#/$defs/positionAttribution" } - } - } - }, - "orderCounts": { - "type": "object", - "additionalProperties": false, - "required": ["total", "active", "filled", "rejected", "cancelled"], - "properties": { - "total": { "type": "integer", "minimum": 0 }, - "active": { "type": "integer", "minimum": 0 }, - "filled": { "type": "integer", "minimum": 0 }, - "rejected": { "type": "integer", "minimum": 0 }, - "cancelled": { "type": "integer", "minimum": 0 } - } - }, - "runCompleted": { - "type": "object", - "additionalProperties": false, - "required": [ - "scenario_sha256", - "execution_model", - "valuation", - "order_counts" - ], - "properties": { - "scenario_sha256": { "$ref": "#/$defs/sha256" }, - "execution_model": { "$ref": "#/$defs/executionModel" }, - "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "$ref": "#/$defs/orderCounts" } - } - } - } -} diff --git a/contracts/v2/scenario-stream.schema.json b/contracts/v2/scenario-stream.schema.json deleted file mode 100644 index 6f63da0..0000000 --- a/contracts/v2/scenario-stream.schema.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v2/scenario-stream.schema.json", - "title": "Trading Engine v2 replay scenario stream record", - "description": "The structural contract for one v2 record in a bounded-memory JSON Lines replay scenario. The engine additionally checks record order, terminal counts, model support, catalog coverage, market ordering, causality, risk, tick, lot, time, and OHLC invariants.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "scenario_sequence", - "record_type", - "payload" - ], - "properties": { - "contract_version": { "const": "2" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "scenario_sequence", - "record_type", - "payload" - ], - "properties": { - "contract_version": { "const": "2" }, - "scenario_sequence": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/sequence" - }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "scenario_sequence", - "record_type", - "payload" - ], - "properties": { - "contract_version": { "const": "2" }, - "scenario_sequence": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/sequence" - }, - "record_type": { "const": "scenario_end" }, - "payload": { "$ref": "#/$defs/endPayload" } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": [ - "metadata", - "run_id", - "base_currency", - "initial_cash", - "instruments", - "risk", - "execution", - "max_internal_events" - ], - "properties": { - "metadata": { "type": "object" }, - "run_id": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/identifier" - }, - "base_currency": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/identifier" - }, - "initial_cash": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/unsignedDecimal" - }, - "instruments": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/instrument" - } - }, - "risk": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/risk" - }, - "execution": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/execution" - }, - "max_internal_events": { "type": "integer", "minimum": 1 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/marketSlice" - }, - "intents": { - "type": "array", - "items": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/intent" - } - } - } - }, - "endPayload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { - "slice_count": { - "$ref": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json#/$defs/quantity" - } - } - } - } -} diff --git a/contracts/v2/scenario.schema.json b/contracts/v2/scenario.schema.json deleted file mode 100644 index 0322b8c..0000000 --- a/contracts/v2/scenario.schema.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v2/scenario.schema.json", - "title": "Trading Engine v2 replay scenario", - "description": "The strict structural input contract. The engine additionally checks catalog coverage, ordering, causality, risk, tick, lot, time, and OHLC invariants.", - "type": "object", - "additionalProperties": false, - "required": [ - "contract_version", - "metadata", - "run_id", - "base_currency", - "initial_cash", - "instruments", - "risk", - "execution", - "max_internal_events", - "schedule", - "slices" - ], - "properties": { - "contract_version": { "const": "2" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_cash": { "$ref": "#/$defs/unsignedDecimal" }, - "instruments": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrument" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1 }, - "schedule": { - "type": "array", - "items": { "$ref": "#/$defs/scheduleItem" } - }, - "slices": { - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)(?:[.][0-9]{0,5}[1-9])?$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "weight": { - "type": "string", - "pattern": "^(?:0(?:[.][0-9]{0,5}[1-9])?|1)$" - }, - "quantity": { - "type": "string", - "pattern": "^(?:0|[1-9][0-9]*)$" - }, - "positiveQuantity": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "sequence": { - "type": "string", - "pattern": "^[1-9][0-9]*$" - }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": [ - "instrument_id", - "symbol", - "quote_currency", - "tick_size", - "lot_size" - ], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveQuantity" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_order_quantity", "max_position"], - "properties": { - "max_order_quantity": { "$ref": "#/$defs/positiveQuantity" }, - "max_position": { "$ref": "#/$defs/positiveQuantity" } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "participation_bps", "fixed_fee", "fee_bps"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "participation_bps": { - "type": "integer", - "minimum": 0, - "maximum": 10000 - }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { - "type": "array", - "items": { "$ref": "#/$defs/intent" } - } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeightsIntent" }, - { "$ref": "#/$defs/targetQuantitiesIntent" }, - { "$ref": "#/$defs/marketOrderIntent" }, - { "$ref": "#/$defs/limitOrderIntent" }, - { "$ref": "#/$defs/cancelOrderIntent" }, - { "$ref": "#/$defs/metricIntent" } - ] - }, - "targetWeightsIntent": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/weightTarget" } - } - } - }, - "weightTarget": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/weight" } - } - }, - "targetQuantitiesIntent": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/quantityTarget" } - } - } - }, - "quantityTarget": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/quantity" } - } - }, - "orderFields": { - "type": "object", - "required": [ - "type", - "instrument_id", - "side", - "quantity", - "order_kind", - "limit_price" - ], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveQuantity" } - } - }, - "marketOrderIntent": { - "allOf": [ - { "$ref": "#/$defs/orderFields" }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "instrument_id", - "side", - "quantity", - "order_kind", - "limit_price" - ], - "properties": { - "type": true, - "instrument_id": true, - "side": true, - "quantity": true, - "order_kind": { "const": "market" }, - "limit_price": { "type": "null" } - } - } - ] - }, - "limitOrderIntent": { - "allOf": [ - { "$ref": "#/$defs/orderFields" }, - { - "type": "object", - "additionalProperties": false, - "required": [ - "type", - "instrument_id", - "side", - "quantity", - "order_kind", - "limit_price" - ], - "properties": { - "type": true, - "instrument_id": true, - "side": true, - "quantity": true, - "order_kind": { "const": "limit" }, - "limit_price": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - }, - "cancelOrderIntent": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metricIntent": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": [ - "slice_sequence", - "start_at", - "end_at", - "available_at", - "received_at", - "bars" - ], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/bar" } - } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { - "oneOf": [ - { "$ref": "#/$defs/quantity" }, - { "type": "null" } - ] - } - } - } - } -} diff --git a/contracts/v3/README.md b/contracts/v3/README.md deleted file mode 100644 index f667908..0000000 --- a/contracts/v3/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Trading Engine contract v3 - -This directory is the authoritative v3 process and file contract shared by Trading Engine and -its clients. Version 2 remains frozen under `contracts/v2`. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. - -Version 3 adds exact six-decimal quantities, signed targets and positions, explicit per-currency -cash and FX marks, splits and cash dividends, borrow costs, exposure and margin policy, and causal -margin-call/liquidation events. Every v3 scenario, stream record, and journal record carries -`"contract_version": "3"`; consumers reject missing or unsupported versions before interpreting -the remainder of a document. diff --git a/contracts/v3/dune b/contracts/v3/dune deleted file mode 100644 index 55cb489..0000000 --- a/contracts/v3/dune +++ /dev/null @@ -1,10 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v3/journal.schema.json) - (scenario-stream.schema.json as contracts/v3/scenario-stream.schema.json) - (scenario.schema.json as contracts/v3/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v3/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v3/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v3/fixtures/demo.scenario.jsonl))) diff --git a/contracts/v3/fixtures/demo.journal.jsonl b/contracts/v3/fixtures/demo.journal.jsonl deleted file mode 100644 index 475885a..0000000 --- a/contracts/v3/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,20 +0,0 @@ -{"contract_version":"3","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"3e19fa66bc6425bb8ed7a89b338080a831dd39ea778c3c7f9e8ce1d3370fbee0","execution_model":"completed_bar_v1"}} -{"contract_version":"3","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"3","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.615","reference_price":"104"}]}} -{"contract_version":"3","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"3","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000002","demo-event-000000000003"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","updated_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"3","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"10000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"0","mark":"104","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"10000","maintenance_excess":"10000","margin_call":false}}} -{"contract_version":"3","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"3","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"3","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","updated_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"3","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000003","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"3.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000010","updated_event_id":"demo-event-000000000010","created_sequence":"10","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"3","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.132","net_market_value":"642","long_market_value":"642","short_market_value":"0","gross_exposure":"642","cost_basis":"618.868","realized_pnl":"0","unrealized_pnl":"23.132","equity":"10023.132","dividend_pnl":"0","execution_fees":"0.868","borrow_fees":"0","total_fees":"0.868","cash_balances":[{"currency":"USD","amount":"9381.132","fx_rate":"1","base_value":"9381.132"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"6","mark":"107","fx_rate":"1","market_value":"642","base_market_value":"642","cost_basis":"618.868","base_cost_basis":"618.868","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"23.132","base_unrealized_pnl":"23.132","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0.868","base_execution_fees":"0.868","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0.868","base_total_fees":"0.868"}],"margin":{"initial_requirement":"321","maintenance_requirement":"160.5","initial_excess":"9702.132","maintenance_excess":"9862.632","margin_call":false}}} -{"contract_version":"3","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"3","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000010","demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"3.615","price":"107","notional":"386.805","fee":"0.636805","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"3","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"3","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.115","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"3","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"8993.690195","net_market_value":"1009.575","long_market_value":"1009.575","short_market_value":"0","gross_exposure":"1009.575","cost_basis":"1006.309805","realized_pnl":"0","unrealized_pnl":"3.265195","equity":"10003.265195","dividend_pnl":"0","execution_fees":"1.504805","borrow_fees":"0","total_fees":"1.504805","cash_balances":[{"currency":"USD","amount":"8993.690195","fx_rate":"1","base_value":"8993.690195"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.615","mark":"105","fx_rate":"1","market_value":"1009.575","base_market_value":"1009.575","cost_basis":"1006.309805","base_cost_basis":"1006.309805","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"3.265195","base_unrealized_pnl":"3.265195","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"1.504805","base_execution_fees":"1.504805","borrow_fees":"0","base_borrow_fees":"0","total_fees":"1.504805","base_total_fees":"1.504805"}],"margin":{"initial_requirement":"504.7875","maintenance_requirement":"252.39375","initial_excess":"9498.477695","maintenance_excess":"9750.871445","margin_call":false}}} -{"contract_version":"3","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"3","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.115","price":"105","notional":"747.075","fee":"0.997075","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"3","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9739.76812","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"261.651016","realized_pnl":"1.419136","unrealized_pnl":"3.348984","equity":"10004.76812","dividend_pnl":"0","execution_fees":"2.50188","borrow_fees":"0","total_fees":"2.50188","cash_balances":[{"currency":"USD","amount":"9739.76812","fx_rate":"1","base_value":"9739.76812"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"261.651016","base_cost_basis":"261.651016","realized_pnl":"1.419136","base_realized_pnl":"1.419136","unrealized_pnl":"3.348984","base_unrealized_pnl":"3.348984","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"2.50188","base_execution_fees":"2.50188","borrow_fees":"0","base_borrow_fees":"0","total_fees":"2.50188","base_total_fees":"2.50188"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9872.26812","maintenance_excess":"9938.51812","margin_call":false}}} -{"contract_version":"3","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"3e19fa66bc6425bb8ed7a89b338080a831dd39ea778c3c7f9e8ce1d3370fbee0","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9739.76812","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"261.651016","realized_pnl":"1.419136","unrealized_pnl":"3.348984","equity":"10004.76812","dividend_pnl":"0","execution_fees":"2.50188","borrow_fees":"0","total_fees":"2.50188","cash_balances":[{"currency":"USD","amount":"9739.76812","fx_rate":"1","base_value":"9739.76812"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"261.651016","base_cost_basis":"261.651016","realized_pnl":"1.419136","base_realized_pnl":"1.419136","unrealized_pnl":"3.348984","base_unrealized_pnl":"3.348984","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"2.50188","base_execution_fees":"2.50188","borrow_fees":"0","base_borrow_fees":"0","total_fees":"2.50188","base_total_fees":"2.50188"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9872.26812","maintenance_excess":"9938.51812","margin_call":false}},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v3/fixtures/demo.scenario.json b/contracts/v3/fixtures/demo.scenario.json deleted file mode 100644 index d6ac1fa..0000000 --- a/contracts/v3/fixtures/demo.scenario.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "contract_version": "3", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "10000" } - ], - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000", - "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 100 - }, - "execution": { - "model": "completed_bar_v1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { "instrument_id": "demo-equity-acme", "weight": "0.1" } - ] - }, - { "type": "emit_metric", "name": "desired_weight", "value": "0.1" } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { "instrument_id": "demo-equity-acme", "quantity": "2.5" } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "100", "high": "105", "low": "99", "close": "104", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "103", "high": "108", "low": "102", "close": "107", "volume": "12" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "107", "high": "109", "low": "104", "close": "105", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "105", "high": "107", "low": "103", "close": "106", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v3/fixtures/demo.scenario.jsonl b/contracts/v3/fixtures/demo.scenario.jsonl deleted file mode 100644 index 09afea0..0000000 --- a/contracts/v3/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"3","payload":{"base_currency":"USD","execution":{"fee_bps":10,"fixed_fee":"0.25","model":"completed_bar_v1","participation_bps":5000},"initial_cash":[{"amount":"10000","currency":"USD"}],"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"0.001","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"max_internal_events":1000,"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"risk":{"initial_margin_bps":5000,"maintenance_margin_bps":2500,"max_gross_exposure":"1000000","max_leverage":"2","max_long_position":"1000","max_order_quantity":"1000","max_short_position":"1000","short_borrow_bps":100},"run_id":"demo"},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"3","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"3","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"3","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"3","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v3/journal.schema.json b/contracts/v3/journal.schema.json deleted file mode 100644 index f6027d8..0000000 --- a/contracts/v3/journal.schema.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v3/journal.schema.json", - "title": "Trading Engine v3 audit journal record", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "engine_sequence", "event_id", "causation_ids", "run_id", "recorded_at", "event_type", "payload"], - "properties": { - "contract_version": { "const": "3" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/identifier" } }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": ["run_started", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", "order_cancelled", "split_applied", "cash_dividend_applied", "order_adjusted", "fill_applied", "margin_limited", "borrow_fee_applied", "margin_call", "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed"] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { "if": { "properties": { "event_type": { "const": "run_started" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } }, - { "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } }, - { "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } }, - { "if": { "properties": { "event_type": { "enum": ["order_accepted", "order_rejected"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } }, - { "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } }, - { "if": { "properties": { "event_type": { "const": "split_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/splitApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "cash_dividend_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/dividendApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "order_adjusted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderAdjusted" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } }, - { "if": { "properties": { "event_type": { "const": "margin_limited" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marginLimited" } } } }, - { "if": { "properties": { "event_type": { "const": "borrow_fee_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/borrowFee" } } } }, - { "if": { "properties": { "event_type": { "enum": ["margin_call", "margin_restored", "valuation"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } }, - { "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } }, - { "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } }, - { "if": { "properties": { "event_type": { "const": "run_completed" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } } - ], - "$defs": { - "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "signedDecimal": { "type": "string", "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "unsignedDecimal": { "type": "string", "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "runStarted": { - "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" } } - }, - "bar": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "open": { "$ref": "#/$defs/positiveDecimal" }, "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", "additionalProperties": false, "required": ["currency", "rate"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "rate": { "$ref": "#/$defs/positiveDecimal" } } - }, - "corporateAction": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], "properties": { "type": { "const": "split" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "numerator": { "$ref": "#/$defs/sequence" }, "denominator": { "$ref": "#/$defs/sequence" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "amount_per_unit"], "properties": { "type": { "const": "cash_dividend" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } } } - ] - }, - "marketSlice": { - "type": "object", "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "targetPortfolio": { - "type": "object", "additionalProperties": false, "required": ["basis", "targets"], - "properties": { - "basis": { "enum": ["weights", "quantities"] }, - "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["instrument_id", "weight", "quantity", "reference_price"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "weight": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/signedDecimal" }] }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "reference_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } } } } - } - }, - "order": { - "type": "object", "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "quantity", "order_kind", "limit_price", "origin", "created_event_id", "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "order_kind": { "enum": ["market", "limit"] }, "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "origin": { "enum": ["direct", "target_rebalance", "margin_liquidation"] }, "created_event_id": { "$ref": "#/$defs/identifier" }, "updated_event_id": { "$ref": "#/$defs/identifier" }, "created_sequence": { "$ref": "#/$defs/sequence" }, "created_at": { "$ref": "#/$defs/timestamp" }, "eligible_after_slice_sequence": { "$ref": "#/$defs/nonnegativeSequence" }, "filled_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, "status": { "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] }, "rejection_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1 }] } - } - }, - "orderCancelled": { - "type": "object", "additionalProperties": false, "required": ["order", "reason"], - "properties": { "order": { "$ref": "#/$defs/order" }, "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc", "margin_call"] } } - }, - "splitApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "previous_quantity", "adjusted_quantity"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "previous_quantity": { "$ref": "#/$defs/signedDecimal" }, "adjusted_quantity": { "$ref": "#/$defs/signedDecimal" } } - }, - "dividendApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "quantity", "cash_amount"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "cash_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "orderAdjusted": { - "type": "object", "additionalProperties": false, "required": ["order", "action_id"], - "properties": { "order": { "$ref": "#/$defs/order" }, "action_id": { "$ref": "#/$defs/identifier" } } - }, - "fill": { - "type": "object", "additionalProperties": false, - "required": ["fill_id", "order_id", "instrument_id", "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", "slice_sequence"], - "properties": { "fill_id": { "$ref": "#/$defs/identifier" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" }, "notional": { "$ref": "#/$defs/positiveDecimal" }, "fee": { "$ref": "#/$defs/unsignedDecimal" }, "executed_at": { "$ref": "#/$defs/timestamp" }, "slice_sequence": { "$ref": "#/$defs/sequence" } } - }, - "marginLimited": { - "type": "object", "additionalProperties": false, "required": ["order_id", "instrument_id", "requested_quantity", "permitted_quantity", "price"], - "properties": { "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "requested_quantity": { "$ref": "#/$defs/positiveDecimal" }, "permitted_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" } } - }, - "borrowFee": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "quote_currency", "short_quantity", "reference_price", "borrow_bps", "period_start", "period_end", "fee"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "short_quantity": { "$ref": "#/$defs/positiveDecimal" }, "reference_price": { "$ref": "#/$defs/positiveDecimal" }, "borrow_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, "period_start": { "$ref": "#/$defs/timestamp" }, "period_end": { "$ref": "#/$defs/timestamp" }, "fee": { "$ref": "#/$defs/positiveDecimal" } } - }, - "cashAttribution": { - "type": "object", "additionalProperties": false, "required": ["currency", "amount", "fx_rate", "base_value"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "base_value": { "$ref": "#/$defs/signedDecimal" } } - }, - "positionAttribution": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quote_currency", "quantity", "mark", "fx_rate", "market_value", "base_market_value", "cost_basis", "base_cost_basis", "realized_pnl", "base_realized_pnl", "unrealized_pnl", "base_unrealized_pnl", "dividend_pnl", "base_dividend_pnl", "execution_fees", "base_execution_fees", "borrow_fees", "base_borrow_fees", "total_fees", "base_total_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "mark": { "$ref": "#/$defs/positiveDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "market_value": { "$ref": "#/$defs/signedDecimal" }, "base_market_value": { "$ref": "#/$defs/signedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "base_cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_total_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "margin": { - "type": "object", "additionalProperties": false, "required": ["initial_requirement", "maintenance_requirement", "initial_excess", "maintenance_excess", "margin_call"], - "properties": { "initial_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "maintenance_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "initial_excess": { "$ref": "#/$defs/signedDecimal" }, "maintenance_excess": { "$ref": "#/$defs/signedDecimal" }, "margin_call": { "type": "boolean" } } - }, - "valuation": { - "type": "object", "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "cost_basis", "realized_pnl", "unrealized_pnl", "equity", "dividend_pnl", "execution_fees", "borrow_fees", "total_fees", "cash_balances", "positions", "margin"], - "properties": { - "base_currency": { "$ref": "#/$defs/identifier" }, "cash": { "$ref": "#/$defs/signedDecimal" }, "net_market_value": { "$ref": "#/$defs/signedDecimal" }, "long_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "short_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "equity": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashAttribution" } }, "positions": { "type": "array", "items": { "$ref": "#/$defs/positionAttribution" } }, "margin": { "$ref": "#/$defs/margin" } - } - }, - "intentRejected": { "type": "object", "additionalProperties": false, "required": ["reason"], "properties": { "reason": { "type": "string", "minLength": 1 } } }, - "metric": { "type": "object", "additionalProperties": false, "required": ["name", "value"], "properties": { "name": { "type": "string" }, "value": { "type": "string" } } }, - "runCompleted": { - "type": "object", "additionalProperties": false, "required": ["scenario_sha256", "execution_model", "valuation", "order_counts"], - "properties": { - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" }, "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "type": "object", "additionalProperties": false, "required": ["total", "active", "filled", "rejected", "cancelled"], "properties": { "total": { "type": "integer", "minimum": 0 }, "active": { "type": "integer", "minimum": 0 }, "filled": { "type": "integer", "minimum": 0 }, "rejected": { "type": "integer", "minimum": 0 }, "cancelled": { "type": "integer", "minimum": 0 } } } - } - } - } -} diff --git a/contracts/v3/scenario-stream.schema.json b/contracts/v3/scenario-stream.schema.json deleted file mode 100644 index bd10528..0000000 --- a/contracts/v3/scenario-stream.schema.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v3/scenario-stream.schema.json", - "title": "Trading Engine v3 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "3" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "3" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "3" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/cashBalance" } }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/instrument" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v3/scenario.schema.json b/contracts/v3/scenario.schema.json deleted file mode 100644 index 8d90cfe..0000000 --- a/contracts/v3/scenario.schema.json +++ /dev/null @@ -1,263 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json", - "title": "Trading Engine v3 replay scenario", - "description": "Strict deterministic scenario contract for fractional quantities, explicit FX, corporate actions, signed positions, and margin risk.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "3" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/cashBalance" } - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_order_quantity", "max_long_position", "max_short_position", "max_gross_exposure", "max_leverage", "initial_margin_bps", "maintenance_margin_bps", "short_borrow_bps"], - "properties": { - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "participation_bps", "fixed_fee", "fee_bps"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "limit_price"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit"] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } - } - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v4/README.md b/contracts/v4/README.md deleted file mode 100644 index b86761d..0000000 --- a/contracts/v4/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Trading Engine contract v4 - -This directory is the authoritative v4 process and file contract shared by Trading Engine and -its clients. Version 3 remains available under `contracts/v3` during the client transition. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 4 replaces the ambiguous `margin_limited` journal event with `fill_clipped`. Its versioned, -exhaustive reason identifies the limiting policy and a typed threshold alongside the proposed and -permitted quantities. Every v4 scenario, stream record, and journal record carries -`"contract_version": "4"`; consumers reject missing or unsupported versions before interpreting -the remainder of a document. The scenario shape is otherwise unchanged from v3. - -`fill_clipped.payload.reason.version` is `"1"`. Its exhaustive policy and threshold pairs are: - -| Policy | Threshold unit | Threshold value | -| --- | --- | --- | -| `max_order_quantity` | `quantity` | Configured maximum order quantity | -| `max_long_position` | `quantity` | Configured maximum long position | -| `max_short_position` | `quantity` | Configured maximum short position magnitude | -| `max_gross_exposure` | `money` | Configured maximum gross exposure | -| `max_leverage` | `ratio` | Configured maximum leverage | -| `initial_margin` | `basis_points` | Configured initial-margin basis points | - -The event also records `order_id`, `instrument_id`, `proposed_quantity`, `permitted_quantity`, and -the proposed fill `price`. A consumer must reject unknown reason versions, policies, threshold -units, and policy/unit combinations. diff --git a/contracts/v4/dune b/contracts/v4/dune deleted file mode 100644 index 6cd8a55..0000000 --- a/contracts/v4/dune +++ /dev/null @@ -1,16 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v4/journal.schema.json) - (scenario-stream.schema.json as contracts/v4/scenario-stream.schema.json) - (scenario.schema.json as contracts/v4/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v4/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v4/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v4/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v4/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v4/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v4/fixtures/demo.journal.jsonl b/contracts/v4/fixtures/demo.journal.jsonl deleted file mode 100644 index 503d7c5..0000000 --- a/contracts/v4/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,20 +0,0 @@ -{"contract_version":"4","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"991890e8c1cc839a0c321a6d30b2ba20a8b588d4135310f43a548fbc929e9fcf","execution_model":"completed_bar_v1"}} -{"contract_version":"4","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"4","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.615","reference_price":"104"}]}} -{"contract_version":"4","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"4","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000002","demo-event-000000000003"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","updated_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"4","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"10000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"0","mark":"104","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"10000","maintenance_excess":"10000","margin_call":false}}} -{"contract_version":"4","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"4","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"4","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","updated_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"4","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000003","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"3.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000010","updated_event_id":"demo-event-000000000010","created_sequence":"10","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"4","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.132","net_market_value":"642","long_market_value":"642","short_market_value":"0","gross_exposure":"642","cost_basis":"618.868","realized_pnl":"0","unrealized_pnl":"23.132","equity":"10023.132","dividend_pnl":"0","execution_fees":"0.868","borrow_fees":"0","total_fees":"0.868","cash_balances":[{"currency":"USD","amount":"9381.132","fx_rate":"1","base_value":"9381.132"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"6","mark":"107","fx_rate":"1","market_value":"642","base_market_value":"642","cost_basis":"618.868","base_cost_basis":"618.868","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"23.132","base_unrealized_pnl":"23.132","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0.868","base_execution_fees":"0.868","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0.868","base_total_fees":"0.868"}],"margin":{"initial_requirement":"321","maintenance_requirement":"160.5","initial_excess":"9702.132","maintenance_excess":"9862.632","margin_call":false}}} -{"contract_version":"4","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"4","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000010","demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"3.615","price":"107","notional":"386.805","fee":"0.636805","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"4","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"4","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.115","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"4","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"8993.690195","net_market_value":"1009.575","long_market_value":"1009.575","short_market_value":"0","gross_exposure":"1009.575","cost_basis":"1006.309805","realized_pnl":"0","unrealized_pnl":"3.265195","equity":"10003.265195","dividend_pnl":"0","execution_fees":"1.504805","borrow_fees":"0","total_fees":"1.504805","cash_balances":[{"currency":"USD","amount":"8993.690195","fx_rate":"1","base_value":"8993.690195"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.615","mark":"105","fx_rate":"1","market_value":"1009.575","base_market_value":"1009.575","cost_basis":"1006.309805","base_cost_basis":"1006.309805","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"3.265195","base_unrealized_pnl":"3.265195","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"1.504805","base_execution_fees":"1.504805","borrow_fees":"0","base_borrow_fees":"0","total_fees":"1.504805","base_total_fees":"1.504805"}],"margin":{"initial_requirement":"504.7875","maintenance_requirement":"252.39375","initial_excess":"9498.477695","maintenance_excess":"9750.871445","margin_call":false}}} -{"contract_version":"4","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"4","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.115","price":"105","notional":"747.075","fee":"0.997075","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"4","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9739.76812","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"261.651016","realized_pnl":"1.419136","unrealized_pnl":"3.348984","equity":"10004.76812","dividend_pnl":"0","execution_fees":"2.50188","borrow_fees":"0","total_fees":"2.50188","cash_balances":[{"currency":"USD","amount":"9739.76812","fx_rate":"1","base_value":"9739.76812"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"261.651016","base_cost_basis":"261.651016","realized_pnl":"1.419136","base_realized_pnl":"1.419136","unrealized_pnl":"3.348984","base_unrealized_pnl":"3.348984","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"2.50188","base_execution_fees":"2.50188","borrow_fees":"0","base_borrow_fees":"0","total_fees":"2.50188","base_total_fees":"2.50188"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9872.26812","maintenance_excess":"9938.51812","margin_call":false}}} -{"contract_version":"4","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"991890e8c1cc839a0c321a6d30b2ba20a8b588d4135310f43a548fbc929e9fcf","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9739.76812","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"261.651016","realized_pnl":"1.419136","unrealized_pnl":"3.348984","equity":"10004.76812","dividend_pnl":"0","execution_fees":"2.50188","borrow_fees":"0","total_fees":"2.50188","cash_balances":[{"currency":"USD","amount":"9739.76812","fx_rate":"1","base_value":"9739.76812"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"261.651016","base_cost_basis":"261.651016","realized_pnl":"1.419136","base_realized_pnl":"1.419136","unrealized_pnl":"3.348984","base_unrealized_pnl":"3.348984","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"2.50188","base_execution_fees":"2.50188","borrow_fees":"0","base_borrow_fees":"0","total_fees":"2.50188","base_total_fees":"2.50188"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9872.26812","maintenance_excess":"9938.51812","margin_call":false}},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v4/fixtures/demo.scenario.json b/contracts/v4/fixtures/demo.scenario.json deleted file mode 100644 index c5174ec..0000000 --- a/contracts/v4/fixtures/demo.scenario.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "contract_version": "4", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "10000" } - ], - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000", - "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 100 - }, - "execution": { - "model": "completed_bar_v1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { "instrument_id": "demo-equity-acme", "weight": "0.1" } - ] - }, - { "type": "emit_metric", "name": "desired_weight", "value": "0.1" } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { "instrument_id": "demo-equity-acme", "quantity": "2.5" } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "100", "high": "105", "low": "99", "close": "104", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "103", "high": "108", "low": "102", "close": "107", "volume": "12" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "107", "high": "109", "low": "104", "close": "105", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "105", "high": "107", "low": "103", "close": "106", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v4/fixtures/demo.scenario.jsonl b/contracts/v4/fixtures/demo.scenario.jsonl deleted file mode 100644 index 829d797..0000000 --- a/contracts/v4/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"4","payload":{"base_currency":"USD","execution":{"fee_bps":10,"fixed_fee":"0.25","model":"completed_bar_v1","participation_bps":5000},"initial_cash":[{"amount":"10000","currency":"USD"}],"instruments":[{"instrument_id":"demo-equity-acme","lot_size":"0.001","quote_currency":"USD","symbol":"ACME","tick_size":"0.01"}],"max_internal_events":1000,"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"risk":{"initial_margin_bps":5000,"maintenance_margin_bps":2500,"max_gross_exposure":"1000000","max_leverage":"2","max_long_position":"1000","max_order_quantity":"1000","max_short_position":"1000","short_borrow_bps":100},"run_id":"demo"},"record_type":"scenario_header","scenario_sequence":"1"} -{"contract_version":"4","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"4","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"4","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"4","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"4","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v4/fixtures/fill-clipped.journal.jsonl b/contracts/v4/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 67d9a50..0000000 --- a/contracts/v4/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,10 +0,0 @@ -{"contract_version":"4","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"6ae16145d56f1ff2b7594c04917fd026a18e8fea9beb688a8aaf4a84cc7dca2c","execution_model":"completed_bar_v1"}} -{"contract_version":"4","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"4","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000003","updated_event_id":"fill-clipped-event-000000000003","created_sequence":"3","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"4","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false}}} -{"contract_version":"4","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"4","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000003","fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"5","price":"100"}} -{"contract_version":"4","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000003","fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"fill-clipped-fill-000000000001","order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"5","price":"100","notional":"500","fee":"10","executed_at":"2026-02-03T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"4","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":["fill-clipped-event-000000000003","fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000003","updated_event_id":"fill-clipped-event-000000000003","created_sequence":"3","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"5","filled_notional":"500","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"4","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"40","net_market_value":"500","long_market_value":"500","short_market_value":"0","gross_exposure":"500","cost_basis":"510","realized_pnl":"0","unrealized_pnl":"-10","equity":"540","dividend_pnl":"0","execution_fees":"10","borrow_fees":"0","total_fees":"10","cash_balances":[{"currency":"USD","amount":"40","fx_rate":"1","base_value":"40"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"5","mark":"100","fx_rate":"1","market_value":"500","base_market_value":"500","cost_basis":"510","base_cost_basis":"510","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-10","base_unrealized_pnl":"-10","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"10","base_execution_fees":"10","borrow_fees":"0","base_borrow_fees":"0","total_fees":"10","base_total_fees":"10"}],"margin":{"initial_requirement":"250","maintenance_requirement":"125","initial_excess":"290","maintenance_excess":"415","margin_call":false}}} -{"contract_version":"4","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000009"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"6ae16145d56f1ff2b7594c04917fd026a18e8fea9beb688a8aaf4a84cc7dca2c","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"40","net_market_value":"500","long_market_value":"500","short_market_value":"0","gross_exposure":"500","cost_basis":"510","realized_pnl":"0","unrealized_pnl":"-10","equity":"540","dividend_pnl":"0","execution_fees":"10","borrow_fees":"0","total_fees":"10","cash_balances":[{"currency":"USD","amount":"40","fx_rate":"1","base_value":"40"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"5","mark":"100","fx_rate":"1","market_value":"500","base_market_value":"500","cost_basis":"510","base_cost_basis":"510","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-10","base_unrealized_pnl":"-10","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"10","base_execution_fees":"10","borrow_fees":"0","base_borrow_fees":"0","total_fees":"10","base_total_fees":"10"}],"margin":{"initial_requirement":"250","maintenance_requirement":"125","initial_excess":"290","maintenance_excess":"415","margin_call":false}},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v4/fixtures/fill-clipped.scenario.json b/contracts/v4/fixtures/fill-clipped.scenario.json deleted file mode 100644 index c575c46..0000000 --- a/contracts/v4/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "contract_version": "4", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "550" } - ], - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 100 - }, - "execution": { - "model": "completed_bar_v1", - "participation_bps": 10000, - "fixed_fee": "10", - "fee_bps": 0 - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "limit_price": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { "instrument_id": "clip-equity", "open": "50", "high": "50", "low": "50", "close": "50", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { "instrument_id": "clip-equity", "open": "100", "high": "100", "low": "100", "close": "100", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v4/journal.schema.json b/contracts/v4/journal.schema.json deleted file mode 100644 index c580f03..0000000 --- a/contracts/v4/journal.schema.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v4/journal.schema.json", - "title": "Trading Engine v4 audit journal record", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "engine_sequence", "event_id", "causation_ids", "run_id", "recorded_at", "event_type", "payload"], - "properties": { - "contract_version": { "const": "4" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/identifier" } }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": ["run_started", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", "order_cancelled", "split_applied", "cash_dividend_applied", "order_adjusted", "fill_applied", "fill_clipped", "borrow_fee_applied", "margin_call", "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed"] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { "if": { "properties": { "event_type": { "const": "run_started" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } }, - { "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } }, - { "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } }, - { "if": { "properties": { "event_type": { "enum": ["order_accepted", "order_rejected"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } }, - { "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } }, - { "if": { "properties": { "event_type": { "const": "split_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/splitApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "cash_dividend_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/dividendApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "order_adjusted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderAdjusted" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_clipped" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fillClipped" } } } }, - { "if": { "properties": { "event_type": { "const": "borrow_fee_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/borrowFee" } } } }, - { "if": { "properties": { "event_type": { "enum": ["margin_call", "margin_restored", "valuation"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } }, - { "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } }, - { "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } }, - { "if": { "properties": { "event_type": { "const": "run_completed" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } } - ], - "$defs": { - "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "signedDecimal": { "type": "string", "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "unsignedDecimal": { "type": "string", "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "runStarted": { - "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" } } - }, - "bar": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "open": { "$ref": "#/$defs/positiveDecimal" }, "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", "additionalProperties": false, "required": ["currency", "rate"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "rate": { "$ref": "#/$defs/positiveDecimal" } } - }, - "corporateAction": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], "properties": { "type": { "const": "split" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "numerator": { "$ref": "#/$defs/sequence" }, "denominator": { "$ref": "#/$defs/sequence" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "amount_per_unit"], "properties": { "type": { "const": "cash_dividend" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } } } - ] - }, - "marketSlice": { - "type": "object", "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "targetPortfolio": { - "type": "object", "additionalProperties": false, "required": ["basis", "targets"], - "properties": { - "basis": { "enum": ["weights", "quantities"] }, - "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["instrument_id", "weight", "quantity", "reference_price"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "weight": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/signedDecimal" }] }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "reference_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } } } } - } - }, - "order": { - "type": "object", "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "quantity", "order_kind", "limit_price", "origin", "created_event_id", "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "order_kind": { "enum": ["market", "limit"] }, "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "origin": { "enum": ["direct", "target_rebalance", "margin_liquidation"] }, "created_event_id": { "$ref": "#/$defs/identifier" }, "updated_event_id": { "$ref": "#/$defs/identifier" }, "created_sequence": { "$ref": "#/$defs/sequence" }, "created_at": { "$ref": "#/$defs/timestamp" }, "eligible_after_slice_sequence": { "$ref": "#/$defs/nonnegativeSequence" }, "filled_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, "status": { "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] }, "rejection_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1 }] } - } - }, - "orderCancelled": { - "type": "object", "additionalProperties": false, "required": ["order", "reason"], - "properties": { "order": { "$ref": "#/$defs/order" }, "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc", "margin_call"] } } - }, - "splitApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "previous_quantity", "adjusted_quantity"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "previous_quantity": { "$ref": "#/$defs/signedDecimal" }, "adjusted_quantity": { "$ref": "#/$defs/signedDecimal" } } - }, - "dividendApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "quantity", "cash_amount"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "cash_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "orderAdjusted": { - "type": "object", "additionalProperties": false, "required": ["order", "action_id"], - "properties": { "order": { "$ref": "#/$defs/order" }, "action_id": { "$ref": "#/$defs/identifier" } } - }, - "fill": { - "type": "object", "additionalProperties": false, - "required": ["fill_id", "order_id", "instrument_id", "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", "slice_sequence"], - "properties": { "fill_id": { "$ref": "#/$defs/identifier" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" }, "notional": { "$ref": "#/$defs/positiveDecimal" }, "fee": { "$ref": "#/$defs/unsignedDecimal" }, "executed_at": { "$ref": "#/$defs/timestamp" }, "slice_sequence": { "$ref": "#/$defs/sequence" } } - }, - "quantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "moneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "ratioThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "basisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "fillClipReason": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_order_quantity" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_long_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_short_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_gross_exposure" }, "threshold": { "$ref": "#/$defs/moneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_leverage" }, "threshold": { "$ref": "#/$defs/ratioThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "initial_margin" }, "threshold": { "$ref": "#/$defs/basisPointsThreshold" } } } - ] - }, - "fillClipped": { - "type": "object", "additionalProperties": false, "required": ["reason", "order_id", "instrument_id", "proposed_quantity", "permitted_quantity", "price"], - "properties": { "reason": { "$ref": "#/$defs/fillClipReason" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "proposed_quantity": { "$ref": "#/$defs/positiveDecimal" }, "permitted_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" } } - }, - "borrowFee": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "quote_currency", "short_quantity", "reference_price", "borrow_bps", "period_start", "period_end", "fee"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "short_quantity": { "$ref": "#/$defs/positiveDecimal" }, "reference_price": { "$ref": "#/$defs/positiveDecimal" }, "borrow_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, "period_start": { "$ref": "#/$defs/timestamp" }, "period_end": { "$ref": "#/$defs/timestamp" }, "fee": { "$ref": "#/$defs/positiveDecimal" } } - }, - "cashAttribution": { - "type": "object", "additionalProperties": false, "required": ["currency", "amount", "fx_rate", "base_value"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "base_value": { "$ref": "#/$defs/signedDecimal" } } - }, - "positionAttribution": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quote_currency", "quantity", "mark", "fx_rate", "market_value", "base_market_value", "cost_basis", "base_cost_basis", "realized_pnl", "base_realized_pnl", "unrealized_pnl", "base_unrealized_pnl", "dividend_pnl", "base_dividend_pnl", "execution_fees", "base_execution_fees", "borrow_fees", "base_borrow_fees", "total_fees", "base_total_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "mark": { "$ref": "#/$defs/positiveDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "market_value": { "$ref": "#/$defs/signedDecimal" }, "base_market_value": { "$ref": "#/$defs/signedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "base_cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_total_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "margin": { - "type": "object", "additionalProperties": false, "required": ["initial_requirement", "maintenance_requirement", "initial_excess", "maintenance_excess", "margin_call"], - "properties": { "initial_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "maintenance_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "initial_excess": { "$ref": "#/$defs/signedDecimal" }, "maintenance_excess": { "$ref": "#/$defs/signedDecimal" }, "margin_call": { "type": "boolean" } } - }, - "valuation": { - "type": "object", "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "cost_basis", "realized_pnl", "unrealized_pnl", "equity", "dividend_pnl", "execution_fees", "borrow_fees", "total_fees", "cash_balances", "positions", "margin"], - "properties": { - "base_currency": { "$ref": "#/$defs/identifier" }, "cash": { "$ref": "#/$defs/signedDecimal" }, "net_market_value": { "$ref": "#/$defs/signedDecimal" }, "long_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "short_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "equity": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashAttribution" } }, "positions": { "type": "array", "items": { "$ref": "#/$defs/positionAttribution" } }, "margin": { "$ref": "#/$defs/margin" } - } - }, - "intentRejected": { "type": "object", "additionalProperties": false, "required": ["reason"], "properties": { "reason": { "type": "string", "minLength": 1 } } }, - "metric": { "type": "object", "additionalProperties": false, "required": ["name", "value"], "properties": { "name": { "type": "string" }, "value": { "type": "string" } } }, - "runCompleted": { - "type": "object", "additionalProperties": false, "required": ["scenario_sha256", "execution_model", "valuation", "order_counts"], - "properties": { - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" }, "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "type": "object", "additionalProperties": false, "required": ["total", "active", "filled", "rejected", "cancelled"], "properties": { "total": { "type": "integer", "minimum": 0 }, "active": { "type": "integer", "minimum": 0 }, "filled": { "type": "integer", "minimum": 0 }, "rejected": { "type": "integer", "minimum": 0 }, "cancelled": { "type": "integer", "minimum": 0 } } } - } - } - } -} diff --git a/contracts/v4/scenario-stream.schema.json b/contracts/v4/scenario-stream.schema.json deleted file mode 100644 index c1da40a..0000000 --- a/contracts/v4/scenario-stream.schema.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v4/scenario-stream.schema.json", - "title": "Trading Engine v4 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "4" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "4" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "4" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/cashBalance" } }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/instrument" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v4/scenario.schema.json b/contracts/v4/scenario.schema.json deleted file mode 100644 index d3aea43..0000000 --- a/contracts/v4/scenario.schema.json +++ /dev/null @@ -1,263 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v4/scenario.schema.json", - "title": "Trading Engine v4 replay scenario", - "description": "Strict deterministic scenario contract for fractional quantities, explicit FX, corporate actions, signed positions, and margin risk.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "4" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/cashBalance" } - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_order_quantity", "max_long_position", "max_short_position", "max_gross_exposure", "max_leverage", "initial_margin_bps", "maintenance_margin_bps", "short_borrow_bps"], - "properties": { - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "participation_bps", "fixed_fee", "fee_bps"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "limit_price"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit"] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } - } - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v5/README.md b/contracts/v5/README.md deleted file mode 100644 index 5495e2e..0000000 --- a/contracts/v5/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# Trading Engine contract v5 - -This directory is the authoritative v5 process and file contract shared by Trading Engine and its -clients. Versions 4 and 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 5 adds explicit immutable venue-calendar snapshots. Each calendar has stable venue and -calendar identities, a calendar contract version, explicit instrument membership, and ordered -date policies. A date is either a holiday or an open session named as regular or early-close. -Open sessions contain absolute timestamp intervals for configured premarket, opening-auction, -regular, closing-auction, and postmarket phases. - -Calendar producers resolve local civil time, time-zone database versions, daylight-saving rules, -and clock changes before creating a scenario. The reducer receives only absolute instants. Missing -date policies are errors and must never be inferred from weekdays or adjacent sessions. Runtime -validation also rejects duplicate calendar identities, overlapping instrument membership, missing -instrument coverage, unordered or overlapping phases, holidays with phases, and open sessions -without a regular phase. - -Every v5 scenario, stream record, and journal record carries `"contract_version": "5"`. - -The v5 `execution` object also namespaces strict configuration beneath the stable model name. -`completed_bar_v1` configuration version `"1"` requires participation basis points, fixed fee, -and fee basis points. Runtime capabilities describe its required fields, supported market and limit -orders, completed-OHLCV data requirement, and numeric limits. diff --git a/contracts/v5/dune b/contracts/v5/dune deleted file mode 100644 index 6e47d5e..0000000 --- a/contracts/v5/dune +++ /dev/null @@ -1,16 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v5/journal.schema.json) - (scenario-stream.schema.json as contracts/v5/scenario-stream.schema.json) - (scenario.schema.json as contracts/v5/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v5/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v5/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v5/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v5/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v5/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v5/fixtures/demo.journal.jsonl b/contracts/v5/fixtures/demo.journal.jsonl deleted file mode 100644 index 7900887..0000000 --- a/contracts/v5/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,20 +0,0 @@ -{"contract_version":"5","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"b800732e40c20c06605c6a1352d3482a3f41fc7ae4b07594860a1c3f153a655c","execution_model":"completed_bar_v1"}} -{"contract_version":"5","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"5","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.615","reference_price":"104"}]}} -{"contract_version":"5","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"5","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000002","demo-event-000000000003"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","updated_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"5","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"10000","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"0","mark":"104","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"10000","maintenance_excess":"10000","margin_call":false}}} -{"contract_version":"5","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"5","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"5","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":["demo-event-000000000005","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"9.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000005","updated_event_id":"demo-event-000000000005","created_sequence":"5","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"5","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000003","demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"3.615","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000010","updated_event_id":"demo-event-000000000010","created_sequence":"10","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"5","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.132","net_market_value":"642","long_market_value":"642","short_market_value":"0","gross_exposure":"642","cost_basis":"618.868","realized_pnl":"0","unrealized_pnl":"23.132","equity":"10023.132","dividend_pnl":"0","execution_fees":"0.868","borrow_fees":"0","total_fees":"0.868","cash_balances":[{"currency":"USD","amount":"9381.132","fx_rate":"1","base_value":"9381.132"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"6","mark":"107","fx_rate":"1","market_value":"642","base_market_value":"642","cost_basis":"618.868","base_cost_basis":"618.868","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"23.132","base_unrealized_pnl":"23.132","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0.868","base_execution_fees":"0.868","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0.868","base_total_fees":"0.868"}],"margin":{"initial_requirement":"321","maintenance_requirement":"160.5","initial_excess":"9702.132","maintenance_excess":"9862.632","margin_call":false}}} -{"contract_version":"5","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"5","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000010","demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"3.615","price":"107","notional":"386.805","fee":"0.636805","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"5","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"5","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.115","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000015","updated_event_id":"demo-event-000000000015","created_sequence":"15","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"5","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000012"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"8993.690195","net_market_value":"1009.575","long_market_value":"1009.575","short_market_value":"0","gross_exposure":"1009.575","cost_basis":"1006.309805","realized_pnl":"0","unrealized_pnl":"3.265195","equity":"10003.265195","dividend_pnl":"0","execution_fees":"1.504805","borrow_fees":"0","total_fees":"1.504805","cash_balances":[{"currency":"USD","amount":"8993.690195","fx_rate":"1","base_value":"8993.690195"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.615","mark":"105","fx_rate":"1","market_value":"1009.575","base_market_value":"1009.575","cost_basis":"1006.309805","base_cost_basis":"1006.309805","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"3.265195","base_unrealized_pnl":"3.265195","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"1.504805","base_execution_fees":"1.504805","borrow_fees":"0","base_borrow_fees":"0","total_fees":"1.504805","base_total_fees":"1.504805"}],"margin":{"initial_requirement":"504.7875","maintenance_requirement":"252.39375","initial_excess":"9498.477695","maintenance_excess":"9750.871445","margin_call":false}}} -{"contract_version":"5","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"5","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000015","demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.115","price":"105","notional":"747.075","fee":"0.997075","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"5","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":["demo-event-000000000017"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9739.76812","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"261.651016","realized_pnl":"1.419136","unrealized_pnl":"3.348984","equity":"10004.76812","dividend_pnl":"0","execution_fees":"2.50188","borrow_fees":"0","total_fees":"2.50188","cash_balances":[{"currency":"USD","amount":"9739.76812","fx_rate":"1","base_value":"9739.76812"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"261.651016","base_cost_basis":"261.651016","realized_pnl":"1.419136","base_realized_pnl":"1.419136","unrealized_pnl":"3.348984","base_unrealized_pnl":"3.348984","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"2.50188","base_execution_fees":"2.50188","borrow_fees":"0","base_borrow_fees":"0","total_fees":"2.50188","base_total_fees":"2.50188"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9872.26812","maintenance_excess":"9938.51812","margin_call":false}}} -{"contract_version":"5","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"b800732e40c20c06605c6a1352d3482a3f41fc7ae4b07594860a1c3f153a655c","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9739.76812","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"261.651016","realized_pnl":"1.419136","unrealized_pnl":"3.348984","equity":"10004.76812","dividend_pnl":"0","execution_fees":"2.50188","borrow_fees":"0","total_fees":"2.50188","cash_balances":[{"currency":"USD","amount":"9739.76812","fx_rate":"1","base_value":"9739.76812"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"261.651016","base_cost_basis":"261.651016","realized_pnl":"1.419136","base_realized_pnl":"1.419136","unrealized_pnl":"3.348984","base_unrealized_pnl":"3.348984","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"2.50188","base_execution_fees":"2.50188","borrow_fees":"0","base_borrow_fees":"0","total_fees":"2.50188","base_total_fees":"2.50188"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9872.26812","maintenance_excess":"9938.51812","margin_call":false}},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v5/fixtures/demo.scenario.json b/contracts/v5/fixtures/demo.scenario.json deleted file mode 100644 index 1ba8e32..0000000 --- a/contracts/v5/fixtures/demo.scenario.json +++ /dev/null @@ -1,166 +0,0 @@ -{ - "contract_version": "5", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "10000" } - ], - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": ["demo-equity-acme"], - "sessions": [ - { "session_date": "2026-01-01", "policy": "holiday", "phases": [] }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { "phase": "premarket", "opens_at": "2026-01-02T09:00:00Z", "closes_at": "2026-01-02T14:25:00Z" }, - { "phase": "opening_auction", "opens_at": "2026-01-02T14:25:00Z", "closes_at": "2026-01-02T14:30:00Z" }, - { "phase": "regular", "opens_at": "2026-01-02T14:30:00Z", "closes_at": "2026-01-02T20:55:00Z" }, - { "phase": "closing_auction", "opens_at": "2026-01-02T20:55:00Z", "closes_at": "2026-01-02T21:00:00Z" }, - { "phase": "postmarket", "opens_at": "2026-01-02T21:00:00Z", "closes_at": "2026-01-03T01:00:00Z" } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { "phase": "regular", "opens_at": "2026-01-05T14:30:00Z", "closes_at": "2026-01-05T21:00:00Z" } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { "phase": "regular", "opens_at": "2026-01-06T14:30:00Z", "closes_at": "2026-01-06T21:00:00Z" } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { "phase": "regular", "opens_at": "2026-01-07T14:30:00Z", "closes_at": "2026-01-07T21:00:00Z" } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { "phase": "regular", "opens_at": "2026-01-08T14:30:00Z", "closes_at": "2026-01-08T18:00:00Z" } - ] - } - ] - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000", - "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 100 - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { "instrument_id": "demo-equity-acme", "weight": "0.1" } - ] - }, - { "type": "emit_metric", "name": "desired_weight", "value": "0.1" } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { "instrument_id": "demo-equity-acme", "quantity": "2.5" } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "100", "high": "105", "low": "99", "close": "104", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "103", "high": "108", "low": "102", "close": "107", "volume": "12" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "107", "high": "109", "low": "104", "close": "105", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { "instrument_id": "demo-equity-acme", "open": "105", "high": "107", "low": "103", "close": "106", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v5/fixtures/demo.scenario.jsonl b/contracts/v5/fixtures/demo.scenario.jsonl deleted file mode 100644 index 7a9733a..0000000 --- a/contracts/v5/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"5","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_cash":[{"currency":"USD","amount":"10000"}],"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_gross_exposure":"1000000","max_leverage":"2","initial_margin_bps":5000,"maintenance_margin_bps":2500,"short_borrow_bps":100},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"max_internal_events":1000}} -{"contract_version":"5","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"5","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"5","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"5","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"5","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v5/fixtures/fill-clipped.journal.jsonl b/contracts/v5/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 3734bbb..0000000 --- a/contracts/v5/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,10 +0,0 @@ -{"contract_version":"5","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"3a66be243ea4ae30e5554c7e0dbdc091bd7dd7c5003f4faf726f04b0fbdaeed6","execution_model":"completed_bar_v1"}} -{"contract_version":"5","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"5","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000003","updated_event_id":"fill-clipped-event-000000000003","created_sequence":"3","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"5","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false}}} -{"contract_version":"5","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"5","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000003","fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"5","price":"100"}} -{"contract_version":"5","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":["fill-clipped-event-000000000003","fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"fill-clipped-fill-000000000001","order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"5","price":"100","notional":"500","fee":"10","executed_at":"2026-02-03T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"5","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":["fill-clipped-event-000000000003","fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000003","updated_event_id":"fill-clipped-event-000000000003","created_sequence":"3","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"5","filled_notional":"500","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"5","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000005"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"40","net_market_value":"500","long_market_value":"500","short_market_value":"0","gross_exposure":"500","cost_basis":"510","realized_pnl":"0","unrealized_pnl":"-10","equity":"540","dividend_pnl":"0","execution_fees":"10","borrow_fees":"0","total_fees":"10","cash_balances":[{"currency":"USD","amount":"40","fx_rate":"1","base_value":"40"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"5","mark":"100","fx_rate":"1","market_value":"500","base_market_value":"500","cost_basis":"510","base_cost_basis":"510","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-10","base_unrealized_pnl":"-10","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"10","base_execution_fees":"10","borrow_fees":"0","base_borrow_fees":"0","total_fees":"10","base_total_fees":"10"}],"margin":{"initial_requirement":"250","maintenance_requirement":"125","initial_excess":"290","maintenance_excess":"415","margin_call":false}}} -{"contract_version":"5","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000009"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"3a66be243ea4ae30e5554c7e0dbdc091bd7dd7c5003f4faf726f04b0fbdaeed6","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"40","net_market_value":"500","long_market_value":"500","short_market_value":"0","gross_exposure":"500","cost_basis":"510","realized_pnl":"0","unrealized_pnl":"-10","equity":"540","dividend_pnl":"0","execution_fees":"10","borrow_fees":"0","total_fees":"10","cash_balances":[{"currency":"USD","amount":"40","fx_rate":"1","base_value":"40"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"5","mark":"100","fx_rate":"1","market_value":"500","base_market_value":"500","cost_basis":"510","base_cost_basis":"510","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-10","base_unrealized_pnl":"-10","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"10","base_execution_fees":"10","borrow_fees":"0","base_borrow_fees":"0","total_fees":"10","base_total_fees":"10"}],"margin":{"initial_requirement":"250","maintenance_requirement":"125","initial_excess":"290","maintenance_excess":"415","margin_call":false}},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v5/fixtures/fill-clipped.scenario.json b/contracts/v5/fixtures/fill-clipped.scenario.json deleted file mode 100644 index b213a8b..0000000 --- a/contracts/v5/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "contract_version": "5", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_cash": [ - { "currency": "USD", "amount": "550" } - ], - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": ["clip-equity"], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { "phase": "regular", "opens_at": "2026-02-02T14:30:00Z", "closes_at": "2026-02-02T21:00:00Z" } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { "phase": "regular", "opens_at": "2026-02-03T14:30:00Z", "closes_at": "2026-02-03T21:00:00Z" } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { "phase": "regular", "opens_at": "2026-02-04T14:30:00Z", "closes_at": "2026-02-04T18:00:00Z" } - ] - } - ] - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 100 - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 10000, - "fixed_fee": "10", - "fee_bps": 0 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "limit_price": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { "instrument_id": "clip-equity", "open": "50", "high": "50", "low": "50", "close": "50", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { "instrument_id": "clip-equity", "open": "100", "high": "100", "low": "100", "close": "100", "volume": "100" } - ], - "fx_rates": [{ "currency": "USD", "rate": "1" }], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v5/journal.schema.json b/contracts/v5/journal.schema.json deleted file mode 100644 index ca161ad..0000000 --- a/contracts/v5/journal.schema.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v5/journal.schema.json", - "title": "Trading Engine v5 audit journal record", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "engine_sequence", "event_id", "causation_ids", "run_id", "recorded_at", "event_type", "payload"], - "properties": { - "contract_version": { "const": "5" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/identifier" } }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": ["run_started", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", "order_cancelled", "split_applied", "cash_dividend_applied", "order_adjusted", "fill_applied", "fill_clipped", "borrow_fee_applied", "margin_call", "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed"] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { "if": { "properties": { "event_type": { "const": "run_started" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } }, - { "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } }, - { "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } }, - { "if": { "properties": { "event_type": { "enum": ["order_accepted", "order_rejected"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } }, - { "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } }, - { "if": { "properties": { "event_type": { "const": "split_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/splitApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "cash_dividend_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/dividendApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "order_adjusted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderAdjusted" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_clipped" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fillClipped" } } } }, - { "if": { "properties": { "event_type": { "const": "borrow_fee_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/borrowFee" } } } }, - { "if": { "properties": { "event_type": { "enum": ["margin_call", "margin_restored", "valuation"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } }, - { "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } }, - { "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } }, - { "if": { "properties": { "event_type": { "const": "run_completed" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } } - ], - "$defs": { - "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "signedDecimal": { "type": "string", "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "unsignedDecimal": { "type": "string", "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "runStarted": { - "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" } } - }, - "bar": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "open": { "$ref": "#/$defs/positiveDecimal" }, "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", "additionalProperties": false, "required": ["currency", "rate"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "rate": { "$ref": "#/$defs/positiveDecimal" } } - }, - "corporateAction": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], "properties": { "type": { "const": "split" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "numerator": { "$ref": "#/$defs/sequence" }, "denominator": { "$ref": "#/$defs/sequence" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "amount_per_unit"], "properties": { "type": { "const": "cash_dividend" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } } } - ] - }, - "marketSlice": { - "type": "object", "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "targetPortfolio": { - "type": "object", "additionalProperties": false, "required": ["basis", "targets"], - "properties": { - "basis": { "enum": ["weights", "quantities"] }, - "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["instrument_id", "weight", "quantity", "reference_price"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "weight": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/signedDecimal" }] }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "reference_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } } } } - } - }, - "order": { - "type": "object", "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "quantity", "order_kind", "limit_price", "origin", "created_event_id", "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "order_kind": { "enum": ["market", "limit"] }, "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "origin": { "enum": ["direct", "target_rebalance", "margin_liquidation"] }, "created_event_id": { "$ref": "#/$defs/identifier" }, "updated_event_id": { "$ref": "#/$defs/identifier" }, "created_sequence": { "$ref": "#/$defs/sequence" }, "created_at": { "$ref": "#/$defs/timestamp" }, "eligible_after_slice_sequence": { "$ref": "#/$defs/nonnegativeSequence" }, "filled_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, "status": { "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] }, "rejection_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1 }] } - } - }, - "orderCancelled": { - "type": "object", "additionalProperties": false, "required": ["order", "reason"], - "properties": { "order": { "$ref": "#/$defs/order" }, "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc", "margin_call"] } } - }, - "splitApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "previous_quantity", "adjusted_quantity"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "previous_quantity": { "$ref": "#/$defs/signedDecimal" }, "adjusted_quantity": { "$ref": "#/$defs/signedDecimal" } } - }, - "dividendApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "quantity", "cash_amount"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "cash_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "orderAdjusted": { - "type": "object", "additionalProperties": false, "required": ["order", "action_id"], - "properties": { "order": { "$ref": "#/$defs/order" }, "action_id": { "$ref": "#/$defs/identifier" } } - }, - "fill": { - "type": "object", "additionalProperties": false, - "required": ["fill_id", "order_id", "instrument_id", "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", "slice_sequence"], - "properties": { "fill_id": { "$ref": "#/$defs/identifier" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" }, "notional": { "$ref": "#/$defs/positiveDecimal" }, "fee": { "$ref": "#/$defs/unsignedDecimal" }, "executed_at": { "$ref": "#/$defs/timestamp" }, "slice_sequence": { "$ref": "#/$defs/sequence" } } - }, - "quantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "moneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "ratioThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "basisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "fillClipReason": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_order_quantity" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_long_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_short_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_gross_exposure" }, "threshold": { "$ref": "#/$defs/moneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_leverage" }, "threshold": { "$ref": "#/$defs/ratioThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "initial_margin" }, "threshold": { "$ref": "#/$defs/basisPointsThreshold" } } } - ] - }, - "fillClipped": { - "type": "object", "additionalProperties": false, "required": ["reason", "order_id", "instrument_id", "proposed_quantity", "permitted_quantity", "price"], - "properties": { "reason": { "$ref": "#/$defs/fillClipReason" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "proposed_quantity": { "$ref": "#/$defs/positiveDecimal" }, "permitted_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" } } - }, - "borrowFee": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "quote_currency", "short_quantity", "reference_price", "borrow_bps", "period_start", "period_end", "fee"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "short_quantity": { "$ref": "#/$defs/positiveDecimal" }, "reference_price": { "$ref": "#/$defs/positiveDecimal" }, "borrow_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, "period_start": { "$ref": "#/$defs/timestamp" }, "period_end": { "$ref": "#/$defs/timestamp" }, "fee": { "$ref": "#/$defs/positiveDecimal" } } - }, - "cashAttribution": { - "type": "object", "additionalProperties": false, "required": ["currency", "amount", "fx_rate", "base_value"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "base_value": { "$ref": "#/$defs/signedDecimal" } } - }, - "positionAttribution": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quote_currency", "quantity", "mark", "fx_rate", "market_value", "base_market_value", "cost_basis", "base_cost_basis", "realized_pnl", "base_realized_pnl", "unrealized_pnl", "base_unrealized_pnl", "dividend_pnl", "base_dividend_pnl", "execution_fees", "base_execution_fees", "borrow_fees", "base_borrow_fees", "total_fees", "base_total_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "mark": { "$ref": "#/$defs/positiveDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "market_value": { "$ref": "#/$defs/signedDecimal" }, "base_market_value": { "$ref": "#/$defs/signedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "base_cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_total_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "margin": { - "type": "object", "additionalProperties": false, "required": ["initial_requirement", "maintenance_requirement", "initial_excess", "maintenance_excess", "margin_call"], - "properties": { "initial_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "maintenance_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "initial_excess": { "$ref": "#/$defs/signedDecimal" }, "maintenance_excess": { "$ref": "#/$defs/signedDecimal" }, "margin_call": { "type": "boolean" } } - }, - "valuation": { - "type": "object", "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "cost_basis", "realized_pnl", "unrealized_pnl", "equity", "dividend_pnl", "execution_fees", "borrow_fees", "total_fees", "cash_balances", "positions", "margin"], - "properties": { - "base_currency": { "$ref": "#/$defs/identifier" }, "cash": { "$ref": "#/$defs/signedDecimal" }, "net_market_value": { "$ref": "#/$defs/signedDecimal" }, "long_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "short_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "equity": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashAttribution" } }, "positions": { "type": "array", "items": { "$ref": "#/$defs/positionAttribution" } }, "margin": { "$ref": "#/$defs/margin" } - } - }, - "intentRejected": { "type": "object", "additionalProperties": false, "required": ["reason"], "properties": { "reason": { "type": "string", "minLength": 1 } } }, - "metric": { "type": "object", "additionalProperties": false, "required": ["name", "value"], "properties": { "name": { "type": "string" }, "value": { "type": "string" } } }, - "runCompleted": { - "type": "object", "additionalProperties": false, "required": ["scenario_sha256", "execution_model", "valuation", "order_counts"], - "properties": { - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" }, "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "type": "object", "additionalProperties": false, "required": ["total", "active", "filled", "rejected", "cancelled"], "properties": { "total": { "type": "integer", "minimum": 0 }, "active": { "type": "integer", "minimum": 0 }, "filled": { "type": "integer", "minimum": 0 }, "rejected": { "type": "integer", "minimum": 0 }, "cancelled": { "type": "integer", "minimum": 0 } } } - } - } - } -} diff --git a/contracts/v5/scenario-stream.schema.json b/contracts/v5/scenario-stream.schema.json deleted file mode 100644 index 87d151a..0000000 --- a/contracts/v5/scenario-stream.schema.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v5/scenario-stream.schema.json", - "title": "Trading Engine v5 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "5" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "5" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "5" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_cash", "instruments", "venue_calendars", "risk", "execution", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/identifier" }, - "initial_cash": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/cashBalance" } }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v5/scenario.schema.json b/contracts/v5/scenario.schema.json deleted file mode 100644 index f9696da..0000000 --- a/contracts/v5/scenario.schema.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v5/scenario.schema.json", - "title": "Trading Engine v5 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_cash", "instruments", "venue_calendars", "risk", "execution", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "5" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_cash": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/cashBalance" } - }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_order_quantity", "max_long_position", "max_short_position", "max_gross_exposure", "max_leverage", "initial_margin_bps", "maintenance_margin_bps", "short_borrow_bps"], - "properties": { - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fixed_fee", "fee_bps"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "limit_price"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit"] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } - } - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v6/README.md b/contracts/v6/README.md deleted file mode 100644 index ff1bd28..0000000 --- a/contracts/v6/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Trading Engine contract v6 - -This directory is the authoritative v6 process and file contract shared by Trading Engine and its -clients. Versions 5, 4, and 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 6 replaces cash-only initialization with an explicit portfolio snapshot. It carries signed -cash, signed positions, native cost basis, realized and dividend P&L histories, execution and -borrow fee histories, position marks, and currency-to-base FX marks. Historical attribution is -point-in-time state and is not applied to cash again. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; position limits; aggregate exposure and -leverage limits; and initial margin. Signed cash is valid. A successful v6 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Version 6 retains the immutable venue-calendar and model-owned execution-configuration envelopes -introduced by v5. - -Every v6 scenario, stream record, and journal record carries `"contract_version": "6"`. - -The v6 `execution` object namespaces strict configuration beneath the stable model name. -`completed_bar_v1` configuration version `"1"` requires participation basis points, fixed fee, -and fee basis points. Runtime capabilities describe its required fields, supported market and limit -orders, completed-OHLCV data requirement, and numeric limits. diff --git a/contracts/v6/dune b/contracts/v6/dune deleted file mode 100644 index 1bf8fd9..0000000 --- a/contracts/v6/dune +++ /dev/null @@ -1,16 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v6/journal.schema.json) - (scenario-stream.schema.json as contracts/v6/scenario-stream.schema.json) - (scenario.schema.json as contracts/v6/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v6/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v6/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v6/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v6/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v6/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v6/fixtures/demo.journal.jsonl b/contracts/v6/fixtures/demo.journal.jsonl deleted file mode 100644 index c9cca94..0000000 --- a/contracts/v6/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,22 +0,0 @@ -{"contract_version":"6","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"c98534261412acebf4b49d87619dc7c951538581c2a7dd05f315eb64d761cec2","execution_model":"completed_bar_v1"}} -{"contract_version":"6","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false}}}} -{"contract_version":"6","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false}}} -{"contract_version":"6","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"6","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"6","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"6","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004","demo-event-000000000005"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"6","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"14","equity":"10104","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052","maintenance_excess":"10078","margin_call":false}}} -{"contract_version":"6","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"6","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"6","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"6","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000005","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.715","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000012","updated_event_id":"demo-event-000000000012","created_sequence":"12","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"6","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.132","net_market_value":"749","long_market_value":"749","short_market_value":"0","gross_exposure":"749","cost_basis":"708.868","realized_pnl":"5","unrealized_pnl":"40.132","equity":"10130.132","dividend_pnl":"1","execution_fees":"1.368","borrow_fees":"0.25","total_fees":"1.618","cash_balances":[{"currency":"USD","amount":"9381.132","fx_rate":"1","base_value":"9381.132"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7","mark":"107","fx_rate":"1","market_value":"749","base_market_value":"749","cost_basis":"708.868","base_cost_basis":"708.868","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.132","base_unrealized_pnl":"40.132","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.368","base_execution_fees":"1.368","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.618","base_total_fees":"1.618"}],"margin":{"initial_requirement":"374.5","maintenance_requirement":"187.25","initial_excess":"9755.632","maintenance_excess":"9942.882","margin_call":false}}} -{"contract_version":"6","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"6","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.715","price":"107","notional":"290.505","fee":"0.540505","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"6","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"6","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":["demo-event-000000000014","demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000017","updated_event_id":"demo-event-000000000017","created_sequence":"17","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"6","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.086495","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.913505","realized_pnl":"5","unrealized_pnl":"20.161495","equity":"10110.161495","dividend_pnl":"1","execution_fees":"1.908505","borrow_fees":"0.25","total_fees":"2.158505","cash_balances":[{"currency":"USD","amount":"9090.086495","fx_rate":"1","base_value":"9090.086495"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.913505","base_cost_basis":"999.913505","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.161495","base_unrealized_pnl":"20.161495","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.908505","base_execution_fees":"1.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.158505","base_total_fees":"2.158505"}],"margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.123995","maintenance_excess":"9855.142745","margin_call":false}}} -{"contract_version":"6","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"6","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000017","demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"105","notional":"757.575","fee":"1.007575","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"6","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.65392","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.965682","unrealized_pnl":"7.688238","equity":"10111.65392","dividend_pnl":"1","execution_fees":"2.91608","borrow_fees":"0.25","total_fees":"3.16608","cash_balances":[{"currency":"USD","amount":"9846.65392","fx_rate":"1","base_value":"9846.65392"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.965682","base_realized_pnl":"18.965682","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.91608","base_execution_fees":"2.91608","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.16608","base_total_fees":"3.16608"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.15392","maintenance_excess":"10045.40392","margin_call":false}}} -{"contract_version":"6","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"c98534261412acebf4b49d87619dc7c951538581c2a7dd05f315eb64d761cec2","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9846.65392","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.965682","unrealized_pnl":"7.688238","equity":"10111.65392","dividend_pnl":"1","execution_fees":"2.91608","borrow_fees":"0.25","total_fees":"3.16608","cash_balances":[{"currency":"USD","amount":"9846.65392","fx_rate":"1","base_value":"9846.65392"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.965682","base_realized_pnl":"18.965682","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.91608","base_execution_fees":"2.91608","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.16608","base_total_fees":"3.16608"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.15392","maintenance_excess":"10045.40392","margin_call":false}},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v6/fixtures/demo.scenario.json b/contracts/v6/fixtures/demo.scenario.json deleted file mode 100644 index 5b4303c..0000000 --- a/contracts/v6/fixtures/demo.scenario.json +++ /dev/null @@ -1,294 +0,0 @@ -{ - "contract_version": "6", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000", - "max_leverage": "2", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 100 - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v6/fixtures/demo.scenario.jsonl b/contracts/v6/fixtures/demo.scenario.jsonl deleted file mode 100644 index 712bef4..0000000 --- a/contracts/v6/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"6","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_gross_exposure":"1000000","max_leverage":"2","initial_margin_bps":5000,"maintenance_margin_bps":2500,"short_borrow_bps":100},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"max_internal_events":1000}} -{"contract_version":"6","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"6","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"6","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"6","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"6","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v6/fixtures/fill-clipped.journal.jsonl b/contracts/v6/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 14bd262..0000000 --- a/contracts/v6/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,12 +0,0 @@ -{"contract_version":"6","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"0ba5499f954080438421e7bf439a0258214392ab6baab7d69015d8c622d5c04c","execution_model":"completed_bar_v1"}} -{"contract_version":"6","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false}}}} -{"contract_version":"6","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false}}} -{"contract_version":"6","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"6","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"6","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false}}} -{"contract_version":"6","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"6","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"5","price":"100"}} -{"contract_version":"6","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"fill-clipped-fill-000000000001","order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","quote_currency":"USD","side":"buy","quantity":"5","price":"100","notional":"500","fee":"10","executed_at":"2026-02-03T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"6","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"5","filled_notional":"500","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"6","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"40","net_market_value":"500","long_market_value":"500","short_market_value":"0","gross_exposure":"500","cost_basis":"510","realized_pnl":"0","unrealized_pnl":"-10","equity":"540","dividend_pnl":"0","execution_fees":"10","borrow_fees":"0","total_fees":"10","cash_balances":[{"currency":"USD","amount":"40","fx_rate":"1","base_value":"40"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"5","mark":"100","fx_rate":"1","market_value":"500","base_market_value":"500","cost_basis":"510","base_cost_basis":"510","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-10","base_unrealized_pnl":"-10","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"10","base_execution_fees":"10","borrow_fees":"0","base_borrow_fees":"0","total_fees":"10","base_total_fees":"10"}],"margin":{"initial_requirement":"250","maintenance_requirement":"125","initial_excess":"290","maintenance_excess":"415","margin_call":false}}} -{"contract_version":"6","engine_sequence":"12","event_id":"fill-clipped-event-000000000012","causation_ids":["fill-clipped-event-000000000011"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"0ba5499f954080438421e7bf439a0258214392ab6baab7d69015d8c622d5c04c","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"40","net_market_value":"500","long_market_value":"500","short_market_value":"0","gross_exposure":"500","cost_basis":"510","realized_pnl":"0","unrealized_pnl":"-10","equity":"540","dividend_pnl":"0","execution_fees":"10","borrow_fees":"0","total_fees":"10","cash_balances":[{"currency":"USD","amount":"40","fx_rate":"1","base_value":"40"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"5","mark":"100","fx_rate":"1","market_value":"500","base_market_value":"500","cost_basis":"510","base_cost_basis":"510","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"-10","base_unrealized_pnl":"-10","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"10","base_execution_fees":"10","borrow_fees":"0","base_borrow_fees":"0","total_fees":"10","base_total_fees":"10"}],"margin":{"initial_requirement":"250","maintenance_requirement":"125","initial_excess":"290","maintenance_excess":"415","margin_call":false}},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v6/fixtures/fill-clipped.scenario.json b/contracts/v6/fixtures/fill-clipped.scenario.json deleted file mode 100644 index b72cefa..0000000 --- a/contracts/v6/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "contract_version": "6", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "short_borrow_bps": 100 - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 10000, - "fixed_fee": "10", - "fee_bps": 0 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "limit_price": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v6/journal.schema.json b/contracts/v6/journal.schema.json deleted file mode 100644 index 0203411..0000000 --- a/contracts/v6/journal.schema.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v6/journal.schema.json", - "title": "Trading Engine v6 audit journal record", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "engine_sequence", "event_id", "causation_ids", "run_id", "recorded_at", "event_type", "payload"], - "properties": { - "contract_version": { "const": "6" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/identifier" } }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": ["run_started", "initial_state", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", "order_cancelled", "split_applied", "cash_dividend_applied", "order_adjusted", "fill_applied", "fill_clipped", "borrow_fee_applied", "margin_call", "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed"] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { "if": { "properties": { "event_type": { "const": "run_started" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } }, - { "if": { "properties": { "event_type": { "const": "initial_state" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/initialState" } } } }, - { "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } }, - { "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } }, - { "if": { "properties": { "event_type": { "enum": ["order_accepted", "order_rejected"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } }, - { "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } }, - { "if": { "properties": { "event_type": { "const": "split_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/splitApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "cash_dividend_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/dividendApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "order_adjusted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderAdjusted" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_clipped" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fillClipped" } } } }, - { "if": { "properties": { "event_type": { "const": "borrow_fee_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/borrowFee" } } } }, - { "if": { "properties": { "event_type": { "enum": ["margin_call", "margin_restored", "valuation"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } }, - { "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } }, - { "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } }, - { "if": { "properties": { "event_type": { "const": "run_completed" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } } - ], - "$defs": { - "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "signedDecimal": { "type": "string", "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "unsignedDecimal": { "type": "string", "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "runStarted": { - "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" } } - }, - "initialState": { - "type": "object", "additionalProperties": false, - "required": ["portfolio", "valuation"], - "properties": { - "portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/initialPortfolio" }, - "valuation": { "$ref": "#/$defs/valuation" } - } - }, - "bar": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "open": { "$ref": "#/$defs/positiveDecimal" }, "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", "additionalProperties": false, "required": ["currency", "rate"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "rate": { "$ref": "#/$defs/positiveDecimal" } } - }, - "corporateAction": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], "properties": { "type": { "const": "split" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "numerator": { "$ref": "#/$defs/sequence" }, "denominator": { "$ref": "#/$defs/sequence" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "amount_per_unit"], "properties": { "type": { "const": "cash_dividend" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } } } - ] - }, - "marketSlice": { - "type": "object", "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "targetPortfolio": { - "type": "object", "additionalProperties": false, "required": ["basis", "targets"], - "properties": { - "basis": { "enum": ["weights", "quantities"] }, - "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["instrument_id", "weight", "quantity", "reference_price"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "weight": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/signedDecimal" }] }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "reference_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } } } } - } - }, - "order": { - "type": "object", "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "quantity", "order_kind", "limit_price", "origin", "created_event_id", "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "order_kind": { "enum": ["market", "limit"] }, "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "origin": { "enum": ["direct", "target_rebalance", "margin_liquidation"] }, "created_event_id": { "$ref": "#/$defs/identifier" }, "updated_event_id": { "$ref": "#/$defs/identifier" }, "created_sequence": { "$ref": "#/$defs/sequence" }, "created_at": { "$ref": "#/$defs/timestamp" }, "eligible_after_slice_sequence": { "$ref": "#/$defs/nonnegativeSequence" }, "filled_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, "status": { "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] }, "rejection_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1 }] } - } - }, - "orderCancelled": { - "type": "object", "additionalProperties": false, "required": ["order", "reason"], - "properties": { "order": { "$ref": "#/$defs/order" }, "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc", "margin_call"] } } - }, - "splitApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "previous_quantity", "adjusted_quantity"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "previous_quantity": { "$ref": "#/$defs/signedDecimal" }, "adjusted_quantity": { "$ref": "#/$defs/signedDecimal" } } - }, - "dividendApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "quantity", "cash_amount"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "cash_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "orderAdjusted": { - "type": "object", "additionalProperties": false, "required": ["order", "action_id"], - "properties": { "order": { "$ref": "#/$defs/order" }, "action_id": { "$ref": "#/$defs/identifier" } } - }, - "fill": { - "type": "object", "additionalProperties": false, - "required": ["fill_id", "order_id", "instrument_id", "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", "slice_sequence"], - "properties": { "fill_id": { "$ref": "#/$defs/identifier" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" }, "notional": { "$ref": "#/$defs/positiveDecimal" }, "fee": { "$ref": "#/$defs/unsignedDecimal" }, "executed_at": { "$ref": "#/$defs/timestamp" }, "slice_sequence": { "$ref": "#/$defs/sequence" } } - }, - "quantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "moneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "ratioThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "basisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "fillClipReason": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_order_quantity" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_long_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_short_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_gross_exposure" }, "threshold": { "$ref": "#/$defs/moneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_leverage" }, "threshold": { "$ref": "#/$defs/ratioThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "initial_margin" }, "threshold": { "$ref": "#/$defs/basisPointsThreshold" } } } - ] - }, - "fillClipped": { - "type": "object", "additionalProperties": false, "required": ["reason", "order_id", "instrument_id", "proposed_quantity", "permitted_quantity", "price"], - "properties": { "reason": { "$ref": "#/$defs/fillClipReason" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "proposed_quantity": { "$ref": "#/$defs/positiveDecimal" }, "permitted_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" } } - }, - "borrowFee": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "quote_currency", "short_quantity", "reference_price", "borrow_bps", "period_start", "period_end", "fee"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "short_quantity": { "$ref": "#/$defs/positiveDecimal" }, "reference_price": { "$ref": "#/$defs/positiveDecimal" }, "borrow_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, "period_start": { "$ref": "#/$defs/timestamp" }, "period_end": { "$ref": "#/$defs/timestamp" }, "fee": { "$ref": "#/$defs/positiveDecimal" } } - }, - "cashAttribution": { - "type": "object", "additionalProperties": false, "required": ["currency", "amount", "fx_rate", "base_value"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "base_value": { "$ref": "#/$defs/signedDecimal" } } - }, - "positionAttribution": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quote_currency", "quantity", "mark", "fx_rate", "market_value", "base_market_value", "cost_basis", "base_cost_basis", "realized_pnl", "base_realized_pnl", "unrealized_pnl", "base_unrealized_pnl", "dividend_pnl", "base_dividend_pnl", "execution_fees", "base_execution_fees", "borrow_fees", "base_borrow_fees", "total_fees", "base_total_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "mark": { "$ref": "#/$defs/positiveDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "market_value": { "$ref": "#/$defs/signedDecimal" }, "base_market_value": { "$ref": "#/$defs/signedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "base_cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_total_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "margin": { - "type": "object", "additionalProperties": false, "required": ["initial_requirement", "maintenance_requirement", "initial_excess", "maintenance_excess", "margin_call"], - "properties": { "initial_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "maintenance_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "initial_excess": { "$ref": "#/$defs/signedDecimal" }, "maintenance_excess": { "$ref": "#/$defs/signedDecimal" }, "margin_call": { "type": "boolean" } } - }, - "valuation": { - "type": "object", "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "cost_basis", "realized_pnl", "unrealized_pnl", "equity", "dividend_pnl", "execution_fees", "borrow_fees", "total_fees", "cash_balances", "positions", "margin"], - "properties": { - "base_currency": { "$ref": "#/$defs/identifier" }, "cash": { "$ref": "#/$defs/signedDecimal" }, "net_market_value": { "$ref": "#/$defs/signedDecimal" }, "long_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "short_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "equity": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashAttribution" } }, "positions": { "type": "array", "items": { "$ref": "#/$defs/positionAttribution" } }, "margin": { "$ref": "#/$defs/margin" } - } - }, - "intentRejected": { "type": "object", "additionalProperties": false, "required": ["reason"], "properties": { "reason": { "type": "string", "minLength": 1 } } }, - "metric": { "type": "object", "additionalProperties": false, "required": ["name", "value"], "properties": { "name": { "type": "string" }, "value": { "type": "string" } } }, - "runCompleted": { - "type": "object", "additionalProperties": false, "required": ["scenario_sha256", "execution_model", "valuation", "order_counts"], - "properties": { - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" }, "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "type": "object", "additionalProperties": false, "required": ["total", "active", "filled", "rejected", "cancelled"], "properties": { "total": { "type": "integer", "minimum": 0 }, "active": { "type": "integer", "minimum": 0 }, "filled": { "type": "integer", "minimum": 0 }, "rejected": { "type": "integer", "minimum": 0 }, "cancelled": { "type": "integer", "minimum": 0 } } } - } - } - } -} diff --git a/contracts/v6/scenario-stream.schema.json b/contracts/v6/scenario-stream.schema.json deleted file mode 100644 index f70b604..0000000 --- a/contracts/v6/scenario-stream.schema.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v6/scenario-stream.schema.json", - "title": "Trading Engine v6 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "6" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "6" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "6" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v6/scenario.schema.json b/contracts/v6/scenario.schema.json deleted file mode 100644 index d5e75ea..0000000 --- a/contracts/v6/scenario.schema.json +++ /dev/null @@ -1,369 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v6/scenario.schema.json", - "title": "Trading Engine v6 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "6" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_order_quantity", "max_long_position", "max_short_position", "max_gross_exposure", "max_leverage", "initial_margin_bps", "maintenance_margin_bps", "short_borrow_bps"], - "properties": { - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fixed_fee", "fee_bps"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "limit_price"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit"] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } - } - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v7/README.md b/contracts/v7/README.md deleted file mode 100644 index 1ec393d..0000000 --- a/contracts/v7/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Trading Engine contract v7 - -This directory is the authoritative v7 process and file contract shared by Trading Engine and its -clients. Versions 6, 5, 4, and 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v7 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v7 scenario, stream record, and journal record carries `"contract_version": "7"`. - -The v7 `execution` object retains the versioned configuration introduced by v5. -`completed_bar_v1` configuration version `"1"` requires participation basis points, fixed fee, -and fee basis points. Runtime capabilities describe its required fields, supported market and limit -orders, completed-OHLCV data requirement, and numeric limits. diff --git a/contracts/v7/dune b/contracts/v7/dune deleted file mode 100644 index 4497ccd..0000000 --- a/contracts/v7/dune +++ /dev/null @@ -1,16 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v7/journal.schema.json) - (scenario-stream.schema.json as contracts/v7/scenario-stream.schema.json) - (scenario.schema.json as contracts/v7/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v7/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v7/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v7/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v7/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v7/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v7/fixtures/demo.journal.jsonl b/contracts/v7/fixtures/demo.journal.jsonl deleted file mode 100644 index acf860e..0000000 --- a/contracts/v7/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,22 +0,0 @@ -{"contract_version":"7","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"d1991fa67140bff80fcbeb9b04b211d8c9cf4f41d4fba39dcec66d5ef3e5fab9","execution_model":"completed_bar_v1"}} -{"contract_version":"7","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"7","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"7","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"7","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"7","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004","demo-event-000000000005"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"7","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"14","equity":"10104","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052","maintenance_excess":"10078","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"7","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"7","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"7","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000005","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.715","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000012","updated_event_id":"demo-event-000000000012","created_sequence":"12","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"7","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.132","net_market_value":"749","long_market_value":"749","short_market_value":"0","gross_exposure":"749","cost_basis":"708.868","realized_pnl":"5","unrealized_pnl":"40.132","equity":"10130.132","dividend_pnl":"1","execution_fees":"1.368","borrow_fees":"0.25","total_fees":"1.618","cash_balances":[{"currency":"USD","amount":"9381.132","fx_rate":"1","base_value":"9381.132"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7","mark":"107","fx_rate":"1","market_value":"749","base_market_value":"749","cost_basis":"708.868","base_cost_basis":"708.868","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.132","base_unrealized_pnl":"40.132","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.368","base_execution_fees":"1.368","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.618","base_total_fees":"1.618"}],"margin":{"initial_requirement":"374.5","maintenance_requirement":"187.25","initial_excess":"9755.632","maintenance_excess":"9942.882","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"7","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.715","price":"107","notional":"290.505","fee":"0.540505","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"7","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"7","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":["demo-event-000000000014","demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","limit_price":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000017","updated_event_id":"demo-event-000000000017","created_sequence":"17","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"7","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.086495","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.913505","realized_pnl":"5","unrealized_pnl":"20.161495","equity":"10110.161495","dividend_pnl":"1","execution_fees":"1.908505","borrow_fees":"0.25","total_fees":"2.158505","cash_balances":[{"currency":"USD","amount":"9090.086495","fx_rate":"1","base_value":"9090.086495"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.913505","base_cost_basis":"999.913505","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.161495","base_unrealized_pnl":"20.161495","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.908505","base_execution_fees":"1.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.158505","base_total_fees":"2.158505"}],"margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.123995","maintenance_excess":"9855.142745","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"7","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000017","demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"105","notional":"757.575","fee":"1.007575","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"7","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.65392","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.965682","unrealized_pnl":"7.688238","equity":"10111.65392","dividend_pnl":"1","execution_fees":"2.91608","borrow_fees":"0.25","total_fees":"3.16608","cash_balances":[{"currency":"USD","amount":"9846.65392","fx_rate":"1","base_value":"9846.65392"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.965682","base_realized_pnl":"18.965682","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.91608","base_execution_fees":"2.91608","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.16608","base_total_fees":"3.16608"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.15392","maintenance_excess":"10045.40392","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"d1991fa67140bff80fcbeb9b04b211d8c9cf4f41d4fba39dcec66d5ef3e5fab9","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9846.65392","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.965682","unrealized_pnl":"7.688238","equity":"10111.65392","dividend_pnl":"1","execution_fees":"2.91608","borrow_fees":"0.25","total_fees":"3.16608","cash_balances":[{"currency":"USD","amount":"9846.65392","fx_rate":"1","base_value":"9846.65392"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.965682","base_realized_pnl":"18.965682","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.91608","base_execution_fees":"2.91608","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.16608","base_total_fees":"3.16608"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.15392","maintenance_excess":"10045.40392","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v7/fixtures/demo.scenario.json b/contracts/v7/fixtures/demo.scenario.json deleted file mode 100644 index 7ad99d3..0000000 --- a/contracts/v7/fixtures/demo.scenario.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "contract_version": "7", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v7/fixtures/demo.scenario.jsonl b/contracts/v7/fixtures/demo.scenario.jsonl deleted file mode 100644 index 6bd7435..0000000 --- a/contracts/v7/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"7","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"max_internal_events":1000}} -{"contract_version":"7","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"7","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"7","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"7","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"7","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v7/fixtures/fill-clipped.journal.jsonl b/contracts/v7/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 678ea43..0000000 --- a/contracts/v7/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,11 +0,0 @@ -{"contract_version":"7","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"61f1319c6667400bec59562d106b580a7607e97fa3f1d837018ac7c4f38cc6bb","execution_model":"completed_bar_v1"}} -{"contract_version":"7","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"7","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"7","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"7","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"7","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"7","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","limit_price":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"7","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"7","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000010"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"61f1319c6667400bec59562d106b580a7607e97fa3f1d837018ac7c4f38cc6bb","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v7/fixtures/fill-clipped.scenario.json b/contracts/v7/fixtures/fill-clipped.scenario.json deleted file mode 100644 index 159d2e4..0000000 --- a/contracts/v7/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,172 +0,0 @@ -{ - "contract_version": "7", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 10000, - "fixed_fee": "10", - "fee_bps": 0 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "limit_price": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v7/journal.schema.json b/contracts/v7/journal.schema.json deleted file mode 100644 index 808db61..0000000 --- a/contracts/v7/journal.schema.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v7/journal.schema.json", - "title": "Trading Engine v6 audit journal record", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "engine_sequence", "event_id", "causation_ids", "run_id", "recorded_at", "event_type", "payload"], - "properties": { - "contract_version": { "const": "7" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/identifier" } }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": ["run_started", "initial_state", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", "order_cancelled", "split_applied", "cash_dividend_applied", "order_adjusted", "fill_applied", "fill_clipped", "borrow_fee_applied", "margin_call", "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed"] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { "if": { "properties": { "event_type": { "const": "run_started" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } }, - { "if": { "properties": { "event_type": { "const": "initial_state" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/initialState" } } } }, - { "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } }, - { "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } }, - { "if": { "properties": { "event_type": { "enum": ["order_accepted", "order_rejected"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } }, - { "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } }, - { "if": { "properties": { "event_type": { "const": "split_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/splitApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "cash_dividend_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/dividendApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "order_adjusted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderAdjusted" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_clipped" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fillClipped" } } } }, - { "if": { "properties": { "event_type": { "const": "borrow_fee_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/borrowFee" } } } }, - { "if": { "properties": { "event_type": { "enum": ["margin_call", "margin_restored", "valuation"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } }, - { "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } }, - { "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } }, - { "if": { "properties": { "event_type": { "const": "run_completed" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } } - ], - "$defs": { - "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "signedDecimal": { "type": "string", "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "unsignedDecimal": { "type": "string", "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "runStarted": { - "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" } } - }, - "initialState": { - "type": "object", "additionalProperties": false, - "required": ["portfolio", "valuation"], - "properties": { - "portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/initialPortfolio" }, - "valuation": { "$ref": "#/$defs/valuation" } - } - }, - "bar": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "open": { "$ref": "#/$defs/positiveDecimal" }, "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", "additionalProperties": false, "required": ["currency", "rate"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "rate": { "$ref": "#/$defs/positiveDecimal" } } - }, - "corporateAction": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], "properties": { "type": { "const": "split" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "numerator": { "$ref": "#/$defs/sequence" }, "denominator": { "$ref": "#/$defs/sequence" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "amount_per_unit"], "properties": { "type": { "const": "cash_dividend" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } } } - ] - }, - "marketSlice": { - "type": "object", "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "targetPortfolio": { - "type": "object", "additionalProperties": false, "required": ["basis", "targets"], - "properties": { - "basis": { "enum": ["weights", "quantities"] }, - "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["instrument_id", "weight", "quantity", "reference_price"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "weight": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/signedDecimal" }] }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "reference_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } } } } - } - }, - "order": { - "type": "object", "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "quantity", "order_kind", "limit_price", "origin", "created_event_id", "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "order_kind": { "enum": ["market", "limit"] }, "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "origin": { "enum": ["direct", "target_rebalance", "margin_liquidation"] }, "created_event_id": { "$ref": "#/$defs/identifier" }, "updated_event_id": { "$ref": "#/$defs/identifier" }, "created_sequence": { "$ref": "#/$defs/sequence" }, "created_at": { "$ref": "#/$defs/timestamp" }, "eligible_after_slice_sequence": { "$ref": "#/$defs/nonnegativeSequence" }, "filled_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, "status": { "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] }, "rejection_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1 }] } - } - }, - "orderCancelled": { - "type": "object", "additionalProperties": false, "required": ["order", "reason"], - "properties": { "order": { "$ref": "#/$defs/order" }, "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc", "margin_call"] } } - }, - "splitApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "previous_quantity", "adjusted_quantity"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "previous_quantity": { "$ref": "#/$defs/signedDecimal" }, "adjusted_quantity": { "$ref": "#/$defs/signedDecimal" } } - }, - "dividendApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "quantity", "cash_amount"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "cash_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "orderAdjusted": { - "type": "object", "additionalProperties": false, "required": ["order", "action_id"], - "properties": { "order": { "$ref": "#/$defs/order" }, "action_id": { "$ref": "#/$defs/identifier" } } - }, - "fill": { - "type": "object", "additionalProperties": false, - "required": ["fill_id", "order_id", "instrument_id", "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", "slice_sequence"], - "properties": { "fill_id": { "$ref": "#/$defs/identifier" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" }, "notional": { "$ref": "#/$defs/positiveDecimal" }, "fee": { "$ref": "#/$defs/unsignedDecimal" }, "executed_at": { "$ref": "#/$defs/timestamp" }, "slice_sequence": { "$ref": "#/$defs/sequence" } } - }, - "quantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "moneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "ratioThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "basisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "instrumentQuantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "instrumentMoneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "instrumentBasisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "instrumentShortingThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "value": { "const": false } } - }, - "groupMoneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["group_id", "unit", "value"], - "properties": { "group_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "groupRatioThreshold": { - "type": "object", "additionalProperties": false, "required": ["group_id", "unit", "value"], - "properties": { "group_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "fillClipReason": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_order_quantity" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_long_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_short_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_gross_exposure" }, "threshold": { "$ref": "#/$defs/moneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_leverage" }, "threshold": { "$ref": "#/$defs/ratioThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "initial_margin" }, "threshold": { "$ref": "#/$defs/basisPointsThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_long_position" }, "threshold": { "$ref": "#/$defs/instrumentQuantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_short_position" }, "threshold": { "$ref": "#/$defs/instrumentQuantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_notional_exposure" }, "threshold": { "$ref": "#/$defs/instrumentMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_shorting_disabled" }, "threshold": { "$ref": "#/$defs/instrumentShortingThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_initial_margin" }, "threshold": { "$ref": "#/$defs/instrumentBasisPointsThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_gross_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_long_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_short_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_absolute_net_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_concentration" }, "threshold": { "$ref": "#/$defs/groupRatioThreshold" } } } - ] - }, - "fillClipped": { - "type": "object", "additionalProperties": false, "required": ["reason", "order_id", "instrument_id", "proposed_quantity", "permitted_quantity", "price"], - "properties": { "reason": { "$ref": "#/$defs/fillClipReason" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "proposed_quantity": { "$ref": "#/$defs/positiveDecimal" }, "permitted_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" } } - }, - "borrowFee": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "quote_currency", "short_quantity", "reference_price", "borrow_bps", "period_start", "period_end", "fee"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "short_quantity": { "$ref": "#/$defs/positiveDecimal" }, "reference_price": { "$ref": "#/$defs/positiveDecimal" }, "borrow_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, "period_start": { "$ref": "#/$defs/timestamp" }, "period_end": { "$ref": "#/$defs/timestamp" }, "fee": { "$ref": "#/$defs/positiveDecimal" } } - }, - "cashAttribution": { - "type": "object", "additionalProperties": false, "required": ["currency", "amount", "fx_rate", "base_value"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "base_value": { "$ref": "#/$defs/signedDecimal" } } - }, - "positionAttribution": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quote_currency", "quantity", "mark", "fx_rate", "market_value", "base_market_value", "cost_basis", "base_cost_basis", "realized_pnl", "base_realized_pnl", "unrealized_pnl", "base_unrealized_pnl", "dividend_pnl", "base_dividend_pnl", "execution_fees", "base_execution_fees", "borrow_fees", "base_borrow_fees", "total_fees", "base_total_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "mark": { "$ref": "#/$defs/positiveDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "market_value": { "$ref": "#/$defs/signedDecimal" }, "base_market_value": { "$ref": "#/$defs/signedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "base_cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_total_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "margin": { - "type": "object", "additionalProperties": false, "required": ["initial_requirement", "maintenance_requirement", "initial_excess", "maintenance_excess", "margin_call"], - "properties": { "initial_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "maintenance_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "initial_excess": { "$ref": "#/$defs/signedDecimal" }, "maintenance_excess": { "$ref": "#/$defs/signedDecimal" }, "margin_call": { "type": "boolean" } } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "gross_exposure", "net_exposure", "long_exposure", "short_exposure", "concentration"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "net_exposure": { "$ref": "#/$defs/signedDecimal" }, - "long_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "short_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "concentration": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/signedDecimal" } - ] - } - } - }, - "valuation": { - "type": "object", "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "cost_basis", "realized_pnl", "unrealized_pnl", "equity", "dividend_pnl", "execution_fees", "borrow_fees", "total_fees", "cash_balances", "positions", "margin", "group_exposures"], - "properties": { - "base_currency": { "$ref": "#/$defs/identifier" }, "cash": { "$ref": "#/$defs/signedDecimal" }, "net_market_value": { "$ref": "#/$defs/signedDecimal" }, "long_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "short_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "equity": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashAttribution" } }, "positions": { "type": "array", "items": { "$ref": "#/$defs/positionAttribution" } }, "margin": { "$ref": "#/$defs/margin" }, "group_exposures": { "type": "array", "items": { "$ref": "#/$defs/groupExposure" } } - } - }, - "intentRejected": { "type": "object", "additionalProperties": false, "required": ["reason"], "properties": { "reason": { "type": "string", "minLength": 1 } } }, - "metric": { "type": "object", "additionalProperties": false, "required": ["name", "value"], "properties": { "name": { "type": "string" }, "value": { "type": "string" } } }, - "runCompleted": { - "type": "object", "additionalProperties": false, "required": ["scenario_sha256", "execution_model", "valuation", "order_counts"], - "properties": { - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" }, "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "type": "object", "additionalProperties": false, "required": ["total", "active", "filled", "rejected", "cancelled"], "properties": { "total": { "type": "integer", "minimum": 0 }, "active": { "type": "integer", "minimum": 0 }, "filled": { "type": "integer", "minimum": 0 }, "rejected": { "type": "integer", "minimum": 0 }, "cancelled": { "type": "integer", "minimum": 0 } } } - } - } - } -} diff --git a/contracts/v7/scenario-stream.schema.json b/contracts/v7/scenario-stream.schema.json deleted file mode 100644 index 90afc77..0000000 --- a/contracts/v7/scenario-stream.schema.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v7/scenario-stream.schema.json", - "title": "Trading Engine v6 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "7" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "7" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "7" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v7/scenario.schema.json b/contracts/v7/scenario.schema.json deleted file mode 100644 index 8dbb6ae..0000000 --- a/contracts/v7/scenario.schema.json +++ /dev/null @@ -1,428 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v7/scenario.schema.json", - "title": "Trading Engine v6 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "7" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fixed_fee", "fee_bps"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "limit_price"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit"] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } - } - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v8/README.md b/contracts/v8/README.md deleted file mode 100644 index b459d5a..0000000 --- a/contracts/v8/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# Trading Engine contract v8 - -This directory is the authoritative v8 process and file contract shared by Trading Engine and its -clients. Versions 7, 6, 5, 4, and 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 8 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v8 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v8 scenario, stream record, and journal record carries `"contract_version": "8"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v8 `execution` object retains the versioned configuration introduced by v5. -`completed_bar_v1` configuration version `"1"` requires participation basis points, fixed fee, -and fee basis points. Runtime capabilities describe its required fields, supported market and limit -orders (including stop and stop-limit), completed-OHLCV data requirement, and numeric limits. diff --git a/contracts/v8/dune b/contracts/v8/dune deleted file mode 100644 index 2f462da..0000000 --- a/contracts/v8/dune +++ /dev/null @@ -1,16 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v8/journal.schema.json) - (scenario-stream.schema.json as contracts/v8/scenario-stream.schema.json) - (scenario.schema.json as contracts/v8/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v8/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v8/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v8/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v8/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v8/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v8/fixtures/demo.journal.jsonl b/contracts/v8/fixtures/demo.journal.jsonl deleted file mode 100644 index 77fb100..0000000 --- a/contracts/v8/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,22 +0,0 @@ -{"contract_version":"8","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"85f7c99e0666159579c79256b3d0dc5f9c328e1275b79465fe1d4c93883e68f1","execution_model":"completed_bar_v1"}} -{"contract_version":"8","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"8","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"8","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"8","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"8","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004","demo-event-000000000005"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"8","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"14","equity":"10104","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75"}],"margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052","maintenance_excess":"10078","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"8","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2"}} -{"contract_version":"8","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"immediate_or_cancel"}} -{"contract_version":"8","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000005","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000012","updated_event_id":"demo-event-000000000012","created_sequence":"12","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"8","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.132","net_market_value":"749","long_market_value":"749","short_market_value":"0","gross_exposure":"749","cost_basis":"708.868","realized_pnl":"5","unrealized_pnl":"40.132","equity":"10130.132","dividend_pnl":"1","execution_fees":"1.368","borrow_fees":"0.25","total_fees":"1.618","cash_balances":[{"currency":"USD","amount":"9381.132","fx_rate":"1","base_value":"9381.132"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7","mark":"107","fx_rate":"1","market_value":"749","base_market_value":"749","cost_basis":"708.868","base_cost_basis":"708.868","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.132","base_unrealized_pnl":"40.132","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.368","base_execution_fees":"1.368","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.618","base_total_fees":"1.618"}],"margin":{"initial_requirement":"374.5","maintenance_requirement":"187.25","initial_excess":"9755.632","maintenance_excess":"9942.882","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"8","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.715","price":"107","notional":"290.505","fee":"0.540505","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3"}} -{"contract_version":"8","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"8","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":["demo-event-000000000014","demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000017","updated_event_id":"demo-event-000000000017","created_sequence":"17","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"8","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.086495","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.913505","realized_pnl":"5","unrealized_pnl":"20.161495","equity":"10110.161495","dividend_pnl":"1","execution_fees":"1.908505","borrow_fees":"0.25","total_fees":"2.158505","cash_balances":[{"currency":"USD","amount":"9090.086495","fx_rate":"1","base_value":"9090.086495"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.913505","base_cost_basis":"999.913505","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.161495","base_unrealized_pnl":"20.161495","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.908505","base_execution_fees":"1.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.158505","base_total_fees":"2.158505"}],"margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.123995","maintenance_excess":"9855.142745","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"8","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000017","demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"105","notional":"757.575","fee":"1.007575","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4"}} -{"contract_version":"8","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.65392","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.965682","unrealized_pnl":"7.688238","equity":"10111.65392","dividend_pnl":"1","execution_fees":"2.91608","borrow_fees":"0.25","total_fees":"3.16608","cash_balances":[{"currency":"USD","amount":"9846.65392","fx_rate":"1","base_value":"9846.65392"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.965682","base_realized_pnl":"18.965682","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.91608","base_execution_fees":"2.91608","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.16608","base_total_fees":"3.16608"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.15392","maintenance_excess":"10045.40392","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"85f7c99e0666159579c79256b3d0dc5f9c328e1275b79465fe1d4c93883e68f1","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9846.65392","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.965682","unrealized_pnl":"7.688238","equity":"10111.65392","dividend_pnl":"1","execution_fees":"2.91608","borrow_fees":"0.25","total_fees":"3.16608","cash_balances":[{"currency":"USD","amount":"9846.65392","fx_rate":"1","base_value":"9846.65392"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.965682","base_realized_pnl":"18.965682","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.91608","base_execution_fees":"2.91608","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.16608","base_total_fees":"3.16608"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.15392","maintenance_excess":"10045.40392","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v8/fixtures/demo.scenario.json b/contracts/v8/fixtures/demo.scenario.json deleted file mode 100644 index ba9ab60..0000000 --- a/contracts/v8/fixtures/demo.scenario.json +++ /dev/null @@ -1,302 +0,0 @@ -{ - "contract_version": "8", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 5000, - "fixed_fee": "0.25", - "fee_bps": 10 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v8/fixtures/demo.scenario.jsonl b/contracts/v8/fixtures/demo.scenario.jsonl deleted file mode 100644 index 3b4f365..0000000 --- a/contracts/v8/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"8","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"1","participation_bps":5000,"fixed_fee":"0.25","fee_bps":10}},"max_internal_events":1000}} -{"contract_version":"8","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"8","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"8","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"8","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"8","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v8/fixtures/fill-clipped.journal.jsonl b/contracts/v8/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 26542b7..0000000 --- a/contracts/v8/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,11 +0,0 @@ -{"contract_version":"8","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"1935c1744a959181894f6610c539e6d3d27ebce56d5737c8286f3e1b4417cb21","execution_model":"completed_bar_v1"}} -{"contract_version":"8","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"8","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"8","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"8","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"8","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"8","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"immediate_or_cancel"}} -{"contract_version":"8","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"8","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000010"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"1935c1744a959181894f6610c539e6d3d27ebce56d5737c8286f3e1b4417cb21","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0"}],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v8/fixtures/fill-clipped.scenario.json b/contracts/v8/fixtures/fill-clipped.scenario.json deleted file mode 100644 index 8f66605..0000000 --- a/contracts/v8/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "contract_version": "8", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "1", - "participation_bps": 10000, - "fixed_fee": "10", - "fee_bps": 0 - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v8/journal.schema.json b/contracts/v8/journal.schema.json deleted file mode 100644 index d7e3107..0000000 --- a/contracts/v8/journal.schema.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v8/journal.schema.json", - "title": "Trading Engine v6 audit journal record", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "engine_sequence", "event_id", "causation_ids", "run_id", "recorded_at", "event_type", "payload"], - "properties": { - "contract_version": { "const": "8" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/identifier" } }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": ["run_started", "initial_state", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", "order_triggered", "order_cancelled", "split_applied", "cash_dividend_applied", "order_adjusted", "fill_applied", "fill_clipped", "borrow_fee_applied", "margin_call", "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed"] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { "if": { "properties": { "event_type": { "const": "run_started" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } }, - { "if": { "properties": { "event_type": { "const": "initial_state" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/initialState" } } } }, - { "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } }, - { "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } }, - { "if": { "properties": { "event_type": { "enum": ["order_accepted", "order_rejected", "order_triggered"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } }, - { "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } }, - { "if": { "properties": { "event_type": { "const": "split_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/splitApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "cash_dividend_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/dividendApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "order_adjusted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderAdjusted" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_clipped" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fillClipped" } } } }, - { "if": { "properties": { "event_type": { "const": "borrow_fee_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/borrowFee" } } } }, - { "if": { "properties": { "event_type": { "enum": ["margin_call", "margin_restored", "valuation"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } }, - { "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } }, - { "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } }, - { "if": { "properties": { "event_type": { "const": "run_completed" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } } - ], - "$defs": { - "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "signedDecimal": { "type": "string", "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "unsignedDecimal": { "type": "string", "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "runStarted": { - "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" } } - }, - "initialState": { - "type": "object", "additionalProperties": false, - "required": ["portfolio", "valuation"], - "properties": { - "portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/initialPortfolio" }, - "valuation": { "$ref": "#/$defs/valuation" } - } - }, - "bar": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "open": { "$ref": "#/$defs/positiveDecimal" }, "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", "additionalProperties": false, "required": ["currency", "rate"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "rate": { "$ref": "#/$defs/positiveDecimal" } } - }, - "corporateAction": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], "properties": { "type": { "const": "split" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "numerator": { "$ref": "#/$defs/sequence" }, "denominator": { "$ref": "#/$defs/sequence" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "amount_per_unit"], "properties": { "type": { "const": "cash_dividend" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } } } - ] - }, - "marketSlice": { - "type": "object", "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "targetPortfolio": { - "type": "object", "additionalProperties": false, "required": ["basis", "targets"], - "properties": { - "basis": { "enum": ["weights", "quantities"] }, - "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["instrument_id", "weight", "quantity", "reference_price"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "weight": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/signedDecimal" }] }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "reference_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } } } } - } - }, - "order": { - "type": "object", "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at", "origin", "created_event_id", "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", "triggered_at", "triggered_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, "origin": { "enum": ["direct", "target_rebalance", "margin_liquidation"] }, "created_event_id": { "$ref": "#/$defs/identifier" }, "updated_event_id": { "$ref": "#/$defs/identifier" }, "created_sequence": { "$ref": "#/$defs/sequence" }, "created_at": { "$ref": "#/$defs/timestamp" }, "eligible_after_slice_sequence": { "$ref": "#/$defs/nonnegativeSequence" }, "triggered_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, "triggered_slice_sequence": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/sequence" }] }, "filled_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, "status": { "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] }, "rejection_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1 }] } - } - }, - "orderCancelled": { - "type": "object", "additionalProperties": false, "required": ["order", "reason"], - "properties": { "order": { "$ref": "#/$defs/order" }, "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc", "immediate_or_cancel", "fill_or_kill", "day_expired", "gtd_expired", "margin_call"] } } - }, - "splitApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "previous_quantity", "adjusted_quantity"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "previous_quantity": { "$ref": "#/$defs/signedDecimal" }, "adjusted_quantity": { "$ref": "#/$defs/signedDecimal" } } - }, - "dividendApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "quantity", "cash_amount"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "cash_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "orderAdjusted": { - "type": "object", "additionalProperties": false, "required": ["order", "action_id"], - "properties": { "order": { "$ref": "#/$defs/order" }, "action_id": { "$ref": "#/$defs/identifier" } } - }, - "fill": { - "type": "object", "additionalProperties": false, - "required": ["fill_id", "order_id", "instrument_id", "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", "slice_sequence"], - "properties": { "fill_id": { "$ref": "#/$defs/identifier" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" }, "notional": { "$ref": "#/$defs/positiveDecimal" }, "fee": { "$ref": "#/$defs/unsignedDecimal" }, "executed_at": { "$ref": "#/$defs/timestamp" }, "slice_sequence": { "$ref": "#/$defs/sequence" } } - }, - "quantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "moneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "ratioThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "basisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "instrumentQuantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "instrumentMoneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "instrumentBasisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "instrumentShortingThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "value": { "const": false } } - }, - "groupMoneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["group_id", "unit", "value"], - "properties": { "group_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "groupRatioThreshold": { - "type": "object", "additionalProperties": false, "required": ["group_id", "unit", "value"], - "properties": { "group_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "fillClipReason": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_order_quantity" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_long_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_short_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_gross_exposure" }, "threshold": { "$ref": "#/$defs/moneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_leverage" }, "threshold": { "$ref": "#/$defs/ratioThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "initial_margin" }, "threshold": { "$ref": "#/$defs/basisPointsThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_long_position" }, "threshold": { "$ref": "#/$defs/instrumentQuantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_short_position" }, "threshold": { "$ref": "#/$defs/instrumentQuantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_notional_exposure" }, "threshold": { "$ref": "#/$defs/instrumentMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_shorting_disabled" }, "threshold": { "$ref": "#/$defs/instrumentShortingThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_initial_margin" }, "threshold": { "$ref": "#/$defs/instrumentBasisPointsThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_gross_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_long_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_short_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_absolute_net_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_concentration" }, "threshold": { "$ref": "#/$defs/groupRatioThreshold" } } } - ] - }, - "fillClipped": { - "type": "object", "additionalProperties": false, "required": ["reason", "order_id", "instrument_id", "proposed_quantity", "permitted_quantity", "price"], - "properties": { "reason": { "$ref": "#/$defs/fillClipReason" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "proposed_quantity": { "$ref": "#/$defs/positiveDecimal" }, "permitted_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" } } - }, - "borrowFee": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "quote_currency", "short_quantity", "reference_price", "borrow_bps", "period_start", "period_end", "fee"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "short_quantity": { "$ref": "#/$defs/positiveDecimal" }, "reference_price": { "$ref": "#/$defs/positiveDecimal" }, "borrow_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, "period_start": { "$ref": "#/$defs/timestamp" }, "period_end": { "$ref": "#/$defs/timestamp" }, "fee": { "$ref": "#/$defs/positiveDecimal" } } - }, - "cashAttribution": { - "type": "object", "additionalProperties": false, "required": ["currency", "amount", "fx_rate", "base_value"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "base_value": { "$ref": "#/$defs/signedDecimal" } } - }, - "positionAttribution": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quote_currency", "quantity", "mark", "fx_rate", "market_value", "base_market_value", "cost_basis", "base_cost_basis", "realized_pnl", "base_realized_pnl", "unrealized_pnl", "base_unrealized_pnl", "dividend_pnl", "base_dividend_pnl", "execution_fees", "base_execution_fees", "borrow_fees", "base_borrow_fees", "total_fees", "base_total_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "mark": { "$ref": "#/$defs/positiveDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "market_value": { "$ref": "#/$defs/signedDecimal" }, "base_market_value": { "$ref": "#/$defs/signedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "base_cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_total_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "margin": { - "type": "object", "additionalProperties": false, "required": ["initial_requirement", "maintenance_requirement", "initial_excess", "maintenance_excess", "margin_call"], - "properties": { "initial_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "maintenance_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "initial_excess": { "$ref": "#/$defs/signedDecimal" }, "maintenance_excess": { "$ref": "#/$defs/signedDecimal" }, "margin_call": { "type": "boolean" } } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "gross_exposure", "net_exposure", "long_exposure", "short_exposure", "concentration"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "net_exposure": { "$ref": "#/$defs/signedDecimal" }, - "long_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "short_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "concentration": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/signedDecimal" } - ] - } - } - }, - "valuation": { - "type": "object", "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "cost_basis", "realized_pnl", "unrealized_pnl", "equity", "dividend_pnl", "execution_fees", "borrow_fees", "total_fees", "cash_balances", "positions", "margin", "group_exposures"], - "properties": { - "base_currency": { "$ref": "#/$defs/identifier" }, "cash": { "$ref": "#/$defs/signedDecimal" }, "net_market_value": { "$ref": "#/$defs/signedDecimal" }, "long_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "short_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "equity": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/unsignedDecimal" }, "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashAttribution" } }, "positions": { "type": "array", "items": { "$ref": "#/$defs/positionAttribution" } }, "margin": { "$ref": "#/$defs/margin" }, "group_exposures": { "type": "array", "items": { "$ref": "#/$defs/groupExposure" } } - } - }, - "intentRejected": { "type": "object", "additionalProperties": false, "required": ["reason"], "properties": { "reason": { "type": "string", "minLength": 1 } } }, - "metric": { "type": "object", "additionalProperties": false, "required": ["name", "value"], "properties": { "name": { "type": "string" }, "value": { "type": "string" } } }, - "runCompleted": { - "type": "object", "additionalProperties": false, "required": ["scenario_sha256", "execution_model", "valuation", "order_counts"], - "properties": { - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" }, "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "type": "object", "additionalProperties": false, "required": ["total", "active", "filled", "rejected", "cancelled"], "properties": { "total": { "type": "integer", "minimum": 0 }, "active": { "type": "integer", "minimum": 0 }, "filled": { "type": "integer", "minimum": 0 }, "rejected": { "type": "integer", "minimum": 0 }, "cancelled": { "type": "integer", "minimum": 0 } } } - } - } - } -} diff --git a/contracts/v8/scenario-stream.schema.json b/contracts/v8/scenario-stream.schema.json deleted file mode 100644 index 7798820..0000000 --- a/contracts/v8/scenario-stream.schema.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v8/scenario-stream.schema.json", - "title": "Trading Engine v6 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "8" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "8" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "8" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json#/$defs/intent" } } - } - } - } -} diff --git a/contracts/v8/scenario.schema.json b/contracts/v8/scenario.schema.json deleted file mode 100644 index de87de4..0000000 --- a/contracts/v8/scenario.schema.json +++ /dev/null @@ -1,442 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v8/scenario.schema.json", - "title": "Trading Engine v6 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "8" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fixed_fee", "fee_bps"], - "properties": { - "version": { "const": "1" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" }, - "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 } - } - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/contracts/v9/README.md b/contracts/v9/README.md deleted file mode 100644 index f9ad441..0000000 --- a/contracts/v9/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Trading Engine contract v9 - -This directory is the authoritative v9 process and file contract shared by Trading Engine and its -clients. Versions 8, 7, 6, 5, 4, and 3 remain readable during their client transitions. - -- `scenario.schema.json` validates batch replay inputs. -- `scenario-stream.schema.json` validates each JSON Lines scenario-stream record. -- `journal.schema.json` validates each JSON Lines audit record. -- The files under `fixtures/` form the canonical valid conformance corpus. -- `fill-clipped.scenario.json` and its journal exercise a leverage-limited partial fill. - -Version 7 requires exactly one explicit risk policy per catalog instrument. Each policy defines -order, signed-position, notional, initial-margin, maintenance-margin, and shorting limits. Versioned -risk groups have explicit membership, may overlap, and can constrain gross, long, short, absolute -net, and gross-to-equity concentration exposure. - -Runtime validation requires exact currency, position-mark, and FX coverage; known instruments; -lot-aligned quantities; tick-aligned positive marks; basis with the same sign as quantity; -nonnegative fee histories; the base FX rate equal to one; instrument, group, aggregate exposure, -leverage, and initial-margin limits. Signed cash is valid. A successful v9 run emits `initial_state` -immediately after `run_started`, followed by a reconciled initial `valuation`, before market data. - -Admission and fill clipping include working-order reservations. When multiple groups limit the same -fill, lexical group identity is the deterministic tie breaker. Valuations and strategy contexts -carry group exposure snapshots, and clipping thresholds identify the exact instrument or group. - -Every v9 scenario, stream record, and journal record carries `"contract_version": "9"`. - -Version 8 adds explicit `market`, `limit`, `stop`, and `stop_limit` orders with `gtc`, `ioc`, -`fok`, `day`, and `gtd` time-in-force policies. `day` orders identify both their venue and the -exact versioned calendar; `gtd` orders carry an absolute expiry timestamp. Older contracts retain -their frozen mapping: market orders are IOC and limit orders are GTC. - -Stops evaluate only completed OHLCV bars. A gap through the trigger records the bar start as the -trigger time; an intrabar touch records the bar end. Trigger state and slice sequence are journaled, -and an activated order cannot execute before the following slice. A stop becomes a market order; -a stop-limit becomes its configured limit order. Splits adjust both trigger and limit prices. - -IOC orders cancel any remainder after their first eligible slice. FOK orders fill only when the -full remaining quantity fits both execution capacity and risk capacity, otherwise they cancel with -no fill. DAY orders cancel after matching the slice that reaches the selected session's final -phase close. GTD orders cancel before matching any completed bar whose end reaches or passes the -expiry, avoiding ambiguous partial-bar execution. - -The v9 `execution` object uses `completed_bar_v1` configuration version `"2"`: participation basis -points plus exactly one composable fee schedule per instrument. Named fixed, notional-basis-point, -and per-unit components declare currency, rounding, and maker/taker applicability. Optional -per-fill minimums and caps use the schedule settlement currency; negative components represent -rebates. Fills and valuations retain every native, quote, and base-currency attribution. Runtime -capabilities also advertise frozen configuration version `"1"` for older scenario contracts. diff --git a/contracts/v9/dune b/contracts/v9/dune deleted file mode 100644 index 4396587..0000000 --- a/contracts/v9/dune +++ /dev/null @@ -1,16 +0,0 @@ -(install - (section share) - (package trading_engine) - (files - (journal.schema.json as contracts/v9/journal.schema.json) - (scenario-stream.schema.json as contracts/v9/scenario-stream.schema.json) - (scenario.schema.json as contracts/v9/scenario.schema.json) - (fixtures/demo.journal.jsonl as contracts/v9/fixtures/demo.journal.jsonl) - (fixtures/demo.scenario.json as contracts/v9/fixtures/demo.scenario.json) - (fixtures/demo.scenario.jsonl as contracts/v9/fixtures/demo.scenario.jsonl) - (fixtures/fill-clipped.journal.jsonl - as - contracts/v9/fixtures/fill-clipped.journal.jsonl) - (fixtures/fill-clipped.scenario.json - as - contracts/v9/fixtures/fill-clipped.scenario.json))) diff --git a/contracts/v9/fixtures/demo.journal.jsonl b/contracts/v9/fixtures/demo.journal.jsonl deleted file mode 100644 index 71efc14..0000000 --- a/contracts/v9/fixtures/demo.journal.jsonl +++ /dev/null @@ -1,22 +0,0 @@ -{"contract_version":"9","engine_sequence":"1","event_id":"demo-event-000000000001","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"8a65aeaaa3c548704b926ecc99c0795bc51fc8279677b5c37848e8919e0fea1d","execution_model":"completed_bar_v1"}} -{"contract_version":"9","engine_sequence":"2","event_id":"demo-event-000000000002","causation_ids":["demo-event-000000000001"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[]}],"execution_fee_components":[],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}}} -{"contract_version":"9","engine_sequence":"3","event_id":"demo-event-000000000003","causation_ids":["demo-event-000000000002"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"100","long_market_value":"100","short_market_value":"0","gross_exposure":"100","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"10","equity":"10100","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"100","fx_rate":"1","market_value":"100","base_market_value":"100","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"10","base_unrealized_pnl":"10","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[]}],"execution_fee_components":[],"margin":{"initial_requirement":"50","maintenance_requirement":"25","initial_excess":"10050","maintenance_excess":"10075","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"4","event_id":"demo-event-000000000004","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-01-02T14:30:00.000000Z","end_at":"2026-01-02T21:00:00.000000Z","available_at":"2026-01-02T21:00:01.000000Z","received_at":"2026-01-02T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"100","high":"105","low":"99","close":"104","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"9","engine_sequence":"5","event_id":"demo-event-000000000005","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"weights","targets":[{"instrument_id":"demo-equity-acme","weight":"0.1","quantity":"9.715","reference_price":"104"}]}} -{"contract_version":"9","engine_sequence":"6","event_id":"demo-event-000000000006","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"metric_emitted","payload":{"name":"desired_weight","value":"0.1"}} -{"contract_version":"9","engine_sequence":"7","event_id":"demo-event-000000000007","causation_ids":["demo-event-000000000004","demo-event-000000000005"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"9","engine_sequence":"8","event_id":"demo-event-000000000008","causation_ids":["demo-event-000000000004"],"run_id":"demo","recorded_at":"2026-01-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"10000","net_market_value":"104","long_market_value":"104","short_market_value":"0","gross_exposure":"104","cost_basis":"90","realized_pnl":"5","unrealized_pnl":"14","equity":"10104","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25","total_fees":"0.75","cash_balances":[{"currency":"USD","amount":"10000","fx_rate":"1","base_value":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"1","mark":"104","fx_rate":"1","market_value":"104","base_market_value":"104","cost_basis":"90","base_cost_basis":"90","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"14","base_unrealized_pnl":"14","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"0.5","base_execution_fees":"0.5","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"0.75","base_total_fees":"0.75","execution_fee_components":[]}],"execution_fee_components":[],"margin":{"initial_requirement":"52","maintenance_requirement":"26","initial_excess":"10052","maintenance_excess":"10078","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"9","event_id":"demo-event-000000000009","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-01-05T14:30:00.000000Z","end_at":"2026-01-05T21:00:00.000000Z","available_at":"2026-01-05T21:00:01.000000Z","received_at":"2026-01-05T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"103","high":"108","low":"102","close":"107","volume":"12"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"9","engine_sequence":"10","event_id":"demo-event-000000000010","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000001","order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"6","price":"103","notional":"618","fee":"0.868","executed_at":"2026-01-05T14:30:00.000000Z","slice_sequence":"2","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_amount":"0.618"}]}} -{"contract_version":"9","engine_sequence":"11","event_id":"demo-event-000000000011","causation_ids":["demo-event-000000000007","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"demo-order-000000000001","instrument_id":"demo-equity-acme","side":"buy","quantity":"8.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000007","updated_event_id":"demo-event-000000000007","created_sequence":"7","created_at":"2026-01-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"6","filled_notional":"618","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"9","engine_sequence":"12","event_id":"demo-event-000000000012","causation_ids":["demo-event-000000000005","demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","side":"buy","quantity":"2.715","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000012","updated_event_id":"demo-event-000000000012","created_sequence":"12","created_at":"2026-01-05T21:00:02.000000Z","eligible_after_slice_sequence":"2","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"9","engine_sequence":"13","event_id":"demo-event-000000000013","causation_ids":["demo-event-000000000009"],"run_id":"demo","recorded_at":"2026-01-05T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9381.132","net_market_value":"749","long_market_value":"749","short_market_value":"0","gross_exposure":"749","cost_basis":"708.868","realized_pnl":"5","unrealized_pnl":"40.132","equity":"10130.132","dividend_pnl":"1","execution_fees":"1.368","borrow_fees":"0.25","total_fees":"1.618","cash_balances":[{"currency":"USD","amount":"9381.132","fx_rate":"1","base_value":"9381.132"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"7","mark":"107","fx_rate":"1","market_value":"749","base_market_value":"749","cost_basis":"708.868","base_cost_basis":"708.868","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"40.132","base_unrealized_pnl":"40.132","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.368","base_execution_fees":"1.368","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"1.618","base_total_fees":"1.618","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_currency":"USD","quote_amount":"0.25","base_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.618","quote_currency":"USD","quote_amount":"0.618","base_amount":"0.618"}],"margin":{"initial_requirement":"374.5","maintenance_requirement":"187.25","initial_excess":"9755.632","maintenance_excess":"9942.882","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"14","event_id":"demo-event-000000000014","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"3","start_at":"2026-01-06T14:30:00.000000Z","end_at":"2026-01-06T21:00:00.000000Z","available_at":"2026-01-06T21:00:01.000000Z","received_at":"2026-01-06T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"107","high":"109","low":"104","close":"105","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"9","engine_sequence":"15","event_id":"demo-event-000000000015","causation_ids":["demo-event-000000000012","demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000002","order_id":"demo-order-000000000002","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"buy","quantity":"2.715","price":"107","notional":"290.505","fee":"0.540505","executed_at":"2026-01-06T14:30:00.000000Z","slice_sequence":"3","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.290505","quote_amount":"0.290505"}]}} -{"contract_version":"9","engine_sequence":"16","event_id":"demo-event-000000000016","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"target_portfolio_requested","payload":{"basis":"quantities","targets":[{"instrument_id":"demo-equity-acme","weight":null,"quantity":"2.5","reference_price":null}]}} -{"contract_version":"9","engine_sequence":"17","event_id":"demo-event-000000000017","causation_ids":["demo-event-000000000014","demo-event-000000000016"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","side":"sell","quantity":"7.215","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"target_rebalance","created_event_id":"demo-event-000000000017","updated_event_id":"demo-event-000000000017","created_sequence":"17","created_at":"2026-01-06T21:00:02.000000Z","eligible_after_slice_sequence":"3","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"9","engine_sequence":"18","event_id":"demo-event-000000000018","causation_ids":["demo-event-000000000014"],"run_id":"demo","recorded_at":"2026-01-06T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9090.086495","net_market_value":"1020.075","long_market_value":"1020.075","short_market_value":"0","gross_exposure":"1020.075","cost_basis":"999.913505","realized_pnl":"5","unrealized_pnl":"20.161495","equity":"10110.161495","dividend_pnl":"1","execution_fees":"1.908505","borrow_fees":"0.25","total_fees":"2.158505","cash_balances":[{"currency":"USD","amount":"9090.086495","fx_rate":"1","base_value":"9090.086495"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"9.715","mark":"105","fx_rate":"1","market_value":"1020.075","base_market_value":"1020.075","cost_basis":"999.913505","base_cost_basis":"999.913505","realized_pnl":"5","base_realized_pnl":"5","unrealized_pnl":"20.161495","base_unrealized_pnl":"20.161495","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"1.908505","base_execution_fees":"1.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"2.158505","base_total_fees":"2.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.5","quote_currency":"USD","quote_amount":"0.5","base_amount":"0.5"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.908505","quote_currency":"USD","quote_amount":"0.908505","base_amount":"0.908505"}],"margin":{"initial_requirement":"510.0375","maintenance_requirement":"255.01875","initial_excess":"9600.123995","maintenance_excess":"9855.142745","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"19","event_id":"demo-event-000000000019","causation_ids":[],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"4","start_at":"2026-01-07T14:30:00.000000Z","end_at":"2026-01-07T21:00:00.000000Z","available_at":"2026-01-07T21:00:01.000000Z","received_at":"2026-01-07T21:00:02.000000Z","bars":[{"instrument_id":"demo-equity-acme","open":"105","high":"107","low":"103","close":"106","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"9","engine_sequence":"20","event_id":"demo-event-000000000020","causation_ids":["demo-event-000000000017","demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"fill_applied","payload":{"fill_id":"demo-fill-000000000003","order_id":"demo-order-000000000003","instrument_id":"demo-equity-acme","quote_currency":"USD","side":"sell","quantity":"7.215","price":"105","notional":"757.575","fee":"1","executed_at":"2026-01-07T14:30:00.000000Z","slice_sequence":"4","fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.25","quote_amount":"0.25"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"0.757575","quote_amount":"0.757575"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_amount":"-0.007575"}]}} -{"contract_version":"9","engine_sequence":"21","event_id":"demo-event-000000000021","causation_ids":["demo-event-000000000019"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"9846.661495","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.973257","unrealized_pnl":"7.688238","equity":"10111.661495","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.661495","fx_rate":"1","base_value":"9846.661495"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.161495","maintenance_excess":"10045.411495","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"22","event_id":"demo-event-000000000022","causation_ids":["demo-event-000000000021"],"run_id":"demo","recorded_at":"2026-01-07T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"8a65aeaaa3c548704b926ecc99c0795bc51fc8279677b5c37848e8919e0fea1d","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"9846.661495","net_market_value":"265","long_market_value":"265","short_market_value":"0","gross_exposure":"265","cost_basis":"257.311762","realized_pnl":"18.973257","unrealized_pnl":"7.688238","equity":"10111.661495","dividend_pnl":"1","execution_fees":"2.908505","borrow_fees":"0.25","total_fees":"3.158505","cash_balances":[{"currency":"USD","amount":"9846.661495","fx_rate":"1","base_value":"9846.661495"}],"positions":[{"instrument_id":"demo-equity-acme","quote_currency":"USD","quantity":"2.5","mark":"106","fx_rate":"1","market_value":"265","base_market_value":"265","cost_basis":"257.311762","base_cost_basis":"257.311762","realized_pnl":"18.973257","base_realized_pnl":"18.973257","unrealized_pnl":"7.688238","base_unrealized_pnl":"7.688238","dividend_pnl":"1","base_dividend_pnl":"1","execution_fees":"2.908505","base_execution_fees":"2.908505","borrow_fees":"0.25","base_borrow_fees":"0.25","total_fees":"3.158505","base_total_fees":"3.158505","execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}]}],"execution_fee_components":[{"name":"broker","kind":"fixed","currency":"USD","amount":"0.75","quote_currency":"USD","quote_amount":"0.75","base_amount":"0.75"},{"name":"exchange","kind":"notional_bps","currency":"USD","amount":"1.66608","quote_currency":"USD","quote_amount":"1.66608","base_amount":"1.66608"},{"name":"maximum_adjustment","kind":"maximum_adjustment","currency":"USD","amount":"-0.007575","quote_currency":"USD","quote_amount":"-0.007575","base_amount":"-0.007575"}],"margin":{"initial_requirement":"132.5","maintenance_requirement":"66.25","initial_excess":"9979.161495","maintenance_excess":"10045.411495","margin_call":false},"group_exposures":[]},"order_counts":{"total":3,"active":0,"filled":2,"rejected":0,"cancelled":1}}} diff --git a/contracts/v9/fixtures/demo.scenario.json b/contracts/v9/fixtures/demo.scenario.json deleted file mode 100644 index f4e41af..0000000 --- a/contracts/v9/fixtures/demo.scenario.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "contract_version": "9", - "metadata": { - "producer": "trading-engine-demo", - "purpose": "deterministic conformance fixture" - }, - "run_id": "demo", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "10000" - } - ], - "positions": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "1", - "cost_basis": "90", - "realized_pnl": "5", - "dividend_pnl": "1", - "execution_fees": "0.5", - "borrow_fees": "0.25" - } - ], - "marks": [ - { - "instrument_id": "demo-equity-acme", - "price": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "demo-equity-acme", - "symbol": "ACME", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "0.001" - } - ], - "venue_calendars": [ - { - "calendar_id": "demo-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "demo-equity-acme" - ], - "sessions": [ - { - "session_date": "2026-01-01", - "policy": "holiday", - "phases": [] - }, - { - "session_date": "2026-01-02", - "policy": "regular", - "phases": [ - { - "phase": "premarket", - "opens_at": "2026-01-02T09:00:00Z", - "closes_at": "2026-01-02T14:25:00Z" - }, - { - "phase": "opening_auction", - "opens_at": "2026-01-02T14:25:00Z", - "closes_at": "2026-01-02T14:30:00Z" - }, - { - "phase": "regular", - "opens_at": "2026-01-02T14:30:00Z", - "closes_at": "2026-01-02T20:55:00Z" - }, - { - "phase": "closing_auction", - "opens_at": "2026-01-02T20:55:00Z", - "closes_at": "2026-01-02T21:00:00Z" - }, - { - "phase": "postmarket", - "opens_at": "2026-01-02T21:00:00Z", - "closes_at": "2026-01-03T01:00:00Z" - } - ] - }, - { - "session_date": "2026-01-05", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-05T14:30:00Z", - "closes_at": "2026-01-05T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-06", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-06T14:30:00Z", - "closes_at": "2026-01-06T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-07", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-07T14:30:00Z", - "closes_at": "2026-01-07T21:00:00Z" - } - ] - }, - { - "session_date": "2026-01-08", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-01-08T14:30:00Z", - "closes_at": "2026-01-08T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000", - "max_leverage": "2", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "demo-equity-acme", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "demo-acme-fees-v1", - "instrument_id": "demo-equity-acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "1", - "components": [ - { "name": "broker", "currency": "USD", "kind": "fixed", "value": "0.25", "rounding": "up", "applies_to": "any" }, - { "name": "exchange", "currency": "USD", "kind": "notional_bps", "value": 10, "rounding": "up", "applies_to": "taker" }, - { "name": "maker_rebate", "currency": "USD", "kind": "notional_bps", "value": -2, "rounding": "nearest", "applies_to": "maker" } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "weight": "0.1" - } - ] - }, - { - "type": "emit_metric", - "name": "desired_weight", - "value": "0.1" - } - ] - }, - { - "after_slice_sequence": "3", - "intents": [ - { - "type": "target_quantities", - "targets": [ - { - "instrument_id": "demo-equity-acme", - "quantity": "2.5" - } - ] - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-01-05T14:30:00Z", - "end_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:01Z", - "received_at": "2026-01-05T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "103", - "high": "108", - "low": "102", - "close": "107", - "volume": "12" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "3", - "start_at": "2026-01-06T14:30:00Z", - "end_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:01Z", - "received_at": "2026-01-06T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "107", - "high": "109", - "low": "104", - "close": "105", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "4", - "start_at": "2026-01-07T14:30:00Z", - "end_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:01Z", - "received_at": "2026-01-07T21:00:02Z", - "bars": [ - { - "instrument_id": "demo-equity-acme", - "open": "105", - "high": "107", - "low": "103", - "close": "106", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v9/fixtures/demo.scenario.jsonl b/contracts/v9/fixtures/demo.scenario.jsonl deleted file mode 100644 index d32bd25..0000000 --- a/contracts/v9/fixtures/demo.scenario.jsonl +++ /dev/null @@ -1,6 +0,0 @@ -{"contract_version":"9","scenario_sequence":"1","record_type":"scenario_header","payload":{"metadata":{"producer":"trading-engine-demo","purpose":"deterministic conformance fixture"},"run_id":"demo","base_currency":"USD","initial_portfolio":{"cash":[{"currency":"USD","amount":"10000"}],"positions":[{"instrument_id":"demo-equity-acme","quantity":"1","cost_basis":"90","realized_pnl":"5","dividend_pnl":"1","execution_fees":"0.5","borrow_fees":"0.25"}],"marks":[{"instrument_id":"demo-equity-acme","price":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}]},"instruments":[{"instrument_id":"demo-equity-acme","symbol":"ACME","quote_currency":"USD","tick_size":"0.01","lot_size":"0.001"}],"venue_calendars":[{"calendar_id":"demo-xnas-2026","calendar_version":"1","venue_id":"XNAS","instrument_ids":["demo-equity-acme"],"sessions":[{"session_date":"2026-01-01","policy":"holiday","phases":[]},{"session_date":"2026-01-02","policy":"regular","phases":[{"phase":"premarket","opens_at":"2026-01-02T09:00:00Z","closes_at":"2026-01-02T14:25:00Z"},{"phase":"opening_auction","opens_at":"2026-01-02T14:25:00Z","closes_at":"2026-01-02T14:30:00Z"},{"phase":"regular","opens_at":"2026-01-02T14:30:00Z","closes_at":"2026-01-02T20:55:00Z"},{"phase":"closing_auction","opens_at":"2026-01-02T20:55:00Z","closes_at":"2026-01-02T21:00:00Z"},{"phase":"postmarket","opens_at":"2026-01-02T21:00:00Z","closes_at":"2026-01-03T01:00:00Z"}]},{"session_date":"2026-01-05","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-05T14:30:00Z","closes_at":"2026-01-05T21:00:00Z"}]},{"session_date":"2026-01-06","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-06T14:30:00Z","closes_at":"2026-01-06T21:00:00Z"}]},{"session_date":"2026-01-07","policy":"regular","phases":[{"phase":"regular","opens_at":"2026-01-07T14:30:00Z","closes_at":"2026-01-07T21:00:00Z"}]},{"session_date":"2026-01-08","policy":"early_close","phases":[{"phase":"regular","opens_at":"2026-01-08T14:30:00Z","closes_at":"2026-01-08T18:00:00Z"}]}]}],"risk":{"max_gross_exposure":"1000000","max_leverage":"2","short_borrow_bps":100,"instrument_policies":[{"instrument_id":"demo-equity-acme","max_order_quantity":"1000","max_long_position":"1000","max_short_position":"1000","max_notional_exposure":"1000000","initial_margin_bps":5000,"maintenance_margin_bps":2500,"shorting_allowed":true}],"groups":[]},"execution":{"model":"completed_bar_v1","configuration":{"version":"2","participation_bps":5000,"fee_schedules":[{"schedule_id":"demo-acme-fees-v1","instrument_id":"demo-equity-acme","settlement_currency":"USD","minimum":"0.3","maximum":"1","components":[{"name":"broker","currency":"USD","kind":"fixed","value":"0.25","rounding":"up","applies_to":"any"},{"name":"exchange","currency":"USD","kind":"notional_bps","value":10,"rounding":"up","applies_to":"taker"},{"name":"maker_rebate","currency":"USD","kind":"notional_bps","value":-2,"rounding":"nearest","applies_to":"maker"}]}]}},"max_internal_events":1000}} -{"contract_version":"9","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","weight":"0.1"}],"type":"target_weights"},{"name":"desired_weight","type":"emit_metric","value":"0.1"}],"market_slice":{"available_at":"2026-01-02T21:00:01Z","bars":[{"close":"104","high":"105","instrument_id":"demo-equity-acme","low":"99","open":"100","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-02T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-02T21:00:02Z","slice_sequence":"1","start_at":"2026-01-02T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"2"} -{"contract_version":"9","payload":{"intents":[],"market_slice":{"available_at":"2026-01-05T21:00:01Z","bars":[{"close":"107","high":"108","instrument_id":"demo-equity-acme","low":"102","open":"103","volume":"12"}],"corporate_actions":[],"end_at":"2026-01-05T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-05T21:00:02Z","slice_sequence":"2","start_at":"2026-01-05T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"3"} -{"contract_version":"9","payload":{"intents":[{"targets":[{"instrument_id":"demo-equity-acme","quantity":"2.5"}],"type":"target_quantities"}],"market_slice":{"available_at":"2026-01-06T21:00:01Z","bars":[{"close":"105","high":"109","instrument_id":"demo-equity-acme","low":"104","open":"107","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-06T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-06T21:00:02Z","slice_sequence":"3","start_at":"2026-01-06T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"4"} -{"contract_version":"9","payload":{"intents":[],"market_slice":{"available_at":"2026-01-07T21:00:01Z","bars":[{"close":"106","high":"107","instrument_id":"demo-equity-acme","low":"103","open":"105","volume":"100"}],"corporate_actions":[],"end_at":"2026-01-07T21:00:00Z","fx_rates":[{"currency":"USD","rate":"1"}],"received_at":"2026-01-07T21:00:02Z","slice_sequence":"4","start_at":"2026-01-07T14:30:00Z"}},"record_type":"market_slice","scenario_sequence":"5"} -{"contract_version":"9","payload":{"slice_count":"4"},"record_type":"scenario_end","scenario_sequence":"6"} diff --git a/contracts/v9/fixtures/fill-clipped.journal.jsonl b/contracts/v9/fixtures/fill-clipped.journal.jsonl deleted file mode 100644 index 272c5b9..0000000 --- a/contracts/v9/fixtures/fill-clipped.journal.jsonl +++ /dev/null @@ -1,11 +0,0 @@ -{"contract_version":"9","engine_sequence":"1","event_id":"fill-clipped-event-000000000001","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"run_started","payload":{"scenario_sha256":"d2b5effb91be9d9725df41aa6a908b761931c4631aff5cbd9fad7d3f14a3c3cb","execution_model":"completed_bar_v1"}} -{"contract_version":"9","engine_sequence":"2","event_id":"fill-clipped-event-000000000002","causation_ids":["fill-clipped-event-000000000001"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"initial_state","payload":{"portfolio":{"cash":[{"currency":"USD","amount":"550"}],"positions":[],"marks":[],"fx_rates":[{"currency":"USD","rate":"1"}]},"valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"execution_fee_components":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}}} -{"contract_version":"9","engine_sequence":"3","event_id":"fill-clipped-event-000000000003","causation_ids":["fill-clipped-event-000000000002"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[],"execution_fee_components":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"4","event_id":"fill-clipped-event-000000000004","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"1","start_at":"2026-02-02T14:30:00.000000Z","end_at":"2026-02-02T21:00:00.000000Z","available_at":"2026-02-02T21:00:01.000000Z","received_at":"2026-02-02T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"50","high":"50","low":"50","close":"50","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"9","engine_sequence":"5","event_id":"fill-clipped-event-000000000005","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"order_accepted","payload":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"working","rejection_reason":null}} -{"contract_version":"9","engine_sequence":"6","event_id":"fill-clipped-event-000000000006","causation_ids":["fill-clipped-event-000000000004"],"run_id":"fill-clipped","recorded_at":"2026-02-02T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"50","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[]}],"execution_fee_components":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"7","event_id":"fill-clipped-event-000000000007","causation_ids":[],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"market_slice_received","payload":{"slice_sequence":"2","start_at":"2026-02-03T14:30:00.000000Z","end_at":"2026-02-03T21:00:00.000000Z","available_at":"2026-02-03T21:00:01.000000Z","received_at":"2026-02-03T21:00:02.000000Z","bars":[{"instrument_id":"clip-equity","open":"100","high":"100","low":"100","close":"100","volume":"100"}],"fx_rates":[{"currency":"USD","rate":"1"}],"corporate_actions":[]}} -{"contract_version":"9","engine_sequence":"8","event_id":"fill-clipped-event-000000000008","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"fill_clipped","payload":{"reason":{"version":"1","policy":"max_leverage","threshold":{"unit":"ratio","value":"1"}},"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","proposed_quantity":"10","permitted_quantity":"0","price":"100"}} -{"contract_version":"9","engine_sequence":"9","event_id":"fill-clipped-event-000000000009","causation_ids":["fill-clipped-event-000000000005","fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"order_cancelled","payload":{"order":{"order_id":"fill-clipped-order-000000000001","instrument_id":"clip-equity","side":"buy","quantity":"10","order_kind":"market","trigger_price":null,"limit_price":null,"time_in_force":"ioc","venue_id":null,"calendar_id":null,"expires_at":null,"origin":"direct","created_event_id":"fill-clipped-event-000000000005","updated_event_id":"fill-clipped-event-000000000005","created_sequence":"5","created_at":"2026-02-02T21:00:02.000000Z","eligible_after_slice_sequence":"1","triggered_at":null,"triggered_slice_sequence":null,"filled_quantity":"0","filled_notional":"0","status":"cancelled","rejection_reason":null},"reason":"market_ioc"}} -{"contract_version":"9","engine_sequence":"10","event_id":"fill-clipped-event-000000000010","causation_ids":["fill-clipped-event-000000000007"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"valuation","payload":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[]}],"execution_fee_components":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]}} -{"contract_version":"9","engine_sequence":"11","event_id":"fill-clipped-event-000000000011","causation_ids":["fill-clipped-event-000000000010"],"run_id":"fill-clipped","recorded_at":"2026-02-03T21:00:02.000000Z","event_type":"run_completed","payload":{"scenario_sha256":"d2b5effb91be9d9725df41aa6a908b761931c4631aff5cbd9fad7d3f14a3c3cb","execution_model":"completed_bar_v1","valuation":{"base_currency":"USD","cash":"550","net_market_value":"0","long_market_value":"0","short_market_value":"0","gross_exposure":"0","cost_basis":"0","realized_pnl":"0","unrealized_pnl":"0","equity":"550","dividend_pnl":"0","execution_fees":"0","borrow_fees":"0","total_fees":"0","cash_balances":[{"currency":"USD","amount":"550","fx_rate":"1","base_value":"550"}],"positions":[{"instrument_id":"clip-equity","quote_currency":"USD","quantity":"0","mark":"100","fx_rate":"1","market_value":"0","base_market_value":"0","cost_basis":"0","base_cost_basis":"0","realized_pnl":"0","base_realized_pnl":"0","unrealized_pnl":"0","base_unrealized_pnl":"0","dividend_pnl":"0","base_dividend_pnl":"0","execution_fees":"0","base_execution_fees":"0","borrow_fees":"0","base_borrow_fees":"0","total_fees":"0","base_total_fees":"0","execution_fee_components":[]}],"execution_fee_components":[],"margin":{"initial_requirement":"0","maintenance_requirement":"0","initial_excess":"550","maintenance_excess":"550","margin_call":false},"group_exposures":[]},"order_counts":{"total":1,"active":0,"filled":0,"rejected":0,"cancelled":1}}} diff --git a/contracts/v9/fixtures/fill-clipped.scenario.json b/contracts/v9/fixtures/fill-clipped.scenario.json deleted file mode 100644 index d14bf55..0000000 --- a/contracts/v9/fixtures/fill-clipped.scenario.json +++ /dev/null @@ -1,187 +0,0 @@ -{ - "contract_version": "9", - "metadata": { - "producer": "trading-engine", - "purpose": "fill clipping conformance fixture" - }, - "run_id": "fill-clipped", - "base_currency": "USD", - "initial_portfolio": { - "cash": [ - { - "currency": "USD", - "amount": "550" - } - ], - "positions": [], - "marks": [], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ] - }, - "instruments": [ - { - "instrument_id": "clip-equity", - "symbol": "CLIP", - "quote_currency": "USD", - "tick_size": "0.01", - "lot_size": "1" - } - ], - "venue_calendars": [ - { - "calendar_id": "clip-xnas-2026", - "calendar_version": "1", - "venue_id": "XNAS", - "instrument_ids": [ - "clip-equity" - ], - "sessions": [ - { - "session_date": "2026-02-02", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-02T14:30:00Z", - "closes_at": "2026-02-02T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-03", - "policy": "regular", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-03T14:30:00Z", - "closes_at": "2026-02-03T21:00:00Z" - } - ] - }, - { - "session_date": "2026-02-04", - "policy": "early_close", - "phases": [ - { - "phase": "regular", - "opens_at": "2026-02-04T14:30:00Z", - "closes_at": "2026-02-04T18:00:00Z" - } - ] - } - ] - } - ], - "risk": { - "max_gross_exposure": "1000000000", - "max_leverage": "1", - "short_borrow_bps": 100, - "instrument_policies": [ - { - "instrument_id": "clip-equity", - "max_order_quantity": "1000", - "max_long_position": "1000", - "max_short_position": "1000", - "max_notional_exposure": "1000000000", - "initial_margin_bps": 5000, - "maintenance_margin_bps": 2500, - "shorting_allowed": true - } - ], - "groups": [] - }, - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 10000, - "fee_schedules": [ - { - "schedule_id": "clip-fees-v1", - "instrument_id": "clip-equity", - "settlement_currency": "USD", - "minimum": null, - "maximum": null, - "components": [ - { "name": "broker", "currency": "USD", "kind": "fixed", "value": "10", "rounding": "up", "applies_to": "any" } - ] - } - ] - } - }, - "max_internal_events": 1000, - "schedule": [ - { - "after_slice_sequence": "1", - "intents": [ - { - "type": "submit_order", - "instrument_id": "clip-equity", - "side": "buy", - "quantity": "10", - "order_kind": "market", - "trigger_price": null, - "limit_price": null, - "time_in_force": "ioc", - "venue_id": null, - "calendar_id": null, - "expires_at": null - } - ] - } - ], - "slices": [ - { - "slice_sequence": "1", - "start_at": "2026-02-02T14:30:00Z", - "end_at": "2026-02-02T21:00:00Z", - "available_at": "2026-02-02T21:00:01Z", - "received_at": "2026-02-02T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "50", - "high": "50", - "low": "50", - "close": "50", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - }, - { - "slice_sequence": "2", - "start_at": "2026-02-03T14:30:00Z", - "end_at": "2026-02-03T21:00:00Z", - "available_at": "2026-02-03T21:00:01Z", - "received_at": "2026-02-03T21:00:02Z", - "bars": [ - { - "instrument_id": "clip-equity", - "open": "100", - "high": "100", - "low": "100", - "close": "100", - "volume": "100" - } - ], - "fx_rates": [ - { - "currency": "USD", - "rate": "1" - } - ], - "corporate_actions": [] - } - ] -} diff --git a/contracts/v9/journal.schema.json b/contracts/v9/journal.schema.json deleted file mode 100644 index 1e6baa6..0000000 --- a/contracts/v9/journal.schema.json +++ /dev/null @@ -1,248 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v9/journal.schema.json", - "title": "Trading Engine v6 audit journal record", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "engine_sequence", "event_id", "causation_ids", "run_id", "recorded_at", "event_type", "payload"], - "properties": { - "contract_version": { "const": "9" }, - "engine_sequence": { "$ref": "#/$defs/sequence" }, - "event_id": { "$ref": "#/$defs/identifier" }, - "causation_ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/identifier" } }, - "run_id": { "$ref": "#/$defs/identifier" }, - "recorded_at": { "$ref": "#/$defs/timestamp" }, - "event_type": { - "enum": ["run_started", "initial_state", "market_slice_received", "target_portfolio_requested", "order_accepted", "order_rejected", "order_triggered", "order_cancelled", "split_applied", "cash_dividend_applied", "order_adjusted", "fill_applied", "fill_clipped", "borrow_fee_applied", "margin_call", "margin_restored", "intent_rejected", "metric_emitted", "valuation", "run_completed"] - }, - "payload": { "type": "object" } - }, - "allOf": [ - { "if": { "properties": { "event_type": { "const": "run_started" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runStarted" } } } }, - { "if": { "properties": { "event_type": { "const": "initial_state" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/initialState" } } } }, - { "if": { "properties": { "event_type": { "const": "market_slice_received" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/marketSlice" } } } }, - { "if": { "properties": { "event_type": { "const": "target_portfolio_requested" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/targetPortfolio" } } } }, - { "if": { "properties": { "event_type": { "enum": ["order_accepted", "order_rejected", "order_triggered"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/order" } } } }, - { "if": { "properties": { "event_type": { "const": "order_cancelled" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderCancelled" } } } }, - { "if": { "properties": { "event_type": { "const": "split_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/splitApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "cash_dividend_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/dividendApplied" } } } }, - { "if": { "properties": { "event_type": { "const": "order_adjusted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/orderAdjusted" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fill" } } } }, - { "if": { "properties": { "event_type": { "const": "fill_clipped" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/fillClipped" } } } }, - { "if": { "properties": { "event_type": { "const": "borrow_fee_applied" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/borrowFee" } } } }, - { "if": { "properties": { "event_type": { "enum": ["margin_call", "margin_restored", "valuation"] } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/valuation" } } } }, - { "if": { "properties": { "event_type": { "const": "intent_rejected" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/intentRejected" } } } }, - { "if": { "properties": { "event_type": { "const": "metric_emitted" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/metric" } } } }, - { "if": { "properties": { "event_type": { "const": "run_completed" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/runCompleted" } } } } - ], - "$defs": { - "identifier": { "type": "string", "minLength": 1, "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" }, - "signedDecimal": { "type": "string", "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" }, - "unsignedDecimal": { "type": "string", "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "positiveDecimal": { "type": "string", "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "nonnegativeSequence": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" }, - "timestamp": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" }, - "runStarted": { - "type": "object", "additionalProperties": false, - "required": ["scenario_sha256", "execution_model"], - "properties": { "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" } } - }, - "initialState": { - "type": "object", "additionalProperties": false, - "required": ["portfolio", "valuation"], - "properties": { - "portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/initialPortfolio" }, - "valuation": { "$ref": "#/$defs/valuation" } - } - }, - "bar": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "open": { "$ref": "#/$defs/positiveDecimal" }, "high": { "$ref": "#/$defs/positiveDecimal" }, "low": { "$ref": "#/$defs/positiveDecimal" }, "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", "additionalProperties": false, "required": ["currency", "rate"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "rate": { "$ref": "#/$defs/positiveDecimal" } } - }, - "corporateAction": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], "properties": { "type": { "const": "split" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "numerator": { "$ref": "#/$defs/sequence" }, "denominator": { "$ref": "#/$defs/sequence" } } }, - { "type": "object", "additionalProperties": false, "required": ["type", "action_id", "instrument_id", "amount_per_unit"], "properties": { "type": { "const": "cash_dividend" }, "action_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } } } - ] - }, - "marketSlice": { - "type": "object", "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, "start_at": { "$ref": "#/$defs/timestamp" }, "end_at": { "$ref": "#/$defs/timestamp" }, "available_at": { "$ref": "#/$defs/timestamp" }, "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "targetPortfolio": { - "type": "object", "additionalProperties": false, "required": ["basis", "targets"], - "properties": { - "basis": { "enum": ["weights", "quantities"] }, - "targets": { "type": "array", "minItems": 1, "items": { "type": "object", "additionalProperties": false, "required": ["instrument_id", "weight", "quantity", "reference_price"], "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "weight": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/signedDecimal" }] }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "reference_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] } } } } - } - }, - "order": { - "type": "object", "additionalProperties": false, - "required": ["order_id", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at", "origin", "created_event_id", "updated_event_id", "created_sequence", "created_at", "eligible_after_slice_sequence", "triggered_at", "triggered_slice_sequence", "filled_quantity", "filled_notional", "status", "rejection_reason"], - "properties": { - "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, "origin": { "enum": ["direct", "target_rebalance", "margin_liquidation"] }, "created_event_id": { "$ref": "#/$defs/identifier" }, "updated_event_id": { "$ref": "#/$defs/identifier" }, "created_sequence": { "$ref": "#/$defs/sequence" }, "created_at": { "$ref": "#/$defs/timestamp" }, "eligible_after_slice_sequence": { "$ref": "#/$defs/nonnegativeSequence" }, "triggered_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] }, "triggered_slice_sequence": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/sequence" }] }, "filled_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "filled_notional": { "$ref": "#/$defs/unsignedDecimal" }, "status": { "enum": ["working", "partially_filled", "filled", "cancelled", "rejected"] }, "rejection_reason": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1 }] } - } - }, - "orderCancelled": { - "type": "object", "additionalProperties": false, "required": ["order", "reason"], - "properties": { "order": { "$ref": "#/$defs/order" }, "reason": { "enum": ["strategy_requested", "target_replaced", "market_ioc", "immediate_or_cancel", "fill_or_kill", "day_expired", "gtd_expired", "margin_call"] } } - }, - "splitApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "previous_quantity", "adjusted_quantity"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "previous_quantity": { "$ref": "#/$defs/signedDecimal" }, "adjusted_quantity": { "$ref": "#/$defs/signedDecimal" } } - }, - "dividendApplied": { - "type": "object", "additionalProperties": false, "required": ["action", "quantity", "cash_amount"], - "properties": { "action": { "$ref": "#/$defs/corporateAction" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "cash_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "orderAdjusted": { - "type": "object", "additionalProperties": false, "required": ["order", "action_id"], - "properties": { "order": { "$ref": "#/$defs/order" }, "action_id": { "$ref": "#/$defs/identifier" } } - }, - "fill": { - "type": "object", "additionalProperties": false, - "required": ["fill_id", "order_id", "instrument_id", "quote_currency", "side", "quantity", "price", "notional", "fee", "executed_at", "slice_sequence", "fee_components"], - "properties": { "fill_id": { "$ref": "#/$defs/identifier" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "side": { "enum": ["buy", "sell"] }, "quantity": { "$ref": "#/$defs/positiveDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" }, "notional": { "$ref": "#/$defs/positiveDecimal" }, "fee": { "$ref": "#/$defs/signedDecimal" }, "fee_components": { "type": "array", "items": { "$ref": "#/$defs/calculatedFeeComponent" } }, "executed_at": { "$ref": "#/$defs/timestamp" }, "slice_sequence": { "$ref": "#/$defs/sequence" } } - }, - "calculatedFeeComponent": { - "type": "object", "additionalProperties": false, - "required": ["name", "kind", "currency", "amount", "quote_amount"], - "properties": { "name": { "$ref": "#/$defs/identifier" }, "kind": { "enum": ["fixed", "notional_bps", "per_unit", "minimum_adjustment", "maximum_adjustment"] }, "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "quote_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "feeComponentAttribution": { - "type": "object", "additionalProperties": false, - "required": ["name", "kind", "currency", "amount", "quote_currency", "quote_amount", "base_amount"], - "properties": { "name": { "$ref": "#/$defs/identifier" }, "kind": { "enum": ["fixed", "notional_bps", "per_unit", "minimum_adjustment", "maximum_adjustment"] }, "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quote_amount": { "$ref": "#/$defs/signedDecimal" }, "base_amount": { "$ref": "#/$defs/signedDecimal" } } - }, - "quantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "moneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "ratioThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "basisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["unit", "value"], - "properties": { "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "instrumentQuantityThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "quantity" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "instrumentMoneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "instrumentBasisPointsThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "unit", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "basis_points" }, "value": { "type": "integer", "minimum": 1, "maximum": 10000 } } - }, - "instrumentShortingThreshold": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "value"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "value": { "const": false } } - }, - "groupMoneyThreshold": { - "type": "object", "additionalProperties": false, "required": ["group_id", "unit", "value"], - "properties": { "group_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "money" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "groupRatioThreshold": { - "type": "object", "additionalProperties": false, "required": ["group_id", "unit", "value"], - "properties": { "group_id": { "$ref": "#/$defs/identifier" }, "unit": { "const": "ratio" }, "value": { "$ref": "#/$defs/positiveDecimal" } } - }, - "fillClipReason": { - "oneOf": [ - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_order_quantity" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_long_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_short_position" }, "threshold": { "$ref": "#/$defs/quantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_gross_exposure" }, "threshold": { "$ref": "#/$defs/moneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "max_leverage" }, "threshold": { "$ref": "#/$defs/ratioThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "initial_margin" }, "threshold": { "$ref": "#/$defs/basisPointsThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_long_position" }, "threshold": { "$ref": "#/$defs/instrumentQuantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_short_position" }, "threshold": { "$ref": "#/$defs/instrumentQuantityThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_max_notional_exposure" }, "threshold": { "$ref": "#/$defs/instrumentMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_shorting_disabled" }, "threshold": { "$ref": "#/$defs/instrumentShortingThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "instrument_initial_margin" }, "threshold": { "$ref": "#/$defs/instrumentBasisPointsThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_gross_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_long_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_short_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_absolute_net_exposure" }, "threshold": { "$ref": "#/$defs/groupMoneyThreshold" } } }, - { "type": "object", "additionalProperties": false, "required": ["version", "policy", "threshold"], "properties": { "version": { "const": "1" }, "policy": { "const": "group_max_concentration" }, "threshold": { "$ref": "#/$defs/groupRatioThreshold" } } } - ] - }, - "fillClipped": { - "type": "object", "additionalProperties": false, "required": ["reason", "order_id", "instrument_id", "proposed_quantity", "permitted_quantity", "price"], - "properties": { "reason": { "$ref": "#/$defs/fillClipReason" }, "order_id": { "$ref": "#/$defs/identifier" }, "instrument_id": { "$ref": "#/$defs/identifier" }, "proposed_quantity": { "$ref": "#/$defs/positiveDecimal" }, "permitted_quantity": { "$ref": "#/$defs/unsignedDecimal" }, "price": { "$ref": "#/$defs/positiveDecimal" } } - }, - "borrowFee": { - "type": "object", "additionalProperties": false, "required": ["instrument_id", "quote_currency", "short_quantity", "reference_price", "borrow_bps", "period_start", "period_end", "fee"], - "properties": { "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "short_quantity": { "$ref": "#/$defs/positiveDecimal" }, "reference_price": { "$ref": "#/$defs/positiveDecimal" }, "borrow_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, "period_start": { "$ref": "#/$defs/timestamp" }, "period_end": { "$ref": "#/$defs/timestamp" }, "fee": { "$ref": "#/$defs/positiveDecimal" } } - }, - "cashAttribution": { - "type": "object", "additionalProperties": false, "required": ["currency", "amount", "fx_rate", "base_value"], - "properties": { "currency": { "$ref": "#/$defs/identifier" }, "amount": { "$ref": "#/$defs/signedDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "base_value": { "$ref": "#/$defs/signedDecimal" } } - }, - "positionAttribution": { - "type": "object", "additionalProperties": false, - "required": ["instrument_id", "quote_currency", "quantity", "mark", "fx_rate", "market_value", "base_market_value", "cost_basis", "base_cost_basis", "realized_pnl", "base_realized_pnl", "unrealized_pnl", "base_unrealized_pnl", "dividend_pnl", "base_dividend_pnl", "execution_fees", "base_execution_fees", "borrow_fees", "base_borrow_fees", "total_fees", "base_total_fees", "execution_fee_components"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, "quote_currency": { "$ref": "#/$defs/identifier" }, "quantity": { "$ref": "#/$defs/signedDecimal" }, "mark": { "$ref": "#/$defs/positiveDecimal" }, "fx_rate": { "$ref": "#/$defs/positiveDecimal" }, "market_value": { "$ref": "#/$defs/signedDecimal" }, "base_market_value": { "$ref": "#/$defs/signedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "base_cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "base_dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/signedDecimal" }, "base_execution_fees": { "$ref": "#/$defs/signedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "base_borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/signedDecimal" }, "base_total_fees": { "$ref": "#/$defs/signedDecimal" }, "execution_fee_components": { "type": "array", "items": { "$ref": "#/$defs/feeComponentAttribution" } } - } - }, - "margin": { - "type": "object", "additionalProperties": false, "required": ["initial_requirement", "maintenance_requirement", "initial_excess", "maintenance_excess", "margin_call"], - "properties": { "initial_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "maintenance_requirement": { "$ref": "#/$defs/unsignedDecimal" }, "initial_excess": { "$ref": "#/$defs/signedDecimal" }, "maintenance_excess": { "$ref": "#/$defs/signedDecimal" }, "margin_call": { "type": "boolean" } } - }, - "groupExposure": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "gross_exposure", "net_exposure", "long_exposure", "short_exposure", "concentration"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "net_exposure": { "$ref": "#/$defs/signedDecimal" }, - "long_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "short_exposure": { "$ref": "#/$defs/unsignedDecimal" }, - "concentration": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/signedDecimal" } - ] - } - } - }, - "valuation": { - "type": "object", "additionalProperties": false, - "required": ["base_currency", "cash", "net_market_value", "long_market_value", "short_market_value", "gross_exposure", "cost_basis", "realized_pnl", "unrealized_pnl", "equity", "dividend_pnl", "execution_fees", "borrow_fees", "total_fees", "cash_balances", "positions", "margin", "group_exposures", "execution_fee_components"], - "properties": { - "base_currency": { "$ref": "#/$defs/identifier" }, "cash": { "$ref": "#/$defs/signedDecimal" }, "net_market_value": { "$ref": "#/$defs/signedDecimal" }, "long_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "short_market_value": { "$ref": "#/$defs/unsignedDecimal" }, "gross_exposure": { "$ref": "#/$defs/unsignedDecimal" }, "cost_basis": { "$ref": "#/$defs/signedDecimal" }, "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, "unrealized_pnl": { "$ref": "#/$defs/signedDecimal" }, "equity": { "$ref": "#/$defs/signedDecimal" }, "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, "execution_fees": { "$ref": "#/$defs/signedDecimal" }, "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" }, "total_fees": { "$ref": "#/$defs/signedDecimal" }, "cash_balances": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashAttribution" } }, "positions": { "type": "array", "items": { "$ref": "#/$defs/positionAttribution" } }, "margin": { "$ref": "#/$defs/margin" }, "group_exposures": { "type": "array", "items": { "$ref": "#/$defs/groupExposure" } }, "execution_fee_components": { "type": "array", "items": { "$ref": "#/$defs/feeComponentAttribution" } } - } - }, - "intentRejected": { "type": "object", "additionalProperties": false, "required": ["reason"], "properties": { "reason": { "type": "string", "minLength": 1 } } }, - "metric": { "type": "object", "additionalProperties": false, "required": ["name", "value"], "properties": { "name": { "type": "string" }, "value": { "type": "string" } } }, - "runCompleted": { - "type": "object", "additionalProperties": false, "required": ["scenario_sha256", "execution_model", "valuation", "order_counts"], - "properties": { - "scenario_sha256": { "type": "string", "pattern": "^[0-9a-f]{64}$" }, "execution_model": { "const": "completed_bar_v1" }, "valuation": { "$ref": "#/$defs/valuation" }, - "order_counts": { "type": "object", "additionalProperties": false, "required": ["total", "active", "filled", "rejected", "cancelled"], "properties": { "total": { "type": "integer", "minimum": 0 }, "active": { "type": "integer", "minimum": 0 }, "filled": { "type": "integer", "minimum": 0 }, "rejected": { "type": "integer", "minimum": 0 }, "cancelled": { "type": "integer", "minimum": 0 } } } - } - } - } -} diff --git a/contracts/v9/scenario-stream.schema.json b/contracts/v9/scenario-stream.schema.json deleted file mode 100644 index a18a7ea..0000000 --- a/contracts/v9/scenario-stream.schema.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v9/scenario-stream.schema.json", - "title": "Trading Engine v6 replay scenario stream record", - "description": "Market-slice records are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-record rule is enforced semantically.", - "oneOf": [ - { "$ref": "#/$defs/headerRecord" }, - { "$ref": "#/$defs/sliceRecord" }, - { "$ref": "#/$defs/endRecord" } - ], - "$defs": { - "headerRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "9" }, - "scenario_sequence": { "const": "1" }, - "record_type": { "const": "scenario_header" }, - "payload": { "$ref": "#/$defs/headerPayload" } - } - }, - "sliceRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "9" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "market_slice" }, - "payload": { "$ref": "#/$defs/slicePayload" } - } - }, - "endRecord": { - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "scenario_sequence", "record_type", "payload"], - "properties": { - "contract_version": { "const": "9" }, - "scenario_sequence": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/sequence" }, - "record_type": { "const": "scenario_end" }, - "payload": { - "type": "object", - "additionalProperties": false, - "required": ["slice_count"], - "properties": { "slice_count": { "type": "string", "pattern": "^(?:0|[1-9][0-9]*)$" } } - } - } - }, - "headerPayload": { - "type": "object", - "additionalProperties": false, - "required": ["metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events"], - "properties": { - "metadata": { "type": "object" }, - "run_id": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/identifier" }, - "base_currency": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/identifier" }, - "initial_portfolio": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/initialPortfolio" }, - "instruments": { "type": "array", "minItems": 1, "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/instrument" } }, - "venue_calendars": { "type": "array", "minItems": 1, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/venueCalendar" } }, - "risk": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/risk" }, - "execution": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 } - } - }, - "slicePayload": { - "type": "object", - "additionalProperties": false, - "required": ["market_slice", "intents"], - "properties": { - "market_slice": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/marketSlice" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json#/$defs/intent" } } - } - } - } -} - diff --git a/contracts/v9/scenario.schema.json b/contracts/v9/scenario.schema.json deleted file mode 100644 index e90b4d8..0000000 --- a/contracts/v9/scenario.schema.json +++ /dev/null @@ -1,471 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://github.com/fallblu/trading-engine/contracts/v9/scenario.schema.json", - "title": "Trading Engine v6 replay scenario", - "description": "Strict deterministic scenario contract with explicit venue-local session policies resolved to absolute instants outside the reducer.", - "type": "object", - "additionalProperties": false, - "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_portfolio", "instruments", "venue_calendars", "risk", "execution", "max_internal_events", "schedule", "slices"], - "properties": { - "contract_version": { "const": "9" }, - "metadata": { "type": "object" }, - "run_id": { "$ref": "#/$defs/identifier" }, - "base_currency": { "$ref": "#/$defs/identifier" }, - "initial_portfolio": { "$ref": "#/$defs/initialPortfolio" }, - "instruments": { - "type": "array", - "minItems": 1, - "maxItems": 4096, - "items": { "$ref": "#/$defs/instrument" } - }, - "venue_calendars": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueCalendar" } - }, - "risk": { "$ref": "#/$defs/risk" }, - "execution": { "$ref": "#/$defs/execution" }, - "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 }, - "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } }, - "slices": { - "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.", - "type": "array", - "items": { "$ref": "#/$defs/marketSlice" } - } - }, - "$defs": { - "identifier": { - "type": "string", - "minLength": 1, - "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$" - }, - "signedDecimal": { - "type": "string", - "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$" - }, - "unsignedDecimal": { - "type": "string", - "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "positiveDecimal": { - "type": "string", - "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$" - }, - "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" }, - "timestamp": { - "type": "string", - "format": "date-time", - "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$" - }, - "cashBalance": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "amount"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "amount": { "$ref": "#/$defs/signedDecimal" } - } - }, - "initialPortfolio": { - "type": "object", - "additionalProperties": false, - "required": ["cash", "positions", "marks", "fx_rates"], - "properties": { - "cash": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/cashBalance" } }, - "positions": { "type": "array", "items": { "$ref": "#/$defs/initialPosition" } }, - "marks": { "type": "array", "items": { "$ref": "#/$defs/initialMark" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } } - } - }, - "initialPosition": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity", "cost_basis", "realized_pnl", "dividend_pnl", "execution_fees", "borrow_fees"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" }, - "cost_basis": { "$ref": "#/$defs/signedDecimal" }, - "realized_pnl": { "$ref": "#/$defs/signedDecimal" }, - "dividend_pnl": { "$ref": "#/$defs/signedDecimal" }, - "execution_fees": { "$ref": "#/$defs/unsignedDecimal" }, - "borrow_fees": { "$ref": "#/$defs/unsignedDecimal" } - } - }, - "initialMark": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "price"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "price": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "instrument": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "symbol": { "$ref": "#/$defs/identifier" }, - "quote_currency": { "$ref": "#/$defs/identifier" }, - "tick_size": { "$ref": "#/$defs/positiveDecimal" }, - "lot_size": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "venueCalendar": { - "type": "object", - "additionalProperties": false, - "required": ["calendar_id", "calendar_version", "venue_id", "instrument_ids", "sessions"], - "properties": { - "calendar_id": { "$ref": "#/$defs/identifier" }, - "calendar_version": { "const": "1" }, - "venue_id": { "$ref": "#/$defs/identifier" }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "sessions": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/venueSession" } - } - } - }, - "venueSession": { - "oneOf": [ - { "$ref": "#/$defs/openVenueSession" }, - { "$ref": "#/$defs/holidayVenueSession" } - ] - }, - "openVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "enum": ["regular", "early_close"] }, - "phases": { - "type": "array", - "minItems": 1, - "maxItems": 5, - "items": { "$ref": "#/$defs/venuePhase" } - } - } - }, - "holidayVenueSession": { - "type": "object", - "additionalProperties": false, - "required": ["session_date", "policy", "phases"], - "properties": { - "session_date": { "type": "string", "format": "date", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" }, - "policy": { "const": "holiday" }, - "phases": { "type": "array", "maxItems": 0 } - } - }, - "venuePhase": { - "type": "object", - "additionalProperties": false, - "required": ["phase", "opens_at", "closes_at"], - "properties": { - "phase": { "enum": ["premarket", "opening_auction", "regular", "closing_auction", "postmarket"] }, - "opens_at": { "$ref": "#/$defs/timestamp" }, - "closes_at": { "$ref": "#/$defs/timestamp" } - } - }, - "risk": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_leverage", "short_borrow_bps", "instrument_policies", "groups"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "max_leverage": { "$ref": "#/$defs/positiveDecimal" }, - "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "instrument_policies": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/instrumentRiskPolicy" } - }, - "groups": { - "type": "array", - "items": { "$ref": "#/$defs/riskGroup" } - } - } - }, - "instrumentRiskPolicy": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "max_order_quantity", "max_long_position", "max_short_position", "max_notional_exposure", "initial_margin_bps", "maintenance_margin_bps", "shorting_allowed"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" }, - "max_long_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_short_position": { "$ref": "#/$defs/positiveDecimal" }, - "max_notional_exposure": { "$ref": "#/$defs/positiveDecimal" }, - "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 }, - "shorting_allowed": { "type": "boolean" } - } - }, - "nullablePositiveDecimal": { - "oneOf": [ - { "type": "null" }, - { "$ref": "#/$defs/positiveDecimal" } - ] - }, - "riskGroup": { - "type": "object", - "additionalProperties": false, - "required": ["group_id", "group_version", "group_type", "instrument_ids", "limits"], - "properties": { - "group_id": { "$ref": "#/$defs/identifier" }, - "group_version": { "const": "1" }, - "group_type": { "enum": ["issuer", "sector", "currency", "country", "asset_class", "custom"] }, - "instrument_ids": { - "type": "array", - "minItems": 1, - "uniqueItems": true, - "items": { "$ref": "#/$defs/identifier" } - }, - "limits": { "$ref": "#/$defs/riskGroupLimits" } - } - }, - "riskGroupLimits": { - "type": "object", - "additionalProperties": false, - "required": ["max_gross_exposure", "max_long_exposure", "max_short_exposure", "max_absolute_net_exposure", "max_concentration"], - "properties": { - "max_gross_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_long_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_short_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_absolute_net_exposure": { "$ref": "#/$defs/nullablePositiveDecimal" }, - "max_concentration": { - "oneOf": [ - { "type": "null" }, - { "allOf": [{ "$ref": "#/$defs/positiveDecimal" }, { "pattern": "^(?:0[.][0-9]{0,5}[1-9]|1)$" }] } - ] - } - } - }, - "execution": { - "type": "object", - "additionalProperties": false, - "required": ["model", "configuration"], - "properties": { - "model": { "const": "completed_bar_v1" }, - "configuration": { "$ref": "#/$defs/completedBarV1Configuration" } - } - }, - "completedBarV1Configuration": { - "type": "object", - "additionalProperties": false, - "required": ["version", "participation_bps", "fee_schedules"], - "properties": { - "version": { "const": "2" }, - "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }, - "fee_schedules": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeSchedule" } } - } - }, - "feeSchedule": { - "type": "object", - "additionalProperties": false, - "required": ["schedule_id", "instrument_id", "settlement_currency", "minimum", "maximum", "components"], - "properties": { - "schedule_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "settlement_currency": { "$ref": "#/$defs/identifier" }, - "minimum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "maximum": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }, - "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/feeComponent" } } - } - }, - "feeComponent": { - "type": "object", - "additionalProperties": false, - "required": ["name", "currency", "kind", "value", "rounding", "applies_to"], - "properties": { - "name": { "$ref": "#/$defs/identifier" }, - "currency": { "$ref": "#/$defs/identifier" }, - "kind": { "enum": ["fixed", "notional_bps", "per_unit"] }, - "value": { "oneOf": [{ "$ref": "#/$defs/signedDecimal" }, { "type": "integer", "minimum": -10000, "maximum": 10000 }] }, - "rounding": { "enum": ["up", "down", "nearest"] }, - "applies_to": { "enum": ["any", "maker", "taker"] } - }, - "allOf": [ - { "if": { "properties": { "kind": { "const": "notional_bps" } } }, "then": { "properties": { "value": { "type": "integer" } } } }, - { "if": { "properties": { "kind": { "enum": ["fixed", "per_unit"] } } }, "then": { "properties": { "value": { "$ref": "#/$defs/signedDecimal" } } } } - ] - }, - "scheduleItem": { - "type": "object", - "additionalProperties": false, - "required": ["after_slice_sequence", "intents"], - "properties": { - "after_slice_sequence": { "$ref": "#/$defs/sequence" }, - "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } } - } - }, - "intent": { - "oneOf": [ - { "$ref": "#/$defs/targetWeights" }, - { "$ref": "#/$defs/targetQuantities" }, - { "$ref": "#/$defs/submitOrder" }, - { "$ref": "#/$defs/cancelOrder" }, - { "$ref": "#/$defs/metric" } - ] - }, - "targetWeights": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_weights" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "weight"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "weight": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "targetQuantities": { - "type": "object", - "additionalProperties": false, - "required": ["type", "targets"], - "properties": { - "type": { "const": "target_quantities" }, - "targets": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "quantity"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "quantity": { "$ref": "#/$defs/signedDecimal" } - } - } - } - } - }, - "submitOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "instrument_id", "side", "quantity", "order_kind", "trigger_price", "limit_price", "time_in_force", "venue_id", "calendar_id", "expires_at"], - "properties": { - "type": { "const": "submit_order" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "side": { "enum": ["buy", "sell"] }, - "quantity": { "$ref": "#/$defs/positiveDecimal" }, - "order_kind": { "enum": ["market", "limit", "stop", "stop_limit"] }, - "trigger_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }, - "time_in_force": { "enum": ["gtc", "ioc", "fok", "day", "gtd"] }, - "venue_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "calendar_id": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] }, - "expires_at": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/timestamp" }] } - }, - "allOf": [ - { "if": { "properties": { "order_kind": { "const": "market" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "limit" } } }, "then": { "properties": { "trigger_price": { "type": "null" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "type": "null" } } } }, - { "if": { "properties": { "order_kind": { "const": "stop_limit" } } }, "then": { "properties": { "trigger_price": { "$ref": "#/$defs/positiveDecimal" }, "limit_price": { "$ref": "#/$defs/positiveDecimal" } } } }, - { "if": { "properties": { "time_in_force": { "const": "day" } } }, "then": { "properties": { "venue_id": { "$ref": "#/$defs/identifier" }, "calendar_id": { "$ref": "#/$defs/identifier" }, "expires_at": { "type": "null" } } } }, - { "if": { "properties": { "time_in_force": { "const": "gtd" } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "$ref": "#/$defs/timestamp" } } } }, - { "if": { "properties": { "time_in_force": { "enum": ["gtc", "ioc", "fok"] } } }, "then": { "properties": { "venue_id": { "type": "null" }, "calendar_id": { "type": "null" }, "expires_at": { "type": "null" } } } } - ] - }, - "cancelOrder": { - "type": "object", - "additionalProperties": false, - "required": ["type", "order_id"], - "properties": { - "type": { "const": "cancel_order" }, - "order_id": { "$ref": "#/$defs/identifier" } - } - }, - "metric": { - "type": "object", - "additionalProperties": false, - "required": ["type", "name", "value"], - "properties": { - "type": { "const": "emit_metric" }, - "name": { "type": "string" }, - "value": { "type": "string" } - } - }, - "marketSlice": { - "type": "object", - "additionalProperties": false, - "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"], - "properties": { - "slice_sequence": { "$ref": "#/$defs/sequence" }, - "start_at": { "$ref": "#/$defs/timestamp" }, - "end_at": { "$ref": "#/$defs/timestamp" }, - "available_at": { "$ref": "#/$defs/timestamp" }, - "received_at": { "$ref": "#/$defs/timestamp" }, - "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } }, - "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } }, - "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } } - } - }, - "bar": { - "type": "object", - "additionalProperties": false, - "required": ["instrument_id", "open", "high", "low", "close", "volume"], - "properties": { - "instrument_id": { "$ref": "#/$defs/identifier" }, - "open": { "$ref": "#/$defs/positiveDecimal" }, - "high": { "$ref": "#/$defs/positiveDecimal" }, - "low": { "$ref": "#/$defs/positiveDecimal" }, - "close": { "$ref": "#/$defs/positiveDecimal" }, - "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] } - } - }, - "fxRate": { - "type": "object", - "additionalProperties": false, - "required": ["currency", "rate"], - "properties": { - "currency": { "$ref": "#/$defs/identifier" }, - "rate": { "$ref": "#/$defs/positiveDecimal" } - } - }, - "corporateAction": { - "oneOf": [ - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "numerator", "denominator"], - "properties": { - "type": { "const": "split" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "numerator": { "$ref": "#/$defs/sequence" }, - "denominator": { "$ref": "#/$defs/sequence" } - } - }, - { - "type": "object", - "additionalProperties": false, - "required": ["type", "action_id", "instrument_id", "amount_per_unit"], - "properties": { - "type": { "const": "cash_dividend" }, - "action_id": { "$ref": "#/$defs/identifier" }, - "instrument_id": { "$ref": "#/$defs/identifier" }, - "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" } - } - } - ] - } - } -} diff --git a/docs/api-reference.md b/docs/api-reference.md index d7b9192..090341d 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -7,4 +7,4 @@ that every public interface has a corresponding page. The generated reference describes library types and functions. The versioned JSON and JSON Lines -files under [Contracts](../contracts/v16/README.md) remain authoritative for process boundaries. +files under [Contracts](../contracts/v1/README.md) remain authoritative for process boundaries. diff --git a/docs/architecture.md b/docs/architecture.md index 8f6357f..afb946d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -124,7 +124,7 @@ Running the same scenario bytes produces byte-identical audit lines. `Engine.Interactive` stops at each strategy request and exposes the immutable context and event. Its `resume` transition accepts typed intents and continues the same pure reducer. The scripted runner invokes an in-process callback at that boundary. The external runner serializes it through -protocol v4. Reducer state never contains a process, clock, pipe, timeout, or file handle. +protocol v1. Reducer state never contains a process, clock, pipe, timeout, or file handle. Each strategy callback carries an account valuation built at that reducer boundary. All callbacks for a slice use its receipt time, completed bars, and FX vector. A callback response is reduced diff --git a/docs/continuous-integration.md b/docs/continuous-integration.md index dbe9e62..cd6e70a 100644 --- a/docs/continuous-integration.md +++ b/docs/continuous-integration.md @@ -1,35 +1,21 @@ # Continuous integration -CI tests a small, explicit environment matrix instead of an accidental Cartesian product. The -public package bounds in `trading_engine.opam` define supported dependencies. The repository lock -defines the reproducible development baseline. +CI tests the supported OCaml and dependency range without creating a Cartesian product. -| Cell | Operating system | OCaml | Dependencies | Gate | Status | -| --- | --- | --- | --- | --- | --- | -| `check` | Ubuntu latest | 5.5.0 | Exact lock | Full `make check` | Required | -| `lowest-ubuntu` | Ubuntu latest | 5.5.0 | Oldest solver-valid versions inside declared bounds | Full dependency-band check | Required | -| `highest-ubuntu` | Ubuntu latest | 5.5.0 | Newest solver-valid versions inside declared bounds | Full dependency-band check | Required | -| `highest-macos` | macOS 15 | 5.5.0 | Newest solver-valid versions inside declared bounds | Build and exact journal comparison | Informational | +| Cell | Platform | Dependencies | Gate | +| --- | --- | --- | --- | +| `check` | Ubuntu | Repository lock | Full `make check` | +| `lowest-ubuntu` | Ubuntu | Oldest declared versions | Dependency-band check | +| `highest-ubuntu` | Ubuntu | Newest declared versions | Dependency-band check | +| `highest-macos` | macOS | Newest declared versions | Build and journal comparison | -The lower and upper cells resolve against the current opam repository. They deliberately test the -range declared by the package rather than pretending to be reproducible locks. A failure in either -required Ubuntu cell means the declared support bounds or the implementation must change. The -macOS cell is an early portability signal while Ubuntu remains the supported build platform. +Required Ubuntu jobs validate contract v1 schemas and fixtures, OCaml tests, protocol fuzzing, +deterministic journals, metadata, documentation, and benchmark smoke workloads. Coverage runs once +against the locked environment. -Every runtime cell replays the frozen v3 demo, v5 demo, and v5 risk-limited fill scenarios under -`TZ=UTC` and the C locale. It compares the resulting journal files byte for byte with their -canonical fixtures. Standard output and standard error are captured separately because human -diagnostics may contain platform-specific paths or process details and are not part of the journal -contract. -The full test suite additionally validates and replays the current v16 batch, stream, journal, and -strategy-v12 fixtures, including quote/trade causality and the reconciled first valuation. +The required Persistra job uses a full pinned commit. A manually dispatched moving-head job is +informational and may fail without changing the supported revision pair. -Coverage runs once in the exact locked Ubuntu environment. The required Persistra job also runs -once against its full pinned commit; it is not repeated across dependency or operating-system -cells. The manually dispatched Persistra moving-head job remains informational. - -Feature-branch pushes do not start CI; the pull-request event owns that validation and avoids a -duplicate check set. Pull requests cancel superseded commits. Push validation runs only on -`develop` and tags, where it is never cancelled, so durable integration evidence is not discarded. -The concurrency key combines the source repository and source branch without colliding with a fork -or another branch. +Pull requests own feature-branch validation and cancel superseded runs. Push validation runs on +`develop` and release tags without cancellation so integration and publication evidence is +retained. diff --git a/docs/documentation-platform.md b/docs/documentation-platform.md index 787fc7a..87c152e 100644 --- a/docs/documentation-platform.md +++ b/docs/documentation-platform.md @@ -13,8 +13,8 @@ live in `requirements/docs.lock`; the exact odoc version lives in `trading_engin The build stages the repository Markdown and entire `contracts/` tree under `_build`, adds the odoc HTML tree, and then runs `mkdocs build --strict`. Staging publishes contract README files, schemas, -and fixtures directly from their source locations. Frozen v1 and v2 pages therefore keep stable -versioned URLs and cannot diverge from the repository copies. +and fixtures directly from their source locations, so the v1 pages cannot diverge from the +repository copies. `make docs-check` performs the deterministic offline source check. `make docs-build` bootstraps the locked documentation tools, builds odoc, runs strict MkDocs, checks every generated local link, and diff --git a/docs/execution-model.md b/docs/execution-model.md index 157fcaf..745c039 100644 --- a/docs/execution-model.md +++ b/docs/execution-model.md @@ -1,283 +1,74 @@ # Execution model -The engine selects a compiled execution module by the scenario's stable `execution.model` name. -Contract v16 advertises `completed_bar_v1`, `completed_bar_next_open_v1`, -`completed_bar_adverse_touch_v1`, `quote_trade_v1`, and `order_book_v1`; embedders can inject another module through -the typed engine configuration without introducing runtime shared-library loading. The selected -name is repeated in both terminal audit records. +The scenario selects one compiled model by `execution.model`. Each model uses strict configuration +version `"1"`, declares its required fields through `--capabilities`, and shares the same order, +risk, fee, settlement, accounting, and audit pipeline. -Each compiled model owns a strict configuration contract. The v16 envelope separates selection from -model-specific parameters: +## Available models -```json -{ - "execution": { - "model": "completed_bar_v1", - "configuration": { - "version": "2", - "participation_bps": 5000, - "fee_schedules": [ - { - "schedule_id": "acme-fees-v1", - "instrument_id": "acme", - "settlement_currency": "USD", - "minimum": "0.3", - "maximum": "5", - "components": [ - { "name": "broker", "currency": "USD", "kind": "fixed", "value": "0.25", "rounding": "up", "applies_to": "any" }, - { "name": "exchange", "currency": "USD", "kind": "notional_bps", "value": 10, "rounding": "up", "applies_to": "taker" } - ] - } - ] - } - } -} -``` - -The model and configuration version are validated before replay. Unknown models, unsupported -model/version pairs, missing fields, and fields from another model are rejected. Contracts v3 and -v4 retain their frozen flat execution object; v8 and earlier configured envelopes remain frozen. - -`--capabilities` preserves the `execution_models` name list and publishes one deterministic -descriptor per model under `execution_model_contracts`: supported scenario and configuration -versions, required fields, order types, market-data requirements, and numeric limits. Clients can -therefore reject incompatible scenarios without guessing from a shared execution object. - -The completed-bar model consumes synchronized slices of OHLCV bars. Every slice contains exactly -one bar for each configured instrument and produces one matching batch and one closing valuation. - -The conservative models use strict configuration version `"1"`. Both require `spread_model` with -`model: "fixed_half_spread_v1"` and `half_spread_bps`, plus `impact_model` with -`model: "linear_participation_v1"`, `coefficient_bps`, and `missing_volume_policy`. The latter is -either `reject` or `zero_impact`; no ambient spread or volume data is inferred. - -The quote/trade model also uses configuration version `"1"`, with `participation_bps` and the same -fee-schedule catalog. It consumes each slice's events in `(available_at, received_at, -ingest_sequence)` order. Market orders and marketable limits consume only the displayed quote size -on their side. Passive buys consume only sell-aggressor trades at or below their limit; passive -sells consume only buy-aggressor trades at or above it. An `unknown` aggressor never supplies a -passive fill. Each event has independent, lot-rounded capacity, and its `event_at` is the fill's -economic timestamp. Completed bars remain required solely for synchronized valuation. +| Model | Market evidence | +| --- | --- | +| `completed_bar_v1` | Next eligible open and optimistic intrabar limit touch | +| `completed_bar_next_open_v1` | Later marketable opens with explicit spread and impact | +| `completed_bar_adverse_touch_v1` | Opens or one-tick adverse trade-through with costs | +| `quote_trade_v1` | Displayed quotes and aggressor-classified trades | +| `order_book_v1` | Bounded level-two snapshots and contiguous updates | -The order-book model uses configuration version `"1"`, adding `max_depth_levels` from 1 through -1,024. Each instrument's slice-local bundle begins with a full bid/ask snapshot and uses contiguous -absolute set, delete, and trade updates. Crossed states, gaps, missing deletes, and states beyond -the depth limit fail replay; a locked best bid and ask is accepted. Each later slice starts from a -fresh snapshot, so no unbounded or hidden book state survives a slice boundary. +Completed bars remain mandatory for synchronized valuation. Conservative models require fixed +half-spread and linear participation-impact policies. Quote/trade and order-book models use causal +availability, receipt, and ingest ordering and never infer hidden liquidity. -Marketable orders walk observable opposite-side levels in price order. Passive limits start behind -the displayed quantity at their price and behind earlier engine orders. Reductions decrease queue -ahead, additions join behind, and an aggressor-qualified trade consumes queue ahead before filling -the order. This model has its own liquidity state and does not reuse completed-bar or quote/trade -fill semantics. Bars remain mandatory only for valuation. +## Eligibility and order lifetime -## Eligibility - -An order records the slice after which it is eligible. The matcher requires: +An order becomes eligible only when both conditions hold: ```text eligible_after_slice_sequence < current slice_sequence created_at <= current slice start_at ``` -This prevents an order emitted from a completed slice from filling inside that slice or at an open -that predates the order. The parser also requires scheduled order-changing intents to arrive by -the next slice start. - -## Portfolio targets - -`target_weights` and `target_quantities` contain one target for every configured instrument. A -weight request: - -1. Values the current account at all synchronized slice closes. -2. Multiplies that equity by each exact weight. -3. Divides by the corresponding closing price. -4. Rounds down to the instrument lot. - -Weights and quantities are signed. Gross absolute weight must stay within `max_leverage`, quantity -targets must align with their lots, and every desired quantity must stay within the configured long -or short position limit. A target that changes sign is reached causally: flatten first, then open -the opposite side on a later attempt. - -The computed desired quantities persist. After each slice, the engine compares them with actual -positions and submits at most one market order per instrument. Each order is capped at -`max_order_quantity` and rounded down to a lot, so large targets advance in bounded chunks. A -market remainder is IOC, but the desired target is retried after a later slice until reached or -superseded. +Market orders attempt the next eligible evidence and cancel any IOC remainder. Limit orders use +their configured time in force. Stop orders activate when their trigger is observed. FOK requires +the full quantity to pass liquidity and risk checks before any fill is applied. -## Working-order risk +Persistent portfolio targets are reconciled in lot-aligned, maximum-order-sized attempts until the +target is reached or replaced. A sign change flattens before opening the opposite side. -Pre-trade risk reserves each active order's unfilled quantity by side. For every instrument, it -values both the position after all reserved buys and the position after all reserved sells, then -uses the larger absolute endpoint for portfolio exposure. Opposing orders therefore cannot hide -risk by netting before either execution path is known. +## Capacity, priority, and callbacks -A new order is rejected while an active opposite-side order exists for the same instrument. This -self-cross rule applies to direct and target-generated orders. Same-side orders may coexist, and -their remaining quantities share the applicable long or short position limit. Risk-reducing orders -remain permitted when an actual position is already outside a limit, but one order may not cross -that position through zero. Fill-time position, exposure, leverage, and margin checks remain the -final defense against price and account changes after acceptance. +Completed-bar capacity is volume multiplied by `participation_bps`, rounded down to the instrument +lot. Quote and book models use only displayed or causally consumed liquidity. Liquidation orders +run first; within an origin class sells precede buys, followed by FIFO creation order. -## Market and limit prices - -A market order executes at the open of its first eligible slice. - -For a buy limit `L`: - -1. If `open <= L`, fill at `open`. -2. Otherwise, if `low <= L`, fill at `L`. -3. Otherwise, do not fill. - -Sell limits use the symmetric open/high rule. Limit remainders remain GTC. The open rule gives -deterministic gap improvement. The frozen `completed_bar_v1` touch rule is optimistic because completed bars contain no -queue, path, or available-size evidence at the limit. - -`completed_bar_next_open_v1` fills a limit only at a later marketable open. -`completed_bar_adverse_touch_v1` additionally permits maker fills after the completed bar trades -through the limit by at least one instrument tick. Its pre-cost reference is that one-tick adverse -price. A mere touch does not fill. - -For both conservative models, fixed half-spread and participation-linear impact are rounded away -from the reference price to whole instrument ticks. Buy adjustments add and sell adjustments -subtract. A cost-adjusted price that would violate a limit is ineligible. Before each fill the -engine emits `execution_price_selected`, attributing reference price, spread adjustment, impact -adjustment, and final executable price; the fill causally references that event. - -## Capacity and priority - -Missing volume means unlimited simulated capacity. Otherwise: - -```text -raw capacity = floor(volume × participation_bps / 10,000) -capacity = raw capacity rounded down to the instrument lot size -``` +After each fill, the reducer applies the strategy callback response before examining the next +eligible order. A cancellation can therefore remove a later same-slice order. Newly submitted +orders wait for another slice. -Eligible liquidation orders are ordered before all other orders across the slice. Within the -liquidation and ordinary origin classes, sells precede buys; orders within a side then use -ascending creation sequence and order ID. Each instrument has its own shared capacity, so the -higher-priority order consumes that instrument's capacity first. +## Risk and fees -## Callback boundaries +Admission reserves every active order's remaining quantity. Fill-time checks use the actual price +and search for the largest permitted lot-aligned quantity under instrument position/notional, +portfolio gross exposure/leverage, margin, locate, and maximum-order limits. Exposure-reducing +fills remain available. A clipped proposal emits a typed `fill_clipped` reason. -The matcher fixes the eligible-order sequence at the slice boundary and advances it with an -immutable cursor. After each fill, the engine pauses matching and applies the strategy response -before examining the next order. The cursor then reads that order from the current OMS, skips it -if an earlier response made it terminal, and preserves any capacity that was not consumed. Orders -submitted by a callback are not part of the cursor and remain ineligible until a later slice. +Each instrument has exactly one fee schedule. Components may be fixed, notional basis points, or +per-unit; use explicit currency, rounding, and maker/taker applicability; and may include schedule +minimums, maximums, or rebates. FX conversion and every adjustment are retained in attribution. -## Corporate actions and borrow +## Financing, settlement, and lifecycle -Corporate actions are ordered by action ID and applied before matching. A split scales the signed -position, persistent quantity target, and each active order by its exact numerator/denominator -ratio. It inversely scales limit prices and preserves total position basis. If the adjusted order -cannot satisfy the configured lot or tick, the slice fails instead of silently rounding. Each -changed order emits `order_adjusted` with causal links to both the original order and split. -Unit-based risk limits do not scale with a split. Adjusted positions and persistent targets are -grandfathered: fills may reduce an out-of-limit absolute position but may not increase it, and -reconciliation orders remain bounded by the configured maximum order quantity. An adjusted active -order may exceed that maximum, but no individual fill may do so. +Effective-time observations drive short availability, borrow charges, recalls, and per-currency +credit or debit interest. Settlement instructions use explicit business calendars and lags, with +configured settled or total cash and position availability. -A cash dividend multiplies the pre-match signed position by its per-unit amount. It credits a long -or debits a short in the instrument's quote-currency ledger and records realized dividend P&L. -Stock dividends, rights, and spin-offs deliver a lot-aligned exact-ratio entitlement. Their payload -allocates basis explicitly and either rejects fractions or converts them at a declared -quote-currency price. Stock dividends also scale persistent targets and eligible working orders. - -Lifecycle events follow corporate actions and precede matching. Identifier changes preserve the -stable instrument ID while updating the symbol and named provider mapping. Halts and terminal -events cancel active orders. Expiration and delisting use an explicit hold or cash-out policy and -cannot be resumed. -Contract v10 replaces the fixed legacy rate with effective-time borrow observations. Each -observation names an instrument, available quantity, annual rate in basis points, and recall state. -Observations become active no later than the slice start and remain active until superseded. A new -short either clips to the available locate or is rejected according to `locate_policy`; existing -short quantity consumes availability. A recall rejects further shorts and, under `close_out`, -cancels active sells and submits a priority IOC buy until the short is flat. `reject_new_shorts` -retains the position but prevents it from increasing. - -Before matching, each open short accrues its observed quote-currency charge from the slice open -mark and exact `start_at`/`end_at` duration. Missing observations follow `borrow_missing_data`: -`reject` fails the slice and `zero` applies no charge while still preventing an unlocated new short. -Signed rates support rebates. Charges use the scenario's explicit `actual_365` or `actual_360` -day-count and `simple` or `daily` compounding policy. - -Cash financing uses effective-time observations per currency with separate annual credit and debit -rates. Positive balances receive the credit rate; negative balances receive the debit rate. The -same explicit interval, day-count, compounding, and deterministic micro-unit rounding rules apply. -`cash_missing_data` either rejects a nonzero balance without an observation or treats its rate as -zero. Interest updates the native cash ledger and is reported separately and within aggregate -realized P&L; debit interest can therefore produce or deepen negative equity. - -## Risk-limited fills and fees - -Contract v10 selects exactly one fee schedule per instrument. A schedule composes named `fixed`, -`notional_bps`, and `per_unit` components. Each component declares its currency, `up`, `down`, or -`nearest` rounding, and `any`, `maker`, or `taker` applicability. A limit filled at its intrabar -touch is maker liquidity; market orders and limits marketable at the open are takers. - -Component amounts are calculated in their declared currencies. Slice FX rates convert quote -notional into the component currency and each result back into the fill's quote currency. The -schedule then applies its optional minimum and maximum in the settlement currency. Any difference -is retained as a named `minimum_adjustment` or `maximum_adjustment`, so the component list always -sums exactly to the signed aggregate fill fee. Negative components are rebates. - -Liquidation proposals are processed first, followed by sells and then buys within each origin -class. For each proposal, the engine searches for the largest lot-aligned quantity whose signed -post-fill position is within the long/short cap and whose fill quantity is no greater than the -maximum order quantity. -When absolute exposure increases, the projected account must also satisfy maximum gross exposure, -maximum leverage, and initial margin. Reductions in absolute exposure are permitted without a new -initial-margin test. A clipped proposal emits `fill_clipped`; a zero permitted quantity produces -no fill. The event records reason taxonomy version `1`, the limiting policy, its typed threshold, -and both the proposed and permitted quantities. Only the applied quantity consumes shared slice -capacity. Candidate arithmetic, accounting, mark, and FX failures abort replay instead of being -misreported as policy clipping. - -This bounded-fill policy preserves split-adjusted GTC limit orders: an oversized remainder may -fill over multiple slices. Market orders remain IOC, so they fill at most one bounded quantity and -cancel any remainder after their eligible slice. - -The complete schedule, including minimum and maximum, is evaluated independently for every partial -fill, so fragmentation can change total cost. Contract v8 configuration v1 retains its frozen -`fixed_fee + ceil(notional × fee_bps / 10,000)` rule. - -## Exact values - -Prices, weights, quantities, FX rates, and money use six decimal places stored in checked `int64` -values. Signed quantities are used for positions and targets; submitted orders and fills retain a -positive quantity plus a side. Scenario strings use the canonical shortest representation: `1`, -`1.25`, `-0.5`, and `0.000001` are valid; `01`, `1.0`, excess precision, and negative zero are not. - -Orders align with lot size. Limit prices and executable OHLC values align with tick size. +Corporate actions run before matching. Splits adjust positions, targets, and working orders; +distributions allocate basis and fractional treatment explicitly. Lifecycle events preserve stable +instrument identity across symbol changes and deterministically cancel or cash out terminal assets. ## Accounting and valuation -For a buy that opens or increases a long with notional `N` and fee `F`: - -```text -cash -= N + F -quantity += fill quantity -cost basis += N + F -``` - -For a sell that reduces a long: - -```text -cash += N - F -removed basis = proportional average cost -realized P&L += N - F - removed basis -``` - -Opening a short credits `N - F` to cash and records its cost basis as the negative net proceeds. -Covering a short debits `N + F`; realized P&L is the removed negative basis minus that cover cost. -One fill may reduce a position to zero but may not cross through zero. Closing a position removes -its exact remaining basis. A partial close uses proportional average basis and leaves the exact -remainder open. - -The account maintains a signed cash ledger for every scenario currency. Each slice supplies a -complete currency-to-base FX vector, with base rate one. Valuation converts native cash, market -value, basis, P&L, and fees into the base reporting currency using the current marks: +The engine uses signed average-cost accounting in native quote currencies and converts every cash, +position, basis, P&L, and fee attribution to the scenario base currency. The core identities are: ```text net market value = sum(base FX × mark × signed quantity) @@ -286,18 +77,5 @@ unrealized P&L = net market value - remaining base cost basis equity = base cash + net market value ``` -Each valuation also emits one deterministic attribution row per marked instrument or retained -account position. A nonzero position requires a mark. A flat retained position does not; when its -mark is omitted, the row uses the canonical mark one because every mark produces zero market value -for zero quantity. Row market value, basis, realized P&L, dividend P&L, execution fees, and borrow -fees is present in both native and base values and sums exactly to the corresponding account totals. -A separate row attributes each currency ledger. Closed instruments retain cumulative realized P&L -and fees with zero quantity and basis. - -The valuation includes initial and maintenance requirements and excesses. After strategy and -target processing, negative maintenance excess triggers one `margin_call`, cancels all active -orders, clears the persistent target, and submits deterministic `margin_liquidation` market orders -in instrument-ID order. Strategies receive the resulting cancellation and liquidation-order -updates before the slice valuation. Each attempt is capped by `max_order_quantity` and lot aligned. -The engine continues on later slices until every position is flat, then emits `margin_restored` -when the maintenance condition is no longer breached. +Valuations include initial and maintenance margin. A maintenance breach cancels working orders, +clears targets, and creates bounded liquidation orders until positions are flat. diff --git a/docs/persistra.md b/docs/persistra.md index 8ebacb5..88070e9 100644 --- a/docs/persistra.md +++ b/docs/persistra.md @@ -1,130 +1,46 @@ # Persistra integration -Persistra and Trading Engine remain separate projects behind a strict process and file boundary. +Persistra and Trading Engine communicate only through versioned files and processes. -Persistra owns provider data, normalized observations, revisions, point-in-time research, -portfolio construction, manifests, analysis, and visualization. Trading Engine owns causal event -sequencing, target sizing, risk, order and fill state, execution simulation, exact accounting, and -execution audit artifacts. +Persistra owns provider ingestion, normalized point-in-time observations, research, portfolio +construction, and run manifests. Trading Engine owns causal sequencing, risk, orders, simulated +execution, financing, settlement, accounting, and audit journals. The engine never reads +Persistra's internal database. ## Handoff -The JSON scenario carries: +Persistra produces scenario contract v1 batch or stream input and should: -- Required `contract_version` identifying the scenario and journal protocol -- Required producer metadata preserved as JSON but ignored by execution -- Required compiled execution-model selection -- One explicit executable-instrument catalog -- Signed position, exposure, leverage, margin, borrow, participation, and fee policies -- Strictly increasing synchronized market slices with complete FX marks and corporate actions -- Effective-time borrow availability, recall, and per-currency credit/debit rate observations -- Explicit signed initial cash and positions with accounting history, marks, and FX state -- Optional scheduled full-portfolio signed weight or fractional quantity targets -- Optional direct orders, cancellations, and metrics +1. Preserve stable executable-instrument identities and provider provenance. +2. Supply complete tick, lot, currency, calendar, risk, execution, financing, and settlement + configuration. +3. Build ordered synchronized slices with explicit availability and receipt times. +4. Preserve target weights instead of pre-sizing them outside the engine. +5. Validate schemas and run `--validate-only` before accepting a replay. +6. Require v1 in the engine's advertised scenario and journal capabilities. +7. Retain the exact scenario hash and require one terminal `run_completed` record. +8. Reconcile journal cash, positions, exposure, P&L, fees, margin, and causal references. -Persistra should: +External strategies use [strategy protocol v1](../contracts/strategy/v1/README.md). Persistra must +retain the scenario, transcript, journal, executable identity, input hashes, and run manifest as one +bound artifact set. -1. Query normalized raw executable bars through its public store API. -2. Preserve provider-scoped instrument IDs or apply an explicit catalog mapping. -3. Supply tick, lot, currency, availability, and receipt policies. -4. Group one bar per instrument into each synchronized slice. -5. Preserve original portfolio weights in `target_weights` instead of pre-sizing them. -6. Populate `metadata` with dataset, policy, and build provenance. -7. Read `--capabilities` and require support for the scenario, journal, and optional strategy - protocol versions. -8. Validate the scenario through the JSON Schema and `--validate-only`. -9. Run the CLI as a separate process and import its audit journal. -10. Require the same contract version and deterministic run-scoped event-ID derivation on every - journal record. -11. Reject duplicate, unknown, forward, cross-run, or noncanonical causal references. -12. Verify the same scenario SHA-256 and selected execution model in `run_started`, - `run_completed`, and the retained manifest. -13. Reconcile every native/base position row and currency cash row to the aggregate account, - exposure, fee, and margin values. -14. Reconcile split adjustments, dividends, borrow and cash financing, recalls, risk-limited fills, - and margin liquidation against scenario and runtime state. -15. For external replay, require an empty schedule, launch an explicit strategy argument vector, - hash every declared strategy input, and validate the complete bidirectional transcript. -16. Reconcile external transcript intents to their journal outcomes. -17. Require the terminal completion record before accepting a replay. +## Compatibility gate -Do not let the engine read Persistra's internal DuckDB tables. Their schema and connection -lifecycle belong to Persistra. +Compatibility means the v1 wire contracts pass against an explicit pair of repository commits. +The required `persistra-compatibility` CI job pins the complete Persistra revision in +`.github/workflows/ci.yml`; Persistra owns the reciprocal Trading Engine pin. Neither repository +silently follows a moving branch for its required gate. -Persistra currently uses the transitional v3 -[scenario](../contracts/v3/scenario.schema.json) and -[journal](../contracts/v3/journal.schema.json) schemas and their adjacent conformance fixtures for -structural checks. The engine advertises current contract v16 while retaining v15 through v3 and -exact v3 journal output for v3 inputs. The engine parser is authoritative for ordering, catalog coverage, -causality, tick, lot, risk, and accounting invariants that JSON Schema cannot express. +Advance a pin only after both exact checkouts pass their native and cross-repository suites. When +the shared boundary changes, update schemas, fixtures, documentation, and pins together. The +optional moving-head canary is informational and does not change the supported baseline. -External strategies use the separate -[strategy protocol v14](../contracts/strategy/v14/README.md). Persistra's host turns protocol -initialization, marked portfolio contexts, market-slice, fill, order, and rejection events into -typed callbacks. Realized weights are available only for positive equity. The retained run -manifest binds the strategy identity, executable hash, declared input hashes, transcript hash, -scenario hash, and journal hash. Strategy standard output remains protocol-only; logs and -diagnostics use standard error. +## Time and data rules -Persistra must answer each callback before the engine continues matching. Every callback for a -slice uses the slice receipt time and complete bar and FX snapshot. A later callback therefore -includes accepted intents returned from an earlier callback at that same replay clock. +Use raw prices for execution. Adjusted data may feed research features, but splits and +distributions must be explicit engine events. Provider as-of and Persistra retrieval times remain +provenance; `available_at` and `received_at` define replay causality. -## Compatibility guarantees - -Compatibility is defined by versioned wire contracts and an explicitly tested pair of repository -revisions. A branch name, package version, or successful build in only one repository is not a -compatibility claim. - -- **Engine:** `--capabilities` is the authoritative machine-readable surface. The engine must - reject unsupported versions and malformed or semantically invalid input before reporting a - successful run. -- **Scenario:** Frozen scenario and stream artifacts do not change. The current v16 contract may - receive additive changes only when old valid inputs retain their meaning; breaking changes need - a new version. Transitional v3 support remains explicit in `--capabilities`. -- **Journal:** A run emits the journal version paired with its accepted scenario. Record ordering, - causal references, scenario hashing, terminal completion, and exact accounting remain runtime - invariants even when JSON Schema cannot express them. -- **Strategy:** Protocol and transcript versions are independent of scenario versions. The current - external boundary is strategy v13; a host must complete its exact initialization, event, - shutdown, timeout, and rejection lifecycle. -- **Persistra:** The required integration gate uses a full Persistra commit and its v3 scenario, - journal, and strategy integration tests. Passing that gate claims compatibility only for the - recorded revision pair and advertised versions. - -The required `persistra-compatibility` job pins the full Persistra commit stored as -`PERSISTRA_COMPAT_REVISION` in `.github/workflows/ci.yml`. It asserts the resolved checkout and -writes the SHA to the log and job summary. It never follows a repository variable or moving branch. -Persistra owns the reciprocal required pin to a reviewed Trading Engine commit. - -To advance either baseline, the repository changing its pin selects a green full commit from the -other repository, builds both exact checkouts, runs the cross-repository integration suite, and -updates the one workflow SHA in a reviewed pull request. When a contract or host/runtime behavior -changes, both repositories update their fixtures, documentation, and pins in dependency order. -Neither repository silently advances the other's required baseline. - -Maintainers can manually dispatch CI with `persistra_latest_head` enabled to test Persistra -`develop`. The `persistra-latest-head` job is nonrequired and allowed to fail, so it provides an -early signal without changing the reproducible baseline or blocking an unrelated engine change. - -## Time mapping - -- Intraday UTC timestamps map to slice event times. -- Daily labels require an explicit venue-calendar delivery policy. -- Provider as-of time remains source provenance. -- Persistra retrieval time remains acquisition provenance, not replay availability. -- `available_at` states when a strategy may use the complete synchronized slice. -- `received_at` states when the engine run observes it. -- A scheduled order-changing intent must arrive no later than the next slice start. - -Use raw prices for execution. Adjusted values can feed features, but splits and dividends require -explicit engine events before adjusted histories can support share-and-cash accounting. - -## Larger artifacts - -JSON is suitable for small and moderate scenarios. Use the versioned JSON Lines scenario stream -for larger histories. It carries one static header, one slice with its causally adjacent intents -per record, and a required terminal count. The engine validates and replays it with bounded input -and audit memory. Persistra should retain and hash that immutable stream beside the journal and -run manifest. The stream remains a file boundary; it does not couple the engine to Persistra's -database tables. +Use the JSON Lines scenario stream for larger histories. It remains an immutable file boundary, +not a database coupling. diff --git a/docs/scenario.md b/docs/scenario.md index a15d7a3..951e6fb 100644 --- a/docs/scenario.md +++ b/docs/scenario.md @@ -1,340 +1,73 @@ -# Scenario contract +# Scenario and journal -A replay scenario uses either one strict JSON object or a strict JSON Lines stream. Exact prices, -weights, quantities, money, and sequences are canonical JSON strings. Counts and basis points are -JSON integers. Unknown, missing, duplicate, noncanonical, and non-finite values fail parsing. - -Use [the v16 demo](../contracts/v16/fixtures/demo.scenario.json) as the canonical complete example. -The [scenario JSON Schema](../contracts/v16/scenario.schema.json) provides structural validation. -The engine parser also enforces cross-field and cross-record invariants. Diagnostics identify the -failed field or array item. Stream diagnostics additionally retain the record line and sequence. +Replay input is either one strict JSON scenario or an equivalent JSON Lines stream. The +[v1 schema](../contracts/v1/scenario.schema.json) and +[canonical fixture](../contracts/v1/fixtures/demo.scenario.json) define the batch form. ```sh trading-engine --input scenario.json --validate-only trading-engine --input scenario.jsonl --input-format jsonl --validate-only ``` -Use `--input - --input-format jsonl` to read a stream from standard input. The CLI spools at most -1 GiB to a private temporary file so the same bytes can be hashed, validated, replayed, and hashed -again. Batch JSON cannot use standard input. - -## JSON Lines stream - -Use the stream for histories that should not be materialized inside the engine. The first record -is `scenario_header` and carries the static top-level fields. Each `market_slice` record carries -one complete slice and the intents evaluated after that slice. The final `scenario_end` record -declares the number of slices. It is required even for an empty stream, so a truncated valid -prefix cannot be mistaken for a complete scenario. - -Every record has exactly `contract_version`, `scenario_sequence`, `record_type`, and `payload`. -The contract version is repeated, and `scenario_sequence` is contiguous from one. Intents are -adjacent to their decision slice rather than stored in a future-looking global schedule. Before -replay, the reader checks each intent-bearing slice against the next slice's start time while -retaining only those two records. - -The batch object and stream header share one domain-construction path and the same static semantic -checks. Stream items reuse the batch slice and intent validators directly; no synthetic batch -scenario is constructed. - -The [stream record JSON Schema](../contracts/v16/scenario-stream.schema.json) validates each line, -and [the v16 stream fixture](../contracts/v16/fixtures/demo.scenario.jsonl) is the canonical example. -The engine validates the entire stream before creating a journal. It then replays one record at a -time without retaining prior slices, scheduled batches, or audit events. Reducer state still -retains current account, order, target, and latest-bar state required by execution semantics. - -## Top-level fields - -| Field | Meaning | -|---|---| -| `contract_version` | Required string identifying this file contract; v16 is `"16"` | -| `metadata` | Required arbitrary JSON object preserved for provenance and ignored by execution | -| `run_id` | Stable identity used in generated IDs | -| `base_currency` | Reporting currency used for aggregate risk and valuation | -| `initial_portfolio` | Signed cash and positions with accounting history, marks, and FX state | -| `instruments` | Approved executable-instrument catalog, at most 4,096 entries | -| `venue_calendars` | Immutable venue/session policies covering every configured instrument | -| `risk` | Signed position, exposure, leverage, margin, and borrow policy | -| `execution` | Capacity and fee configuration | -| `financing` | Borrow/cash day-count, compounding, locate, recall, and missing-data policies | -| `settlement` | Business-date calendars, per-instrument lags, and cash/position availability policies | -| `max_internal_events` | Positive reducer feedback cap, at most 100,000 | -| `schedule` | Intents emitted after named slices, at most 4,096 per batch | -| `slices` | Complete synchronized market observations | - -Metadata may contain nested JSON values. Duplicate object keys and non-finite numbers are rejected -at any depth. Metadata is retained on `Scenario.t` but never affects execution. - -An external strategy replay requires `schedule: []`. The JSON Lines form likewise requires every -slice record's `intents` array to be empty. This keeps one authoritative decision source: either -the scenario contract or the separate strategy protocol, never both. - -Each JSON Lines record is limited to 1 MiB, excluding its line feed. The reader accepts a final -record without a line feed and drains an oversized record without retaining bytes above the limit. - -Use `--journal -` to write a journal to standard output. The engine first creates and verifies a -complete temporary journal, then copies only journal bytes to the pipe. The final `run_completed` -record and a zero process exit status signal completeness. Success summaries move to standard error, -and diagnostics always use standard error, so protocol, journal, and summary bytes never share one -stream. Pipes do not provide exclusive no-replace publication, atomic linking, retained partial -artifacts, directory synchronization, or restart durability. They cannot be combined with -`--durable-artifacts`. - -## Instruments, risk, and execution - -Each instrument contains `instrument_id`, `symbol`, `quote_currency`, `tick_size`, and `lot_size`. -Identifiers and labels are nonempty and contain no whitespace or control characters. Tick and lot -sizes are positive exact values with at most six decimal places. Quote currencies may differ from -`base_currency`; `initial_portfolio.cash` contains every distinct quote currency plus the base -currency exactly once. - -## Initial portfolio - -The v6 `initial_portfolio` contains `cash`, `positions`, `marks`, and `fx_rates`. Cash is signed and -has exact scenario-currency coverage. Each nonzero signed position names a catalog instrument and -records signed `quantity` and `cost_basis`, signed `realized_pnl` and `dividend_pnl`, and -nonnegative `execution_fees` and `borrow_fees`. Basis has the same sign as quantity. These P&L and -fee values are point-in-time histories; importing them does not apply them to cash again. - -Position quantities align to instrument lots and respect long and short limits. Marks cover the -position set exactly, are positive, and align to instrument ticks. FX rates cover every scenario -currency exactly and the base rate is one. Before replay, the engine constructs the account, -reconciles its valuation, and enforces gross exposure, leverage, and initial margin. It accepts -negative cash when the complete marked account remains valid under the configured risk policy. - -## Venue calendars - -Contract v7 requires every instrument to belong to exactly one explicit venue calendar. A calendar -is identified by `venue_id`, `calendar_id`, and `calendar_version`; version 1 is the only supported -calendar payload. Its `sessions` are unique and ordered by `session_date`, and each date declares -one policy: `regular`, `early_close`, or `holiday`. Holidays have no phases. Open sessions must -contain a `regular` phase and may also contain `premarket`, `opening_auction`, `closing_auction`, -and `postmarket` phases in market order. Phase intervals cannot overlap. - -All phase boundaries are absolute RFC 3339 timestamps. Scenario producers, not the reducer, resolve -venue-local civil times, time-zone database versions, daylight-saving changes, and clock effects. -Calendar lookup rejects a date without an explicit policy; it never infers weekends, holidays, or -hours from adjacent entries. This makes future DAY expiry, auction eligibility, settlement, and -daily-bar publication policies depend on versioned input rather than ambient system state. - -Risk contains portfolio-wide positive `max_gross_exposure` and `max_leverage`, annualized -`short_borrow_bps`, exactly one `instrument_policies` entry per catalog instrument, and an explicit -`groups` array. Instrument policies define order, long, short, notional, initial-margin, -maintenance-margin, and shorting limits. Groups carry versioned identities and explicit membership; -they may overlap and can constrain gross, long, short, absolute net, and gross-to-equity -concentration exposure. Admission and fill clipping include working-order reservations. Every -applicable group is enforced, with group identity providing deterministic tie ordering. - -Contract v10 execution contains a stable `model` and a model-owned `configuration`. For -`completed_bar_v1`, configuration version `"2"` contains: - -- `version`, the strict model-configuration contract version -- `participation_bps`, from 0 through 10,000 -- `fee_schedules`, exactly one schedule per instrument. Each schedule has a stable ID, instrument, - settlement currency, nullable minimum and maximum, and one or more named components. - -Each component declares `currency`, `kind` (`fixed`, `notional_bps`, or `per_unit`), a signed -`value`, `rounding` (`up`, `down`, or `nearest`), and `applies_to` (`any`, `maker`, or `taker`). -Signed values permit rebates. Minimums and maximums are nonnegative and apply per fill after the -component values are converted into the settlement currency. - -The engine advertises each model's scenario and configuration versions, required fields, supported -order types, data requirements, and limits through `--capabilities.execution_model_contracts`. The -v8 and earlier contracts retain completed-bar configuration version `"1"`; v3 and v4 preserve -their flat execution object unchanged. - -Contract v13 introduced `completed_bar_next_open_v1` and -`completed_bar_adverse_touch_v1`, each with strict configuration version `"1"`. They retain -`participation_bps` and `fee_schedules`, and additionally require: - -- `spread_model`: `fixed_half_spread_v1` with `half_spread_bps` from 0 through 10,000. -- `impact_model`: `linear_participation_v1` with `coefficient_bps` from 0 through 10,000 and - `missing_volume_policy` set to `reject` or `zero_impact`. - -The next-open model does not infer intrabar limit fills. The adverse-touch model requires a -one-tick trade-through. Both round price costs away from the reference to the instrument tick and -journal reference, spread, impact, and final executable prices separately. - -## Schedule and intents - -Schedule entries are positive, strictly increasing, and anchored to existing slices: - -```json -{ - "after_slice_sequence": "1", - "intents": [ - { - "type": "target_weights", - "targets": [ - { "instrument_id": "asset-a", "weight": "0.6" }, - { "instrument_id": "asset-b", "weight": "0.3" } - ] - } - ] -} -``` - -Supported intents are: - -- `target_weights` with a `targets` array of `instrument_id` and `weight` -- `target_quantities` with a `targets` array of `instrument_id` and `quantity` -- `submit_order` with instrument, side, quantity, kind, and nullable limit price -- `cancel_order` with a deterministic `order_id` -- `emit_metric` with a bounded string `name` and typed `value`. The value object declares - `numeric` (a canonical decimal string), `string`, or `boolean`. Optional `unit`, `aggregation` - (`last`, `sum`, `minimum`, `maximum`, or `mean`), and up to 16 string dimensions carry - reconciliation metadata. Dimension keys are unique and journal encoding sorts them - lexicographically. Contracts through v15 retain the legacy string-only shape. - -Both target forms contain every configured instrument exactly once. Weights and quantities are -signed. Gross absolute weight must not exceed `max_leverage`; quantity targets align to their -instrument lots and stay within the long and short position limits. A rebalance that crosses from -long to short, or short to long, first flattens the existing position and continues toward the -target on a later attempt. - -A market submission uses `"order_kind": "market"` and `"limit_price": null`. A limit submission -uses `"order_kind": "limit"` and a canonical positive price. Static order size, lot, and tick -checks run during parsing; position and outstanding-order checks run in the reducer. - -## Market slices - -Each slice has common timing, one bar per configured instrument, a complete set of currency-to-base -FX marks, zero or more corporate actions, and effective-time borrow and cash-rate observations: - -Timestamps use `YYYY-MM-DD[Tt]HH:MM:SS`, optional one-to-six fractional-second digits, and either -`Z`/`z` or a colonized numeric offset such as `-05:00`. Seconds range from `00` through `59`. -Audit timestamps use the same boundary. - -```json -{ - "slice_sequence": "1", - "start_at": "2026-01-02T14:30:00Z", - "end_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:00:01Z", - "received_at": "2026-01-02T21:00:02Z", - "bars": [ - { - "instrument_id": "asset-a", - "open": "100", - "high": "105", - "low": "99", - "close": "104", - "volume": "100" - } - ], - "fx_rates": [ - { "currency": "USD", "rate": "1" } - ], - "corporate_actions": [], - "borrow_observations": [ - { "instrument_id": "asset-a", "effective_at": "2026-01-02T14:30:00Z", "available_quantity": "1000", "annual_rate_bps": 100, "recalled": false } - ], - "cash_rate_observations": [ - { "currency": "USD", "effective_at": "2026-01-02T14:30:00Z", "credit_rate_bps": 100, "debit_rate_bps": 200 } - ], - "settlement_failures": [] -} -``` +## Scenario structure -Use `null` volume when unavailable; it means unlimited simulation capacity, not zero. Sequences -are positive and strictly increasing. Slices do not overlap: each start is at or after the prior -end, so equal boundaries are valid. Receipt time never moves backward. Start precedes end, -availability does not precede end, and receipt does not precede availability. OHLC values satisfy -their usual range relationships. Volume may be fractional but must align to the instrument lot. -Each slice supplies exactly one positive FX rate for every scenario currency, and the -base-currency rate is exactly one. +Every scenario carries `"contract_version": "1"` and these top-level fields: -Financing observations are unique per instrument or currency within a slice, effective no later -than the slice start, and strictly advance the effective time for their key across slices. A recall -has zero available quantity. The latest observation remains active until replaced. The top-level -`financing` object selects `actual_365` or `actual_360`, `simple` or `daily`, `reject` or `zero` -missing-data handling, `reject_order` or `clip_fill` locate behavior, and -`reject_new_shorts` or `close_out` recall behavior. +| Field | Purpose | +| --- | --- | +| `metadata` | Producer and dataset provenance; ignored by execution | +| `run_id` | Stable namespace for generated identities | +| `base_currency` | Aggregate reporting currency | +| `initial_portfolio` | Cash, positions, marks, FX, basis, P&L, and fee state | +| `instruments` | Executable catalog with tick, lot, and quote currency | +| `venue_calendars` | Explicit sessions covering every instrument | +| `risk` | Instrument policies, groups, gross exposure, leverage, and borrow limits | +| `execution` | Compiled model and strict v1 model configuration | +| `financing` | Borrow and cash-rate policies | +| `settlement` | Calendars, lags, and cash/position availability | +| `max_internal_events` | Reducer feedback limit | +| `schedule` | Intents emitted after specified slices | +| `slices` | Synchronized market and lifecycle observations | -The v12 `settlement` object selects `total_cash` or `settled_cash` buying power and -`total_positions` or `settled_positions` availability. Its immutable calendars contain ordered -canonical business dates, and each instrument has exactly one calendar and a lag from zero through -30 business days. A fill updates economic accounting immediately and creates a deterministic -instruction. Pending cash and quantity appear as unsettled attribution until the first slice on or -after the due date. A due instruction named in that slice's `settlement_failures` becomes failed -instead, retains its unsettled balances, and records the supplied reason. +Decimals are canonical strings with at most six fractional digits. Counts and basis points are +JSON integers. Unknown fields, duplicate keys, non-finite values, missing catalog coverage, +misaligned ticks or lots, invalid timestamps, and noncausal schedules are rejected. -Supported corporate actions are exact-ratio `split`, per-unit `cash_dividend`, `stock_dividend`, -`rights`, and `spin_off` records. Distribution records name a destination instrument, entitlement -ratio, basis allocation in basis points, and a fractional policy. `reject` fails on a non-lot -entitlement; `cash_in_lieu` requires an explicit destination-quote-currency price and journals the -delivered quantity, fractional quantity, allocated basis, fractional basis, and cash amount. Action -IDs are unique across the scenario. Actions are applied in canonical ID order before borrow fees -and matching. A split rescales the position, persistent target, and active orders while preserving -basis; it does not rescale unit-based risk limits. Split-adjusted positions and targets are -grandfathered under the existing reduce-only position policy. Split-adjusted orders remain active, -but each fill is bounded by `max_order_quantity`; GTC limit remainders may fill on later slices, -while market IOC remainders are cancelled. A dividend changes the quote-currency cash ledger and -realized dividend P&L, crediting a long and debiting a short. +Each slice has explicit start, end, availability, and receipt instants; complete bars and FX marks; +and optional corporate actions, financing observations, settlement failures, lifecycle events, +quotes, trades, and order-book events. Slices are strictly ordered and cannot overlap. -Version 12 slices also carry `lifecycle_events`. Stable `instrument_id` never changes. An -`identifier_change` updates the current symbol and one named provider mapping with provenance; -`halt` and `resume` control whether new exposure is accepted. `expiration` and `delisting` are -terminal and require either `hold` or an explicit quote-currency `cash_out` price. Halts and -terminal events cancel active orders. Terminal events set persistent target exposure to zero and -cash-out clears the position with exact realized-P&L attribution. +## Stream form -Version 14 slices add `market_events`. A quote records bid/ask prices and displayed quantities; a -trade records price, quantity, and `buy`, `sell`, or `unknown` aggressor side. Every event also -records `event_at`, `available_at`, `received_at`, and a positive `ingest_sequence`. Events are -strictly ordered by availability, receipt, and ingest sequence; economic time cannot follow -availability, and no event may escape its containing slice's time or observability boundary. -Prices and quantities align to the instrument tick and lot. The -[`quote-trade` fixture](../contracts/v16/fixtures/quote-trade.scenario.json) demonstrates passive -fills and has an equivalent bounded JSON Lines replay. +The [stream schema](../contracts/v1/scenario-stream.schema.json) defines three record types: -Version 15 slices add `order_book_events`. Every configured instrument supplies a fresh full -snapshot followed by contiguous absolute `set`, `delete`, and aggressor-classified `trade` updates. -Snapshots contain price-ordered unique bid and ask levels. Crossed states are invalid, while locked -books are accepted. Runtime validation enforces the configured `max_depth_levels`, known levels on -delete, sequence continuity, slice observability, and tick/lot alignment. Marketable orders walk -the visible book; passive limits queue behind displayed same-price depth, with reductions moving -them forward and additions joining behind. The -[`order-book` fixture](../contracts/v16/fixtures/order-book.scenario.json) demonstrates bounded -queue replay and has equivalent JSON Lines and journal artifacts. +1. `scenario_header` contains the static configuration. +2. Each `market_slice` contains one slice and its causally adjacent intents. +3. `scenario_end` declares the final slice count. -For causal next-open execution, an order-changing schedule entry's anchor `received_at` is no later -than the next slice `start_at`. +Every record repeats contract v1 and has a contiguous sequence. The engine validates the complete +stream before creating a journal, then replays it without retaining prior slices or audit events. +Standard input is spooled to a bounded private file so the exact bytes can be validated, hashed, +replayed, and verified again. -## Audit journal +## Strategy intents -The [journal JSON Schema](../contracts/v16/journal.schema.json) validates each JSON Lines record. -Every record contains `contract_version`, `engine_sequence`, deterministic `event_id`, ordered -`causation_ids`, `run_id`, `recorded_at`, `event_type`, and an event-specific `payload`. Causal -references are unique prior event IDs from the same run. The version is repeated on every record -so a journal remains self-describing when it is streamed or split. +Scheduled and external strategies may submit full-catalog target weights or quantities, direct +orders, cancellations, and typed metrics. An intent produced after slice `n` cannot execute inside +that slice. External strategy scenarios use an empty schedule so there is only one decision source. -The first record is `run_started` with `scenario_sha256` and the selected execution model. In v6, -`initial_state` then records the imported portfolio and reconciled valuation, followed by an -initial `valuation`; both precede the first market slice. The CLI hashes the exact batch document -or stream bytes it parses. -`market_slice_received` contains the complete normalized slice. Portfolio requests record their -basis, original weight when applicable, computed quantity, and sizing reference price. Orders use -`eligible_after_slice_sequence`; fills use `slice_sequence`. `fill_clipped` records the proposed -fill and the greatest lot-aligned permitted quantity. Its reason taxonomy version `1` names one of -`max_order_quantity`, `max_long_position`, `max_short_position`, `max_gross_exposure`, -`max_leverage`, `initial_margin`, or `instrument_borrow_availability` and carries a quantity, money, -ratio, or basis-points threshold. -Each order snapshot retains both creation and latest-update event IDs. +## Journal -The journal also records split/dividend/distribution application, lifecycle transitions, -action-driven order adjustments, observed -borrow charges, recalls and close-outs, cash-interest entries, margin calls, liquidation-origin -orders, and restoration. Every valuation contains complete -per-currency cash attribution, signed per-instrument native and base-currency attribution, long, -short, net, and gross exposure, execution and borrow fees, and its initial/maintenance margin -snapshot. Those rows reconcile exactly to the aggregate valuation. +The [journal schema](../contracts/v1/journal.schema.json) defines each append-only record. Every +record carries contract v1, a deterministic event ID, ordered prior causation IDs, the run ID, +recording time, event type, and strict payload. -A successful replay ends with exactly one `run_completed` record containing the same scenario -hash, reconciled valuation, and mutually exclusive order-status counts. A journal without that -terminal record is incomplete. The requested journal path appears only after exclusive successful -finalization; a failed run retains the `.partial` artifact. +A journal begins with `run_started`, `initial_state`, and an initial valuation. It then records the +normalized slices and all strategy, risk, order, execution, financing, settlement, lifecycle, +accounting, and valuation outcomes. Each completed slice emits one closing valuation. Successful +runs end with one `run_completed` record containing the scenario hash, final valuation, and order +counts. -`--durable-artifacts` synchronizes staged contents before publication and containing-directory -metadata after publication and partial cleanup. The filesystem must support hard links plus file -and directory synchronization. Unsupported durability operations fail with `artifact.io` and do -not silently fall back to buffered publication. +The requested path is published only after the terminal record is closed successfully. Failures +retain the `.partial` artifact. `--durable-artifacts` additionally synchronizes file and directory +metadata on supported filesystems. diff --git a/lib/audit.ml b/lib/audit.ml index 6145ce3..36a578d 100644 --- a/lib/audit.ml +++ b/lib/audit.ml @@ -73,13 +73,6 @@ type event = | Settlement_instruction_created of Settlement.instruction | Settlement_completed of Settlement.instruction | Settlement_failed of Settlement.instruction - | Margin_limited of { - order_id : Id.Order.t; - instrument_id : Id.Instrument.t; - requested_quantity : Scalar.Quantity.t; - permitted_quantity : Scalar.Quantity.t; - price : Scalar.Price.t; - } | Fill_clipped of { order_id : Id.Order.t; instrument_id : Id.Instrument.t; @@ -88,16 +81,6 @@ type event = price : Scalar.Price.t; limit : Risk.fill_limit; } - | Borrow_fee_applied of { - instrument_id : Id.Instrument.t; - quote_currency : string; - short_quantity : Scalar.Quantity.t; - reference_price : Scalar.Price.t; - borrow_bps : int; - period_start : Ptime.t; - period_end : Ptime.t; - fee : Scalar.Money.t; - } | Borrow_charge_applied of { observation : Financing.borrow_observation; quote_currency : string; @@ -199,9 +182,7 @@ let event_name = function | Settlement_instruction_created _ -> "settlement_instruction_created" | Settlement_completed _ -> "settlement_completed" | Settlement_failed _ -> "settlement_failed" - | Margin_limited _ -> "margin_limited" | Fill_clipped _ -> "fill_clipped" - | Borrow_fee_applied _ -> "borrow_fee_applied" | Borrow_charge_applied _ -> "borrow_charge_applied" | Borrow_recall_received _ -> "borrow_recall_received" | Cash_interest_applied _ -> "cash_interest_applied" diff --git a/lib/audit.mli b/lib/audit.mli index 07708df..20ba914 100644 --- a/lib/audit.mli +++ b/lib/audit.mli @@ -75,13 +75,6 @@ type event = | Settlement_instruction_created of Settlement.instruction | Settlement_completed of Settlement.instruction | Settlement_failed of Settlement.instruction - | Margin_limited of { - order_id : Id.Order.t; - instrument_id : Id.Instrument.t; - requested_quantity : Scalar.Quantity.t; - permitted_quantity : Scalar.Quantity.t; - price : Scalar.Price.t; - } | Fill_clipped of { order_id : Id.Order.t; instrument_id : Id.Instrument.t; @@ -90,16 +83,6 @@ type event = price : Scalar.Price.t; limit : Risk.fill_limit; } - | Borrow_fee_applied of { - instrument_id : Id.Instrument.t; - quote_currency : string; - short_quantity : Scalar.Quantity.t; - reference_price : Scalar.Price.t; - borrow_bps : int; - period_start : Ptime.t; - period_end : Ptime.t; - fee : Scalar.Money.t; - } | Borrow_charge_applied of { observation : Financing.borrow_observation; quote_currency : string; diff --git a/lib/codec.ml b/lib/codec.ml index fb5f935..c399627 100644 --- a/lib/codec.ml +++ b/lib/codec.ml @@ -440,7 +440,7 @@ let order_book_event_to_yojson event = string (Market_event.aggressor_side_to_string aggressor_side) ); ]) -let versioned_market_slice_to_yojson ~contract_version market_slice = +let market_slice_to_yojson market_slice = `Assoc [ ("slice_sequence", int64 market_slice.Market_slice.slice_sequence); @@ -454,108 +454,33 @@ let versioned_market_slice_to_yojson ~contract_version market_slice = `List (List.map corporate_action_to_yojson market_slice.corporate_actions) ); + ( "borrow_observations", + `List + (List.map borrow_observation_to_yojson + market_slice.Market_slice.borrow_observations) ); + ( "cash_rate_observations", + `List + (List.map cash_rate_observation_to_yojson + market_slice.Market_slice.cash_rate_observations) ); + ( "settlement_failures", + `List + (List.map settlement_failure_to_yojson + market_slice.Market_slice.settlement_failures) ); + ( "lifecycle_events", + `List + (List.map lifecycle_event_to_yojson + market_slice.Market_slice.lifecycle_events) ); + ( "market_events", + `List + (List.map market_event_to_yojson + market_slice.Market_slice.market_events) ); + ( "order_book_events", + `List + (List.map order_book_event_to_yojson + market_slice.Market_slice.order_book_events) ); ] - |> function - | `Assoc fields - when List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] - -> - let settlement = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] then - [ - ( "settlement_failures", - `List - (List.map settlement_failure_to_yojson - market_slice.Market_slice.settlement_failures) ); - ] - else [] - in - let lifecycle = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12" ] then - [ - ( "lifecycle_events", - `List - (List.map lifecycle_event_to_yojson - market_slice.Market_slice.lifecycle_events) ); - ] - else [] - in - let market_events = - if List.mem contract_version [ "16"; "15"; "14" ] then - [ - ( "market_events", - `List - (List.map market_event_to_yojson - market_slice.Market_slice.market_events) ); - ] - else [] - in - let order_book_events = - if List.mem contract_version [ "16"; "15" ] then - [ - ( "order_book_events", - `List - (List.map order_book_event_to_yojson - market_slice.Market_slice.order_book_events) ); - ] - else [] - in - `Assoc - (fields - @ [ - ( "borrow_observations", - `List - (List.map borrow_observation_to_yojson - market_slice.Market_slice.borrow_observations) ); - ( "cash_rate_observations", - `List - (List.map cash_rate_observation_to_yojson - market_slice.Market_slice.cash_rate_observations) ); - ] - @ settlement @ lifecycle @ market_events @ order_book_events) - | json -> json - -let market_slice_to_yojson market_slice = - versioned_market_slice_to_yojson ~contract_version:"9" market_slice - -let market_slice_to_yojson_v10 market_slice = - versioned_market_slice_to_yojson ~contract_version:"10" market_slice - -let market_slice_to_yojson_v11 market_slice = - versioned_market_slice_to_yojson ~contract_version:"11" market_slice - -let market_slice_to_yojson_v12 market_slice = - versioned_market_slice_to_yojson ~contract_version:"12" market_slice - -let market_slice_to_yojson_v13 market_slice = - versioned_market_slice_to_yojson ~contract_version:"13" market_slice - -let market_slice_to_yojson_v14 market_slice = - versioned_market_slice_to_yojson ~contract_version:"14" market_slice - -let market_slice_to_yojson_v15 market_slice = - versioned_market_slice_to_yojson ~contract_version:"15" market_slice - -let market_slice_to_yojson_v16 market_slice = - versioned_market_slice_to_yojson ~contract_version:"16" market_slice let request_fields request = - let kind, limit_price = - match request.Order.kind with - | Order.Market -> ("market", `Null) - | Order.Limit value -> ("limit", price value) - | Order.Stop value -> ("stop", price value) - | Order.Stop_limit { limit_price; _ } -> ("stop_limit", price limit_price) - in - [ - ("instrument_id", instrument_id request.instrument_id); - ("side", string (Order.side_to_string request.side)); - ("quantity", quantity request.quantity); - ("order_kind", string kind); - ("limit_price", limit_price); - ("origin", string (Order.origin_to_string request.origin)); - ] - -let request_fields_v8 request = let kind, trigger_price, limit_price = match request.Order.kind with | Order.Market -> ("market", `Null, `Null) @@ -591,27 +516,6 @@ let request_fields_v8 request = ] let order_to_yojson order = - let rejection_reason = - match order.Order.status with - | Order.Rejected reason -> string reason - | _ -> `Null - in - `Assoc - ((("order_id", order_id order.id) :: request_fields order.request) - @ [ - ("created_event_id", string (Id.Event.to_string order.created_event_id)); - ("updated_event_id", string (Id.Event.to_string order.updated_event_id)); - ("created_sequence", int64 order.created_sequence); - ("created_at", timestamp order.created_at); - ( "eligible_after_slice_sequence", - int64 order.eligible_after_slice_sequence ); - ("filled_quantity", quantity order.filled_quantity); - ("filled_notional", money order.filled_notional); - ("status", string (Order.status_to_string order.status)); - ("rejection_reason", rejection_reason); - ]) - -let order_to_yojson_v8 order = let rejection_reason = match order.Order.status with | Order.Rejected reason -> string reason @@ -624,7 +528,7 @@ let order_to_yojson_v8 order = | Some Order.Dormant | None -> (`Null, `Null) in `Assoc - ((("order_id", order_id order.id) :: request_fields_v8 order.request) + ((("order_id", order_id order.id) :: request_fields order.request) @ [ ("created_event_id", string (Id.Event.to_string order.created_event_id)); ("updated_event_id", string (Id.Event.to_string order.updated_event_id)); @@ -640,12 +544,15 @@ let order_to_yojson_v8 order = ("rejection_reason", rejection_reason); ]) -let versioned_order_to_yojson ~contract_version order = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8" ] - then order_to_yojson_v8 order - else order_to_yojson order +let calculated_fee_component_to_yojson component = + `Assoc + [ + ("name", string component.Fee_schedule.name); + ("kind", string component.kind); + ("currency", string component.currency); + ("amount", money component.amount); + ("quote_amount", money component.quote_amount); + ] let fill_to_yojson fill = `Assoc @@ -659,33 +566,13 @@ let fill_to_yojson fill = ("price", price fill.price); ("notional", money fill.notional); ("fee", money fill.fee); + ( "fee_components", + `List (List.map calculated_fee_component_to_yojson fill.fee_components) + ); ("executed_at", timestamp fill.executed_at); ("slice_sequence", int64 fill.slice_sequence); ] -let calculated_fee_component_to_yojson component = - `Assoc - [ - ("name", string component.Fee_schedule.name); - ("kind", string component.kind); - ("currency", string component.currency); - ("amount", money component.amount); - ("quote_amount", money component.quote_amount); - ] - -let fill_to_yojson_v9 fill = - match fill_to_yojson fill with - | `Assoc fields -> - `Assoc - (fields - @ [ - ( "fee_components", - `List - (List.map calculated_fee_component_to_yojson - fill.Fill.fee_components) ); - ]) - | _ -> assert false - let initial_position_to_yojson (position : Initial_portfolio.position) = `Assoc [ @@ -726,12 +613,26 @@ let initial_portfolio_to_yojson (portfolio : Initial_portfolio.t) = ("fx_rates", `List fx_rates); ] +let execution_fee_component_attribution_to_yojson component = + `Assoc + [ + ("name", string component.Account.name); + ("kind", string component.kind); + ("currency", string component.currency); + ("amount", money component.amount); + ("quote_currency", string component.quote_currency); + ("quote_amount", money component.quote_amount); + ("base_amount", money component.base_amount); + ] + let position_attribution_to_yojson position = `Assoc [ ("instrument_id", instrument_id position.Account.instrument_id); ("quote_currency", string position.quote_currency); ("quantity", quantity position.quantity); + ("settled_quantity", quantity position.settled_quantity); + ("unsettled_quantity", quantity position.unsettled_quantity); ("mark", price position.mark); ("fx_rate", price position.fx_rate); ("market_value", money position.market_value); @@ -746,82 +647,32 @@ let position_attribution_to_yojson position = ("base_dividend_pnl", money position.base_dividend_pnl); ("execution_fees", money position.execution_fees); ("base_execution_fees", money position.base_execution_fees); + ( "execution_fee_components", + `List + (List.map execution_fee_component_attribution_to_yojson + position.execution_fee_components) ); ("borrow_fees", money position.borrow_fees); ("base_borrow_fees", money position.base_borrow_fees); ("total_fees", money position.total_fees); ("base_total_fees", money position.base_total_fees); ] -let execution_fee_component_attribution_to_yojson component = - `Assoc - [ - ("name", string component.Account.name); - ("kind", string component.kind); - ("currency", string component.currency); - ("amount", money component.amount); - ("quote_currency", string component.quote_currency); - ("quote_amount", money component.quote_amount); - ("base_amount", money component.base_amount); - ] - -let position_attribution_to_yojson_v9 position = - match position_attribution_to_yojson position with - | `Assoc fields -> - `Assoc - (fields - @ [ - ( "execution_fee_components", - `List - (List.map execution_fee_component_attribution_to_yojson - position.Account.execution_fee_components) ); - ]) - | _ -> assert false - -let position_attribution_to_yojson_v11 position = - match position_attribution_to_yojson_v9 position with - | `Assoc fields -> - `Assoc - (fields - @ [ - ("settled_quantity", quantity position.Account.settled_quantity); - ("unsettled_quantity", quantity position.unsettled_quantity); - ]) - | _ -> assert false - let cash_attribution_to_yojson cash = `Assoc [ ("currency", string cash.Account.currency); ("amount", money cash.amount); + ("settled_amount", money cash.settled_amount); + ("unsettled_amount", money cash.unsettled_amount); ("fx_rate", price cash.fx_rate); ("base_value", money cash.base_value); + ("base_settled_value", money cash.base_settled_value); + ("base_unsettled_value", money cash.base_unsettled_value); + ("interest", money cash.interest); + ("base_interest", money cash.base_interest); ] -let cash_attribution_to_yojson_v10 cash = - match cash_attribution_to_yojson cash with - | `Assoc fields -> - `Assoc - (fields - @ [ - ("interest", money cash.Account.interest); - ("base_interest", money cash.base_interest); - ]) - | _ -> assert false - -let cash_attribution_to_yojson_v11 cash = - match cash_attribution_to_yojson_v10 cash with - | `Assoc fields -> - `Assoc - (fields - @ [ - ("settled_amount", money cash.Account.settled_amount); - ("unsettled_amount", money cash.unsettled_amount); - ("base_settled_value", money cash.base_settled_value); - ("base_unsettled_value", money cash.base_unsettled_value); - ]) - | _ -> assert false - -let account_valuation_to_yojson ?(contract_version = "8") valuation = +let account_valuation_to_yojson valuation = `Assoc [ ("base_currency", string valuation.Account.base_currency); @@ -836,59 +687,20 @@ let account_valuation_to_yojson ?(contract_version = "8") valuation = ("equity", money valuation.equity); ("dividend_pnl", money valuation.dividend_pnl); ("execution_fees", money valuation.execution_fees); + ( "execution_fee_components", + `List + (List.map execution_fee_component_attribution_to_yojson + valuation.Account.execution_fee_components) ); ("borrow_fees", money valuation.borrow_fees); ("total_fees", money valuation.total_fees); + ("cash_interest", money valuation.cash_interest); + ("settled_cash", money valuation.settled_cash); + ("unsettled_cash", money valuation.unsettled_cash); ( "cash_balances", - `List - (List.map - (if - List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] - then cash_attribution_to_yojson_v11 - else if String.equal contract_version "10" then - cash_attribution_to_yojson_v10 - else cash_attribution_to_yojson) - valuation.cash_balances) ); + `List (List.map cash_attribution_to_yojson valuation.cash_balances) ); ( "positions", - `List - (List.map - (if - List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] - then position_attribution_to_yojson_v11 - else if - String.equal contract_version "9" - || String.equal contract_version "10" - then position_attribution_to_yojson_v9 - else position_attribution_to_yojson) - valuation.positions) ); + `List (List.map position_attribution_to_yojson valuation.positions) ); ] - |> function - | `Assoc fields - when List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9" ] -> - let financing = - if - List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] - then [ ("cash_interest", money valuation.Account.cash_interest) ] - else [] - in - let settlement = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] then - [ - ("settled_cash", money valuation.Account.settled_cash); - ("unsettled_cash", money valuation.unsettled_cash); - ] - else [] - in - `Assoc - (fields - @ [ - ( "execution_fee_components", - `List - (List.map execution_fee_component_attribution_to_yojson - valuation.Account.execution_fee_components) ); - ] - @ financing @ settlement) - | json -> json let margin_to_yojson margin = `Assoc @@ -912,27 +724,18 @@ let group_exposure_to_yojson (exposure : Risk.group_exposure) = Option.fold ~none:`Null ~some:weight exposure.concentration ); ] -let valuation_to_yojson ~contract_version valuation = - match - account_valuation_to_yojson ~contract_version valuation.Audit.account - with +let valuation_to_yojson valuation = + match account_valuation_to_yojson valuation.Audit.account with | `Assoc fields -> - let fields = fields @ [ ("margin", margin_to_yojson valuation.margin) ] in - let fields = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8" ] - then - fields - @ [ - ( "group_exposures", - `List - (List.map group_exposure_to_yojson - valuation.margin.Risk.group_exposures) ); - ] - else fields - in - `Assoc fields + `Assoc + (fields + @ [ + ("margin", margin_to_yojson valuation.margin); + ( "group_exposures", + `List + (List.map group_exposure_to_yojson + valuation.margin.Risk.group_exposures) ); + ]) | _ -> assert false let order_counts_to_yojson counts = @@ -1014,7 +817,7 @@ let metric_to_yojson metric = | Some aggregation -> [ ("aggregation", string (Metric.aggregation_to_string aggregation)) ]) -let payload_to_yojson ~contract_version = function +let payload_to_yojson = function | Audit.Run_started { scenario_sha256; execution_model } -> `Assoc [ @@ -1025,10 +828,10 @@ let payload_to_yojson ~contract_version = function `Assoc [ ("portfolio", initial_portfolio_to_yojson portfolio); - ("valuation", valuation_to_yojson ~contract_version valuation); + ("valuation", valuation_to_yojson valuation); ] | Audit.Market_slice_received market_slice -> - versioned_market_slice_to_yojson ~contract_version market_slice + market_slice_to_yojson market_slice | Audit.Target_portfolio_requested { basis; targets } -> `Assoc [ @@ -1036,13 +839,12 @@ let payload_to_yojson ~contract_version = function ("targets", `List (List.map requested_target_to_yojson targets)); ] | Audit.Order_accepted order | Audit.Order_rejected order -> - versioned_order_to_yojson ~contract_version order - | Audit.Order_triggered order -> - versioned_order_to_yojson ~contract_version order + order_to_yojson order + | Audit.Order_triggered order -> order_to_yojson order | Audit.Order_cancelled { order; reason } -> `Assoc [ - ("order", versioned_order_to_yojson ~contract_version order); + ("order", order_to_yojson order); ("reason", string (Audit.cancellation_reason_to_string reason)); ] | Audit.Split_applied { action; previous_quantity; adjusted_quantity } -> @@ -1082,7 +884,7 @@ let payload_to_yojson ~contract_version = function | Audit.Order_adjusted { order; action_id } -> `Assoc [ - ("order", versioned_order_to_yojson ~contract_version order); + ("order", order_to_yojson order); ("action_id", string (Id.Corporate_action.to_string action_id)); ] | Audit.Execution_price_selected @@ -1097,32 +899,11 @@ let payload_to_yojson ~contract_version = function ("impact_adjustment", money attribution.impact_adjustment); ("final_price", price attribution.final_price); ] - | Audit.Fill_applied fill -> - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9" ] - then fill_to_yojson_v9 fill - else fill_to_yojson fill + | Audit.Fill_applied fill -> fill_to_yojson fill | Audit.Settlement_instruction_created instruction | Audit.Settlement_completed instruction | Audit.Settlement_failed instruction -> settlement_instruction_to_yojson instruction - | Audit.Margin_limited - { - order_id = id; - instrument_id = instrument; - requested_quantity; - permitted_quantity; - price = fill_price; - } -> - `Assoc - [ - ("order_id", order_id id); - ("instrument_id", instrument_id instrument); - ("requested_quantity", quantity requested_quantity); - ("permitted_quantity", quantity permitted_quantity); - ("price", price fill_price); - ] | Audit.Fill_clipped { order_id = id; @@ -1148,28 +929,6 @@ let payload_to_yojson ~contract_version = function ("permitted_quantity", quantity permitted_quantity); ("price", price fill_price); ] - | Audit.Borrow_fee_applied - { - instrument_id = instrument; - quote_currency; - short_quantity; - reference_price; - borrow_bps; - period_start; - period_end; - fee; - } -> - `Assoc - [ - ("instrument_id", instrument_id instrument); - ("quote_currency", string quote_currency); - ("short_quantity", quantity short_quantity); - ("reference_price", price reference_price); - ("borrow_bps", `Int borrow_bps); - ("period_start", timestamp period_start); - ("period_end", timestamp period_end); - ("fee", money fee); - ] | Audit.Borrow_charge_applied { observation; @@ -1227,26 +986,17 @@ let payload_to_yojson ~contract_version = function ("closing_balance", money closing_balance); ] | Audit.Margin_call_triggered valuation | Audit.Margin_restored valuation -> - valuation_to_yojson ~contract_version valuation + valuation_to_yojson valuation | Audit.Intent_rejected reason -> `Assoc [ ("reason", string reason) ] - | Audit.Metric_emitted metric -> - if String.equal contract_version "16" then metric_to_yojson metric - else - let value = - match metric.Metric.value with - | Metric.String value -> value - | Metric.Numeric value -> Metric.numeric_to_string value - | Metric.Boolean value -> string_of_bool value - in - `Assoc [ ("name", string metric.name); ("value", string value) ] - | Audit.Valuation valuation -> valuation_to_yojson ~contract_version valuation + | Audit.Metric_emitted metric -> metric_to_yojson metric + | Audit.Valuation valuation -> valuation_to_yojson valuation | Audit.Run_completed { scenario_sha256; execution_model; valuation; order_counts } -> `Assoc [ ("scenario_sha256", string scenario_sha256); ("execution_model", string execution_model); - ("valuation", valuation_to_yojson ~contract_version valuation); + ("valuation", valuation_to_yojson valuation); ("order_counts", order_counts_to_yojson order_counts); ] @@ -1264,9 +1014,7 @@ let audit_to_yojson audit = ("run_id", string (Id.Run.to_string audit.run_id)); ("recorded_at", timestamp audit.recorded_at); ("event_type", string (Audit.event_name audit.event)); - ( "payload", - payload_to_yojson ~contract_version:audit.contract_version audit.event - ); + ("payload", payload_to_yojson audit.event); ] let audit_to_string audit = Yojson.Safe.to_string (audit_to_yojson audit) diff --git a/lib/codec.mli b/lib/codec.mli index ed39a34..86ff0a9 100644 --- a/lib/codec.mli +++ b/lib/codec.mli @@ -4,21 +4,9 @@ val ptime_to_string : Ptime.t -> string val ptime_of_string : string -> (Ptime.t, string) result val bar_to_yojson : Bar.t -> Yojson.Safe.t val market_slice_to_yojson : Market_slice.t -> Yojson.Safe.t -val market_slice_to_yojson_v10 : Market_slice.t -> Yojson.Safe.t -val market_slice_to_yojson_v11 : Market_slice.t -> Yojson.Safe.t -val market_slice_to_yojson_v12 : Market_slice.t -> Yojson.Safe.t -val market_slice_to_yojson_v13 : Market_slice.t -> Yojson.Safe.t -val market_slice_to_yojson_v14 : Market_slice.t -> Yojson.Safe.t -val market_slice_to_yojson_v15 : Market_slice.t -> Yojson.Safe.t -val market_slice_to_yojson_v16 : Market_slice.t -> Yojson.Safe.t val order_to_yojson : Order.t -> Yojson.Safe.t -val order_to_yojson_v8 : Order.t -> Yojson.Safe.t val fill_to_yojson : Fill.t -> Yojson.Safe.t -val fill_to_yojson_v9 : Fill.t -> Yojson.Safe.t val initial_portfolio_to_yojson : Initial_portfolio.t -> Yojson.Safe.t - -val account_valuation_to_yojson : - ?contract_version:string -> Account.valuation -> Yojson.Safe.t - +val account_valuation_to_yojson : Account.valuation -> Yojson.Safe.t val audit_to_yojson : Audit.t -> Yojson.Safe.t val audit_to_string : Audit.t -> string diff --git a/lib/contract.ml b/lib/contract.ml index d8682a4..06d6f5f 100644 --- a/lib/contract.ml +++ b/lib/contract.ml @@ -1,28 +1,7 @@ -let version = "16" -let previous_version = "15" -let legacy_journal_version = "3" - -let supported_versions = - [ - version; - previous_version; - "14"; - "13"; - "12"; - "11"; - "10"; - "9"; - "8"; - "7"; - "6"; - "5"; - "4"; - legacy_journal_version; - ] - +let version = "1" +let supported_versions = [ version ] let is_supported version = List.mem version supported_versions -let strategy_protocol_version = "14" -let previous_strategy_protocol_version = "13" +let strategy_protocol_version = "1" let engine_version = "1.0.0" let strings values = `List (List.map (fun value -> `String value) values) @@ -36,22 +15,7 @@ let capabilities_to_yojson () = ("journal_formats", strings [ "jsonl" ]); ("execution_models", strings Execution_model.supported); ("execution_model_contracts", Execution_model.capabilities_to_yojson ()); - ( "strategy_protocol_versions", - strings - [ - strategy_protocol_version; - previous_strategy_protocol_version; - "12"; - "11"; - "10"; - "9"; - "8"; - "7"; - "6"; - "5"; - "4"; - "3"; - ] ); + ("strategy_protocol_versions", strings [ strategy_protocol_version ]); ("resource_limits", Resource_limits.to_yojson ()); ] diff --git a/lib/contract.mli b/lib/contract.mli index 967a91a..7e18e56 100644 --- a/lib/contract.mli +++ b/lib/contract.mli @@ -1,12 +1,9 @@ (** Version and capability identifiers for the process/file boundary. *) val version : string -val previous_version : string -val legacy_journal_version : string val supported_versions : string list val is_supported : string -> bool val strategy_protocol_version : string -val previous_strategy_protocol_version : string val engine_version : string val capabilities_to_yojson : unit -> Yojson.Safe.t val capabilities_to_string : unit -> string diff --git a/lib/engine.ml b/lib/engine.ml index c88493e..cbc4adf 100644 --- a/lib/engine.ml +++ b/lib/engine.ml @@ -6,13 +6,13 @@ type config = { venue_calendars : Venue_calendar.t list; execution_model : Execution_model.t; execution : Execution.t; - financing : Financing.policy option; - settlement : Settlement.policy option; + financing : Financing.policy; + settlement : Settlement.policy; max_internal_events : int; } -let make_config ~venue_calendars ~contract_version ~risk ~execution_model - ~execution ~financing ~settlement ~max_internal_events = +let config ~contract_version ~risk ~venue_calendars ~execution_model ~execution + ~financing ~settlement ~max_internal_events = if not (Contract.is_supported contract_version) then Error "engine contract version is unsupported" else if @@ -50,33 +50,6 @@ let make_config ~venue_calendars ~contract_version ~risk ~execution_model max_internal_events; } -let config ~contract_version ~risk ~execution_model ~execution - ~max_internal_events = - make_config ~venue_calendars:[] ~contract_version ~risk ~execution_model - ~execution ~financing:None ~max_internal_events ~settlement:None - -let config_v8 ~contract_version ~risk ~venue_calendars ~execution_model - ~execution ~max_internal_events = - make_config ~venue_calendars ~contract_version ~risk ~execution_model - ~execution ~financing:None ~max_internal_events ~settlement:None - -let config_v10 ~contract_version ~risk ~venue_calendars ~execution_model - ~execution ~financing ~max_internal_events = - make_config ~venue_calendars ~contract_version ~risk ~execution_model - ~execution ~financing:(Some financing) ~max_internal_events ~settlement:None - -let config_v11 ~contract_version ~risk ~venue_calendars ~execution_model - ~execution ~financing ~settlement ~max_internal_events = - make_config ~venue_calendars ~contract_version ~risk ~execution_model - ~execution ~financing:(Some financing) ~settlement:(Some settlement) - ~max_internal_events - -let config_v12 = config_v11 -let config_v13 = config_v12 -let config_v14 = config_v13 -let config_v15 = config_v14 -let config_v16 = config_v15 - let valid_sha256 value = String.length value = 64 && String.for_all @@ -108,7 +81,7 @@ module Interactive = struct latest_borrow : Financing.borrow_observation Id.Instrument.Map.t; latest_cash_rates : Financing.cash_rate_observation Currency_map.t; settlement_instructions : Settlement.instruction list; - initial_portfolio : Initial_portfolio.t option; + initial_portfolio : Initial_portfolio.t; applied_action_ids : Id.Corporate_action.Set.t; lifecycle : Instrument_lifecycle.t; desired_targets : desired_targets option; @@ -194,34 +167,7 @@ module Interactive = struct (Risk.instruments config.risk) |> List.sort_uniq String.compare - let create ~run_id ~scenario_sha256 ~config ~initial_cash = - if not (valid_sha256 scenario_sha256) then - Error "scenario SHA-256 must contain 64 lowercase hexadecimal characters" - else - let expected_currencies = expected_currencies config in - let supplied_currencies = - List.map fst initial_cash |> List.sort_uniq String.compare - in - if supplied_currencies <> expected_currencies then - Error "initial cash must contain every configured currency exactly once" - else - match - Account.create - ~base_currency:(Risk.base_currency config.risk) - ~initial_cash - with - | Error _ as error -> error - | Ok account -> - let base_rate = - Scalar.Price.of_decimal_string "1" |> Result.get_ok - in - create_state ~run_id ~scenario_sha256 ~config ~account - ~latest_marks:Id.Instrument.Map.empty - ~latest_fx_rates:[ (Risk.base_currency config.risk, base_rate) ] - ~initial_portfolio:None - - let create_with_portfolio ~run_id ~scenario_sha256 ~config ~initial_portfolio - = + let create ~run_id ~scenario_sha256 ~config ~initial_portfolio = if not (valid_sha256 scenario_sha256) then Error "scenario SHA-256 must contain 64 lowercase hexadecimal characters" else if @@ -250,8 +196,7 @@ module Interactive = struct in let* () = Risk.check_initial config.risk valuation in create_state ~run_id ~scenario_sha256 ~config ~account ~latest_marks - ~latest_fx_rates:initial_portfolio.fx_rates - ~initial_portfolio:(Some initial_portfolio) + ~latest_fx_rates:initial_portfolio.fx_rates ~initial_portfolio let account state = state.account let oms state = state.oms @@ -309,21 +254,16 @@ module Interactive = struct }) in let reduction = with_causes reduction [ event_id ] in - match reduction.state.initial_portfolio with - | None -> Ok reduction - | Some portfolio -> - let* account = value reduction.state in - let* margin = - Risk.margin_snapshot reduction.state.config.risk account - in - let valuation = Audit.{ account; margin } in - let* reduction, initial_event_id = - emit_with_id reduction - (Audit.Initial_state { portfolio; valuation }) - in - emit - (with_causes reduction [ initial_event_id ]) - (Audit.Valuation valuation) + let portfolio = reduction.state.initial_portfolio in + let* account = value reduction.state in + let* margin = Risk.margin_snapshot reduction.state.config.risk account in + let valuation = Audit.{ account; margin } in + let* reduction, initial_event_id = + emit_with_id reduction (Audit.Initial_state { portfolio; valuation }) + in + emit + (with_causes reduction [ initial_event_id ]) + (Audit.Valuation valuation) let enqueue reduction items = { reduction with pending = Pending_queue.enqueue reduction.pending items } @@ -432,13 +372,13 @@ module Interactive = struct Id.Instrument.Map.bindings reduction.state.latest_marks in let* () = + let policy = reduction.state.config.financing in match - ( reduction.state.config.financing, - request.Order.side, + ( request.Order.side, Account.position_quantity reduction.state.account request.instrument_id ) with - | Some policy, Order.Sell, position + | Order.Sell, position when policy.Financing.locate_policy = Financing.Reject_order && not (Scalar.Quantity.is_positive position) -> let available = @@ -530,7 +470,7 @@ module Interactive = struct let submit_recall_order reduction market_slice instrument quantity = let* request = - Order.request_v8 ~instrument_id:instrument.Instrument.id ~side:Order.Buy + Order.request ~instrument_id:instrument.Instrument.id ~side:Order.Buy ~quantity ~kind:Order.Market ~time_in_force:Order.Ioc ~origin:Order.Borrow_recall in @@ -1004,58 +944,6 @@ module Interactive = struct if Z.fits_int64 fee then Ok (Scalar.Money.of_micros (Z.to_int64 fee)) else Error "short borrow fee overflow" - let apply_legacy_borrow_fees reduction market_slice = - let span = - Ptime.diff market_slice.Market_slice.end_at market_slice.start_at - in - List.fold_left - (fun result instrument -> - let* reduction = result in - let quantity = - Account.position_quantity reduction.state.account - instrument.Instrument.id - in - if - (not (Scalar.Quantity.is_negative quantity)) - || Risk.short_borrow_bps reduction.state.config.risk = 0 - then Ok reduction - else - let* short_quantity = Scalar.Quantity.absolute quantity in - let* bar = - match Market_slice.bar market_slice instrument.id with - | Some value -> Ok value - | None -> Error "short position has no market slice bar" - in - let* notional = Scalar.Money.notional bar.open_price short_quantity in - let borrow_bps = Risk.short_borrow_bps reduction.state.config.risk in - let* fee = borrow_fee ~notional ~bps:borrow_bps span in - if Scalar.Money.equal fee Scalar.Money.zero then Ok reduction - else - let* account = - Account.apply_borrow_fee reduction.state.account - ~instrument_id:instrument.id - ~quote_currency:instrument.quote_currency ~fee - in - let reduction = - { reduction with state = { reduction.state with account } } - in - let causes = Option.to_list reduction.slice_event_id in - emit - (with_causes reduction causes) - (Audit.Borrow_fee_applied - { - instrument_id = instrument.id; - quote_currency = instrument.quote_currency; - short_quantity; - reference_price = bar.open_price; - borrow_bps; - period_start = market_slice.start_at; - period_end = market_slice.end_at; - fee; - })) - (Ok reduction) - (configured_instruments reduction.state) - let apply_observed_borrow_fees reduction market_slice policy = let span = Ptime.diff market_slice.Market_slice.end_at market_slice.start_at @@ -1242,85 +1130,73 @@ module Interactive = struct (configured_instruments reduction.state) let apply_financing reduction market_slice = - match reduction.state.config.financing with - | None -> apply_legacy_borrow_fees reduction market_slice - | Some policy -> - let* reduction = process_borrow_recalls reduction market_slice policy in - let* reduction = - apply_observed_borrow_fees reduction market_slice policy - in - apply_cash_interest reduction market_slice policy + let policy = reduction.state.config.financing in + let* reduction = process_borrow_recalls reduction market_slice policy in + let* reduction = apply_observed_borrow_fees reduction market_slice policy in + apply_cash_interest reduction market_slice policy let process_settlements reduction (market_slice : Market_slice.t) = - match reduction.state.config.settlement with - | None -> Ok reduction - | Some _ -> - List.fold_left - (fun result (instruction : Settlement.instruction) -> - let* reduction = result in - match instruction.status with - | Settlement.Settled _ | Settlement.Failed _ -> Ok reduction - | Settlement.Pending -> - if not (Settlement.is_due instruction market_slice.start_at) - then Ok reduction - else - let failure = - List.find_opt - (fun (failure : Settlement.failure) -> - String.equal failure.instruction_id - instruction.instruction_id) - market_slice.Market_slice.settlement_failures - in - let* instruction, account, event = - match failure with - | Some failure -> - let* instruction = - Settlement.fail instruction - ~failed_at:market_slice.start_at - ~reason:failure.reason - in - Ok - ( instruction, - reduction.state.account, - Audit.Settlement_failed instruction ) - | None -> - let* account = - Account.apply_settlement reduction.state.account - instruction - in - let* instruction = - Settlement.settle instruction - ~settled_at:market_slice.start_at - in - Ok - ( instruction, - account, - Audit.Settlement_completed instruction ) - in - let settlement_instructions = - List.map - (fun (current : Settlement.instruction) -> - if - String.equal current.instruction_id - instruction.instruction_id - then instruction - else current) - reduction.state.settlement_instructions - in - emit - (with_causes - { - reduction with - state = - { - reduction.state with - account; - settlement_instructions; - }; - } - (Option.to_list reduction.slice_event_id)) - event) - (Ok reduction) reduction.state.settlement_instructions + List.fold_left + (fun result (instruction : Settlement.instruction) -> + let* reduction = result in + match instruction.status with + | Settlement.Settled _ | Settlement.Failed _ -> Ok reduction + | Settlement.Pending -> + if not (Settlement.is_due instruction market_slice.start_at) then + Ok reduction + else + let failure = + List.find_opt + (fun (failure : Settlement.failure) -> + String.equal failure.instruction_id + instruction.instruction_id) + market_slice.Market_slice.settlement_failures + in + let* instruction, account, event = + match failure with + | Some failure -> + let* instruction = + Settlement.fail instruction + ~failed_at:market_slice.start_at ~reason:failure.reason + in + Ok + ( instruction, + reduction.state.account, + Audit.Settlement_failed instruction ) + | None -> + let* account = + Account.apply_settlement reduction.state.account + instruction + in + let* instruction = + Settlement.settle instruction + ~settled_at:market_slice.start_at + in + Ok + ( instruction, + account, + Audit.Settlement_completed instruction ) + in + let settlement_instructions = + List.map + (fun (current : Settlement.instruction) -> + if + String.equal current.instruction_id + instruction.instruction_id + then instruction + else current) + reduction.state.settlement_instructions + in + emit + (with_causes + { + reduction with + state = + { reduction.state with account; settlement_instructions }; + } + (Option.to_list reduction.slice_event_id)) + event) + (Ok reduction) reduction.state.settlement_instructions let validate_target_ids state ids = let expected = @@ -1637,18 +1513,15 @@ module Interactive = struct market_slice.cash_rate_observations in let settlement_failures_valid = - match state.config.settlement with - | None -> market_slice.settlement_failures = [] - | Some _ -> - List.for_all - (fun (failure : Settlement.failure) -> - List.exists - (fun (instruction : Settlement.instruction) -> - String.equal instruction.instruction_id failure.instruction_id - && instruction.status = Settlement.Pending - && Settlement.is_due instruction market_slice.start_at) - state.settlement_instructions) - market_slice.settlement_failures + List.for_all + (fun (failure : Settlement.failure) -> + List.exists + (fun (instruction : Settlement.instruction) -> + String.equal instruction.instruction_id failure.instruction_id + && instruction.status = Settlement.Pending + && Settlement.is_due instruction market_slice.start_at) + state.settlement_instructions) + market_slice.settlement_failures in if List.length ids <> List.length actual || actual <> expected then Error "market slice must contain each configured instrument exactly once" @@ -1702,12 +1575,8 @@ module Interactive = struct let create_execution_fill execution ~id ~order_id ~instrument_id ~quote_currency ~side ~quantity ~price ~fee ~fee_components ~executed_at ~slice_sequence = - if Execution.fee_schedules execution = [] then - Fill.create ~id ~order_id ~instrument_id ~quote_currency ~side ~quantity - ~price ~fee ~executed_at ~slice_sequence - else - Fill.create_v9 ~id ~order_id ~instrument_id ~quote_currency ~side - ~quantity ~price ~fee ~fee_components ~executed_at ~slice_sequence + Fill.create ~id ~order_id ~instrument_id ~quote_currency ~side ~quantity + ~price ~fee ~fee_components ~executed_at ~slice_sequence let slice_open_marks market_slice = List.map @@ -1738,11 +1607,7 @@ module Interactive = struct ~executed_at:proposed.executed_at ~slice_sequence:market_slice.Market_slice.slice_sequence in - let* account = - match state.config.settlement with - | None -> Account.apply_fill state.account fill - | Some _ -> Account.apply_unsettled_fill state.account fill - in + let* account = Account.apply_unsettled_fill state.account fill in let after_position = Account.position_quantity account instrument.id in let* after = Account.value account ~instruments ~marks @@ -1755,8 +1620,9 @@ module Interactive = struct | Ok (fee_components, fee, account, after_position, after) -> ( let checked = let* () = - match (state.config.settlement, order.Order.request.side) with - | Some settlement, Order.Buy -> ( + let settlement = state.config.settlement in + match order.Order.request.side with + | Order.Buy -> ( let available = match settlement.Settlement.cash_buying_power with | Settlement.Total_cash -> @@ -1787,7 +1653,7 @@ module Interactive = struct (Risk.Settlement_cash_buying_power (instrument.quote_currency, available))) else Ok ()) - | Some settlement, Order.Sell + | Order.Sell when settlement.position_availability = Settlement.Settled_positions && Scalar.Quantity.is_positive before_position -> @@ -1805,7 +1671,7 @@ module Interactive = struct (Risk.Settlement_position_availability (instrument.id, available))) else Ok () - | None, _ | Some _, _ -> Ok () + | Order.Sell -> Ok () in let* () = Risk.check_post_fill_for state.config.risk @@ -1828,9 +1694,9 @@ module Interactive = struct | None -> Error "fill instrument has no risk policy" in let* borrow_constraint = - match (state.config.financing, order.Order.request.side) with - | Some policy, Order.Sell - when not (Scalar.Quantity.is_positive before_position) -> + let policy = state.config.financing in + match order.Order.request.side with + | Order.Sell when not (Scalar.Quantity.is_positive before_position) -> let available = match Id.Instrument.Map.find_opt instrument.id state.latest_borrow @@ -1856,7 +1722,7 @@ module Interactive = struct match policy.Financing.locate_policy with | Financing.Reject_order -> true | Financing.Clip_fill -> false )) - | _ -> Ok None + | Order.Sell | Order.Buy -> Ok None in let quantity_limit = let risk_limit = @@ -1963,12 +1829,8 @@ module Interactive = struct Error "newly allocated fill ID was duplicated" | Ok (oms, Oms.Applied order) -> ( match - match reduction.state.config.settlement with - | None -> - Account.apply_fill reduction.state.account fill - | Some _ -> - Account.apply_unsettled_fill - reduction.state.account fill + Account.apply_unsettled_fill reduction.state.account + fill with | Error _ as error -> error | Ok account -> ( @@ -1980,26 +1842,23 @@ module Interactive = struct | Error _ as error -> error | Ok (reduction, event_id) -> let* reduction = - match reduction.state.config.settlement with - | None -> Ok reduction - | Some policy -> - let* instruction = - Settlement.instruction policy fill - in - let state = - { - reduction.state with - settlement_instructions = - reduction.state - .settlement_instructions - @ [ instruction ]; - } - in - emit - (with_causes { reduction with state } - [ event_id ]) - (Audit.Settlement_instruction_created - instruction) + let* instruction = + Settlement.instruction + reduction.state.config.settlement fill + in + let state = + { + reduction.state with + settlement_instructions = + reduction.state.settlement_instructions + @ [ instruction ]; + } + in + emit + (with_causes { reduction with state } + [ event_id ]) + (Audit.Settlement_instruction_created + instruction) in let* fill_pending = notification reduction @@ -2055,30 +1914,16 @@ module Interactive = struct match limit with | None -> Ok reduction | Some limit -> - if - String.equal reduction.state.config.contract_version - Contract.legacy_journal_version - then - emit reduction - (Audit.Margin_limited - { - order_id = order.id; - instrument_id = order.request.instrument_id; - requested_quantity = proposed.quantity; - permitted_quantity; - price = proposed.price; - }) - else - emit reduction - (Audit.Fill_clipped - { - order_id = order.id; - instrument_id = order.request.instrument_id; - proposed_quantity = proposed.quantity; - permitted_quantity; - price = proposed.price; - limit; - }) + emit reduction + (Audit.Fill_clipped + { + order_id = order.id; + instrument_id = order.request.instrument_id; + proposed_quantity = proposed.quantity; + permitted_quantity; + price = proposed.price; + limit; + }) in if Scalar.Quantity.is_zero permitted_quantity then Ok (reduction, permitted_quantity) @@ -2096,12 +1941,8 @@ module Interactive = struct | None -> Error "immediate order disappeared during matching" | Some order -> ( let reason = - if - (not - (String.equal reduction.state.config.contract_version "8")) - && Order.is_market order - then Audit.Market_ioc - else if Order.is_fok order then Audit.Fill_or_kill + if Order.is_fok order then Audit.Fill_or_kill + else if Order.is_market order then Audit.Market_ioc else Audit.Immediate_or_cancel in let result = @@ -2222,7 +2063,8 @@ module Interactive = struct Error "target order limit cannot cover one instrument lot" | Ok quantity -> Order.request ~instrument_id ~side ~quantity - ~kind:Order.Market ~origin:Order.Target_rebalance + ~kind:Order.Market ~time_in_force:Order.Ioc + ~origin:Order.Target_rebalance |> Result.map Option.some)) let reconcile_targets reduction = @@ -2296,7 +2138,8 @@ module Interactive = struct in let* request = Order.request ~instrument_id:instrument.id ~side ~quantity - ~kind:Order.Market ~origin:Order.Margin_liquidation + ~kind:Order.Market ~time_in_force:Order.Ioc + ~origin:Order.Margin_liquidation in submit_order (with_causes reduction causes) request) (Ok reduction) @@ -2635,14 +2478,9 @@ module Make (Strategy_impl : Strategy.S) = struct type t = { engine : Interactive.t; strategy_state : Strategy_impl.state } - let create ~run_id ~scenario_sha256 ~config ~initial_cash ~strategy_state = - Interactive.create ~run_id ~scenario_sha256 ~config ~initial_cash - |> Result.map (fun engine -> { engine; strategy_state }) - - let create_with_portfolio ~run_id ~scenario_sha256 ~config ~initial_portfolio - ~strategy_state = - Interactive.create_with_portfolio ~run_id ~scenario_sha256 ~config - ~initial_portfolio + let create ~run_id ~scenario_sha256 ~config ~initial_portfolio ~strategy_state + = + Interactive.create ~run_id ~scenario_sha256 ~config ~initial_portfolio |> Result.map (fun engine -> { engine; strategy_state }) let account state = Interactive.account state.engine diff --git a/lib/engine.mli b/lib/engine.mli index dc47f1f..4014293 100644 --- a/lib/engine.mli +++ b/lib/engine.mli @@ -3,88 +3,6 @@ type config val config : - contract_version:string -> - risk:Risk.t -> - execution_model:Execution_model.t -> - execution:Execution.t -> - max_internal_events:int -> - (config, string) result - -val config_v8 : - contract_version:string -> - risk:Risk.t -> - venue_calendars:Venue_calendar.t list -> - execution_model:Execution_model.t -> - execution:Execution.t -> - max_internal_events:int -> - (config, string) result - -val config_v10 : - contract_version:string -> - risk:Risk.t -> - venue_calendars:Venue_calendar.t list -> - execution_model:Execution_model.t -> - execution:Execution.t -> - financing:Financing.policy -> - max_internal_events:int -> - (config, string) result - -val config_v11 : - contract_version:string -> - risk:Risk.t -> - venue_calendars:Venue_calendar.t list -> - execution_model:Execution_model.t -> - execution:Execution.t -> - financing:Financing.policy -> - settlement:Settlement.policy -> - max_internal_events:int -> - (config, string) result - -val config_v12 : - contract_version:string -> - risk:Risk.t -> - venue_calendars:Venue_calendar.t list -> - execution_model:Execution_model.t -> - execution:Execution.t -> - financing:Financing.policy -> - settlement:Settlement.policy -> - max_internal_events:int -> - (config, string) result - -val config_v13 : - contract_version:string -> - risk:Risk.t -> - venue_calendars:Venue_calendar.t list -> - execution_model:Execution_model.t -> - execution:Execution.t -> - financing:Financing.policy -> - settlement:Settlement.policy -> - max_internal_events:int -> - (config, string) result - -val config_v14 : - contract_version:string -> - risk:Risk.t -> - venue_calendars:Venue_calendar.t list -> - execution_model:Execution_model.t -> - execution:Execution.t -> - financing:Financing.policy -> - settlement:Settlement.policy -> - max_internal_events:int -> - (config, string) result - -val config_v15 : - contract_version:string -> - risk:Risk.t -> - venue_calendars:Venue_calendar.t list -> - execution_model:Execution_model.t -> - execution:Execution.t -> - financing:Financing.policy -> - settlement:Settlement.policy -> - max_internal_events:int -> - (config, string) result - -val config_v16 : contract_version:string -> risk:Risk.t -> venue_calendars:Venue_calendar.t list -> @@ -100,13 +18,6 @@ module Interactive : sig type progress val create : - run_id:Id.Run.t -> - scenario_sha256:string -> - config:config -> - initial_cash:(string * Scalar.Money.t) list -> - (t, string) result - - val create_with_portfolio : run_id:Id.Run.t -> scenario_sha256:string -> config:config -> @@ -127,14 +38,6 @@ module Make (Strategy_impl : Strategy.S) : sig type t val create : - run_id:Id.Run.t -> - scenario_sha256:string -> - config:config -> - initial_cash:(string * Scalar.Money.t) list -> - strategy_state:Strategy_impl.state -> - (t, string) result - - val create_with_portfolio : run_id:Id.Run.t -> scenario_sha256:string -> config:config -> diff --git a/lib/execution.ml b/lib/execution.ml index 4e60910..49c5cdf 100644 --- a/lib/execution.ml +++ b/lib/execution.ml @@ -1,7 +1,3 @@ -type fee_configuration = - | Legacy of { fixed_fee : Scalar.Money.t; fee_bps : int } - | Schedules of Fee_schedule.t Id.Instrument.Map.t - type missing_volume_policy = Reject_missing_volume | Zero_impact type cost_model = { @@ -12,7 +8,7 @@ type cost_model = { type t = { participation_bps : int; - fee_configuration : fee_configuration; + fee_schedules : Fee_schedule.t Id.Instrument.Map.t; cost_model : cost_model option; book_depth_limit : int option; } @@ -55,23 +51,7 @@ let ( let* ) result function_ = let cursor next = Cursor (fun oms -> next ~oms) -let create ~participation_bps ~fixed_fee ~fee_bps = - if participation_bps < 0 || participation_bps > 10_000 then - Error "participation basis points must be between 0 and 10000" - else if Scalar.Money.compare fixed_fee Scalar.Money.zero < 0 then - Error "fixed fee must be nonnegative" - else if fee_bps < 0 || fee_bps > 10_000 then - Error "fee basis points must be between 0 and 10000" - else - Ok - { - participation_bps; - fee_configuration = Legacy { fixed_fee; fee_bps }; - cost_model = None; - book_depth_limit = None; - } - -let create_v2 ~participation_bps ~fee_schedules = +let create ~participation_bps ~fee_schedules = if participation_bps < 0 || participation_bps > 10_000 then Error "participation basis points must be between 0 and 10000" else @@ -91,7 +71,7 @@ let create_v2 ~participation_bps ~fee_schedules = (fun schedules -> { participation_bps; - fee_configuration = Schedules schedules; + fee_schedules = schedules; cost_model = None; book_depth_limit = None; }) @@ -112,7 +92,7 @@ let create_conservative ~participation_bps ~fee_schedules ~half_spread_bps Some { half_spread_bps; impact_coefficient_bps; missing_volume_policy }; }) - (create_v2 ~participation_bps ~fee_schedules) + (create ~participation_bps ~fee_schedules) let create_order_book ~participation_bps ~fee_schedules ~max_depth_levels = if max_depth_levels <= 0 || max_depth_levels > 1024 then @@ -120,45 +100,24 @@ let create_order_book ~participation_bps ~fee_schedules ~max_depth_levels = else Result.map (fun state -> { state with book_depth_limit = Some max_depth_levels }) - (create_v2 ~participation_bps ~fee_schedules) + (create ~participation_bps ~fee_schedules) let participation_bps state = state.participation_bps let book_depth_limit state = state.book_depth_limit -let fixed_fee state = - match state.fee_configuration with - | Legacy { fixed_fee; _ } -> fixed_fee - | Schedules _ -> Scalar.Money.zero - -let fee_bps state = - match state.fee_configuration with - | Legacy { fee_bps; _ } -> fee_bps - | Schedules _ -> 0 - let fee_schedules state = - match state.fee_configuration with - | Legacy _ -> [] - | Schedules schedules -> Id.Instrument.Map.bindings schedules |> List.map snd + Id.Instrument.Map.bindings state.fee_schedules |> List.map snd let cost_model state = state.cost_model let calculate_fee state ~instrument ~notional ~quantity ~liquidity ~fx_rates = - match state.fee_configuration with - | Legacy { fixed_fee; fee_bps } -> - let ( let* ) result function_ = - match result with - | Ok value -> function_ value - | Error _ as error -> error - in - let* fee = Scalar.Money.fee ~fixed:fixed_fee ~bps:fee_bps ~notional in - Ok ([], fee) - | Schedules schedules -> ( - match Id.Instrument.Map.find_opt instrument.Instrument.id schedules with - | None -> Error "execution instrument has no configured fee schedule" - | Some schedule -> - Fee_schedule.calculate schedule - ~quote_currency:instrument.quote_currency ~notional ~quantity - ~liquidity ~fx_rates) + match + Id.Instrument.Map.find_opt instrument.Instrument.id state.fee_schedules + with + | None -> Error "execution instrument has no configured fee schedule" + | Some schedule -> + Fee_schedule.calculate schedule ~quote_currency:instrument.quote_currency + ~notional ~quantity ~liquidity ~fx_rates type limit_fill_policy = Optimistic_touch | Next_open_only | Adverse_touch diff --git a/lib/execution.mli b/lib/execution.mli index da67d1c..70aeed3 100644 --- a/lib/execution.mli +++ b/lib/execution.mli @@ -44,12 +44,6 @@ val cursor : (oms:Oms.t -> (step, string) result) -> cursor (** Build an immutable cursor from one matching-step function. *) val create : - participation_bps:int -> - fixed_fee:Scalar.Money.t -> - fee_bps:int -> - (t, string) result - -val create_v2 : participation_bps:int -> fee_schedules:Fee_schedule.t list -> (t, string) result @@ -70,8 +64,6 @@ val create_order_book : val participation_bps : t -> int val book_depth_limit : t -> int option -val fixed_fee : t -> Scalar.Money.t -val fee_bps : t -> int val fee_schedules : t -> Fee_schedule.t list val cost_model : t -> cost_model option @@ -141,8 +133,8 @@ val fold_slice : (** Fold executable orders in liquidation-first, then sell-before-buy/FIFO order. The callback returns the quantity it actually applied; only that quantity consumes the shared per-instrument slice capacity. Returns an error - when a dormant stop triggers because this compatibility helper has no - callback through which to persist trigger state. *) + when a dormant stop triggers because the callback cannot persist trigger + state. *) val match_slice : t -> diff --git a/lib/execution_model.ml b/lib/execution_model.ml index 64c1712..c5ed8ba 100644 --- a/lib/execution_model.ml +++ b/lib/execution_model.ml @@ -13,10 +13,8 @@ type t = (module S) type configuration_contract = { version : string; - previous_versions : string list; scenario_contract_versions : string list; required_fields : string list; - legacy_required_fields : string list; supported_order_types : string list; data_requirements : string list; limits : Yojson.Safe.t; @@ -63,28 +61,9 @@ let supported = List.map name builtins let completed_bar_v1_contract = { - version = "2"; - previous_versions = [ "1" ]; - scenario_contract_versions = - [ - "16"; - "15"; - "14"; - "13"; - "12"; - "11"; - "10"; - "9"; - "8"; - "7"; - "6"; - "5"; - "4"; - "3"; - ]; + version = "1"; + scenario_contract_versions = [ "1" ]; required_fields = [ "version"; "participation_bps"; "fee_schedules" ]; - legacy_required_fields = - [ "version"; "participation_bps"; "fixed_fee"; "fee_bps" ]; supported_order_types = [ "market"; "limit"; "stop"; "stop_limit" ]; data_requirements = [ "completed_ohlcv_bars" ]; limits = @@ -92,17 +71,13 @@ let completed_bar_v1_contract = [ ( "participation_bps", `Assoc [ ("minimum", `Int 0); ("maximum", `Int 10_000) ] ); - ("fee_bps", `Assoc [ ("minimum", `Int 0); ("maximum", `Int 10_000) ]); - ( "fixed_fee", - `Assoc [ ("minimum", `String "0"); ("unit", `String "money") ] ); ]; } let conservative_contract = { version = "1"; - previous_versions = []; - scenario_contract_versions = [ "16"; "15"; "14"; "13" ]; + scenario_contract_versions = [ "1" ]; required_fields = [ "version"; @@ -111,7 +86,6 @@ let conservative_contract = "spread_model"; "impact_model"; ]; - legacy_required_fields = []; supported_order_types = [ "market"; "limit"; "stop"; "stop_limit" ]; data_requirements = [ "completed_ohlcv_bars"; "bar_volume_for_linear_impact" ]; @@ -130,10 +104,8 @@ let conservative_contract = let quote_trade_contract = { version = "1"; - previous_versions = []; - scenario_contract_versions = [ "16"; "15"; "14" ]; + scenario_contract_versions = [ "1" ]; required_fields = [ "version"; "participation_bps"; "fee_schedules" ]; - legacy_required_fields = []; supported_order_types = [ "market"; "limit"; "stop"; "stop_limit" ]; data_requirements = [ @@ -152,11 +124,9 @@ let quote_trade_contract = let order_book_contract = { version = "1"; - previous_versions = []; - scenario_contract_versions = [ "16"; "15" ]; + scenario_contract_versions = [ "1" ]; required_fields = [ "version"; "participation_bps"; "fee_schedules"; "max_depth_levels" ]; - legacy_required_fields = []; supported_order_types = [ "market"; "limit"; "stop"; "stop_limit" ]; data_requirements = [ @@ -190,13 +160,10 @@ let configuration_contract model = let supports_configuration model version = let contract = configuration_contract model in String.equal contract.version version - || List.mem version contract.previous_versions let required_fields model version = let contract = configuration_contract model in if String.equal version contract.version then Ok contract.required_fields - else if List.mem version contract.previous_versions then - Ok contract.legacy_required_fields else Error (Printf.sprintf @@ -216,18 +183,13 @@ let capabilities_to_yojson () = `Assoc [ ("name", `String (name model)); - ( "configuration_versions", - strings (contract.version :: contract.previous_versions) ); + ("configuration_versions", strings [ contract.version ]); ( "scenario_contract_versions", strings contract.scenario_contract_versions ); ("required_fields", strings contract.required_fields); ( "configuration_required_fields", - `Assoc - ((contract.version, strings contract.required_fields) - :: List.map - (fun version -> - (version, strings contract.legacy_required_fields)) - contract.previous_versions) ); + `Assoc [ (contract.version, strings contract.required_fields) ] + ); ("supported_order_types", strings contract.supported_order_types); ("data_requirements", strings contract.data_requirements); ("limits", contract.limits); diff --git a/lib/execution_model.mli b/lib/execution_model.mli index 25968aa..f8641be 100644 --- a/lib/execution_model.mli +++ b/lib/execution_model.mli @@ -21,10 +21,8 @@ type t type configuration_contract = private { version : string; - previous_versions : string list; scenario_contract_versions : string list; required_fields : string list; - legacy_required_fields : string list; supported_order_types : string list; data_requirements : string list; limits : Yojson.Safe.t; diff --git a/lib/external_replay.ml b/lib/external_replay.ml index 1c446ae..de770f5 100644 --- a/lib/external_replay.ml +++ b/lib/external_replay.ml @@ -62,7 +62,6 @@ let initialization_of_scenario ~scenario_sha256 (scenario : Scenario.t) = metadata = scenario.metadata; run_id = scenario.run_id; base_currency = scenario.base_currency; - initial_cash = scenario.initial_cash; initial_portfolio = scenario.initial_portfolio; instruments = scenario.instruments; venue_calendars = scenario.venue_calendars; @@ -82,7 +81,6 @@ let initialization_of_header ~scenario_sha256 (header : Scenario.stream_header) metadata = header.metadata; run_id = header.run_id; base_currency = header.base_currency; - initial_cash = header.initial_cash; initial_portfolio = header.initial_portfolio; instruments = header.instruments; venue_calendars = header.venue_calendars; @@ -95,47 +93,14 @@ let initialization_of_header ~scenario_sha256 (header : Scenario.stream_header) let create_runner ~contract_version ~run_id ~scenario_sha256 ~risk ~venue_calendars ~execution_model ~execution ~financing ~settlement - ~max_internal_events ~initial_cash ~initial_portfolio = + ~max_internal_events ~initial_portfolio = let* config = - (match (financing, settlement) with - | None, None -> - Engine.config_v8 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~max_internal_events - | Some financing, None -> - Engine.config_v10 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~max_internal_events - | Some financing, Some settlement -> - if List.mem contract_version [ "16"; "15" ] then - Engine.config_v16 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else if String.equal contract_version "14" then - Engine.config_v14 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else if String.equal contract_version "13" then - Engine.config_v13 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else if String.equal contract_version "12" then - Engine.config_v12 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else - Engine.config_v11 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - | None, Some _ -> Error "settlement requires financing configuration") + Engine.config ~contract_version ~risk ~venue_calendars ~execution_model + ~execution ~financing ~settlement ~max_internal_events |> reducer_result in - match initial_portfolio with - | None -> - Runner.create ~run_id ~scenario_sha256 ~config ~initial_cash - |> reducer_result - | Some initial_portfolio -> - Runner.create_with_portfolio ~run_id ~scenario_sha256 ~config - ~initial_portfolio - |> reducer_result + Runner.create ~run_id ~scenario_sha256 ~config ~initial_portfolio + |> reducer_result let append_events journal events = match journal with @@ -214,7 +179,6 @@ let run ?(durability = Artifact_writer.Buffered) ~env ~scenario_sha256 ~execution_model:scenario.execution_model ~execution:scenario.execution ~financing:scenario.financing ~settlement:scenario.settlement ~max_internal_events:scenario.max_internal_events - ~initial_cash:scenario.initial_cash ~initial_portfolio:scenario.initial_portfolio in let* journal, transcript = @@ -271,7 +235,6 @@ let validate_stream_pass ~scenario_sha256 channel = ~execution_model:header.execution_model ~execution:header.execution ~financing:header.financing ~settlement:header.settlement ~max_internal_events:header.max_internal_events - ~initial_cash:header.initial_cash ~initial_portfolio:header.initial_portfolio in Ok (runner, initialization_of_header ~scenario_sha256 header, 0L)) @@ -302,7 +265,6 @@ let replay_stream_pass ~scenario_sha256 ~journal ~session channel = ~execution_model:header.execution_model ~execution:header.execution ~financing:header.financing ~settlement:header.settlement ~max_internal_events:header.max_internal_events - ~initial_cash:header.initial_cash ~initial_portfolio:header.initial_portfolio in Ok { runner; journal = Some journal; audit_count = 0L }) diff --git a/lib/fill.ml b/lib/fill.ml index 2af8476..d315356 100644 --- a/lib/fill.ml +++ b/lib/fill.ml @@ -13,8 +13,8 @@ type t = { slice_sequence : int64; } -let create_internal ~allow_rebate ~fee_components ~id ~order_id ~instrument_id - ~quote_currency ~side ~quantity ~price ~fee ~executed_at ~slice_sequence = +let create ~id ~order_id ~instrument_id ~quote_currency ~side ~quantity ~price + ~fee ~fee_components ~executed_at ~slice_sequence = if not (Scalar.Quantity.is_positive quantity) then Error "fill quantity must be positive" else if String.length quote_currency = 0 then @@ -27,8 +27,6 @@ let create_internal ~allow_rebate ~fee_components ~id ~order_id ~instrument_id code >= 0x21 && code <> 0x7f) quote_currency) then Error "fill quote currency must not contain whitespace" - else if (not allow_rebate) && Scalar.Money.compare fee Scalar.Money.zero < 0 - then Error "fill fee must be nonnegative" else if Int64.compare slice_sequence 0L <= 0 then Error "fill slice sequence must be positive" else @@ -68,18 +66,6 @@ let create_internal ~allow_rebate ~fee_components ~id ~order_id ~instrument_id slice_sequence; } -let create ~id ~order_id ~instrument_id ~quote_currency ~side ~quantity ~price - ~fee ~executed_at ~slice_sequence = - create_internal ~allow_rebate:false ~fee_components:[] ~id ~order_id - ~instrument_id ~quote_currency ~side ~quantity ~price ~fee ~executed_at - ~slice_sequence - -let create_v9 ~id ~order_id ~instrument_id ~quote_currency ~side ~quantity - ~price ~fee ~fee_components ~executed_at ~slice_sequence = - create_internal ~allow_rebate:true ~fee_components ~id ~order_id - ~instrument_id ~quote_currency ~side ~quantity ~price ~fee ~executed_at - ~slice_sequence - let equal left right = Id.Fill.equal left.id right.id && Id.Order.equal left.order_id right.order_id diff --git a/lib/fill.mli b/lib/fill.mli index e9d6d9b..67e6aee 100644 --- a/lib/fill.mli +++ b/lib/fill.mli @@ -16,19 +16,6 @@ type t = private { } val create : - id:Id.Fill.t -> - order_id:Id.Order.t -> - instrument_id:Id.Instrument.t -> - quote_currency:string -> - side:Order.side -> - quantity:Scalar.Quantity.t -> - price:Scalar.Price.t -> - fee:Scalar.Money.t -> - executed_at:Ptime.t -> - slice_sequence:int64 -> - (t, string) result - -val create_v9 : id:Id.Fill.t -> order_id:Id.Order.t -> instrument_id:Id.Instrument.t -> diff --git a/lib/financing.ml b/lib/financing.ml index 2c44f33..c86fba2 100644 --- a/lib/financing.ml +++ b/lib/financing.ml @@ -39,11 +39,6 @@ let policy ~day_count ~compounding ~borrow_missing_data ~cash_missing_data recall_policy; } -let legacy_policy = - policy ~day_count:Actual_365 ~compounding:Simple ~borrow_missing_data:Zero - ~cash_missing_data:Zero ~locate_policy:Clip_fill - ~recall_policy:Reject_new_shorts - let valid_currency value = String.length value > 0 && String.for_all diff --git a/lib/financing.mli b/lib/financing.mli index 878072a..acb9c60 100644 --- a/lib/financing.mli +++ b/lib/financing.mli @@ -39,8 +39,6 @@ val policy : recall_policy:recall_policy -> policy -val legacy_policy : policy - val borrow_observation : instrument_id:Id.Instrument.t -> effective_at:Ptime.t -> diff --git a/lib/journal.ml b/lib/journal.ml index 2f07698..f7946aa 100644 --- a/lib/journal.ml +++ b/lib/journal.ml @@ -9,8 +9,7 @@ let audit_context event = Some (Id.Order.to_string order.Order.id) | Order_cancelled { order; _ } -> Some (Id.Order.to_string order.id) | Fill_applied fill -> Some (Id.Order.to_string fill.Fill.order_id) - | Margin_limited { order_id; _ } | Fill_clipped { order_id; _ } -> - Some (Id.Order.to_string order_id) + | Fill_clipped { order_id; _ } -> Some (Id.Order.to_string order_id) | _ -> None in (event_id, order_id, causation_ids) diff --git a/lib/market_slice.ml b/lib/market_slice.ml index f3dcd27..062b1e7 100644 --- a/lib/market_slice.ml +++ b/lib/market_slice.ml @@ -33,10 +33,9 @@ let fx_mark ~currency ~rate = let compare_bar left right = Id.Instrument.compare left.Bar.instrument_id right.Bar.instrument_id -let create_v15 ~slice_sequence ~start_at ~end_at ~available_at ~received_at - ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations ~settlement_failures ~lifecycle_events - ~market_events ~order_book_events = +let create ~slice_sequence ~start_at ~end_at ~available_at ~received_at ~bars + ~fx_rates ~corporate_actions ~borrow_observations ~cash_rate_observations + ~settlement_failures ~lifecycle_events ~market_events ~order_book_events = if Int64.compare slice_sequence 0L <= 0 then Error "market slice sequence must be positive" else if Ptime.compare start_at end_at >= 0 then @@ -186,46 +185,6 @@ let create_v15 ~slice_sequence ~start_at ~end_at ~available_at ~received_at settlement_failures; } -let create_v16 = create_v15 - -let create_v14 ~slice_sequence ~start_at ~end_at ~available_at ~received_at - ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations ~settlement_failures ~lifecycle_events - ~market_events = - create_v15 ~slice_sequence ~start_at ~end_at ~available_at ~received_at ~bars - ~fx_rates ~corporate_actions ~borrow_observations ~cash_rate_observations - ~settlement_failures ~lifecycle_events ~market_events ~order_book_events:[] - -let create_v12 ~slice_sequence ~start_at ~end_at ~available_at ~received_at - ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations ~settlement_failures ~lifecycle_events = - create_v15 ~slice_sequence ~start_at ~end_at ~available_at ~received_at ~bars - ~fx_rates ~corporate_actions ~borrow_observations ~cash_rate_observations - ~settlement_failures ~lifecycle_events ~market_events:[] - ~order_book_events:[] - -let create_v13 = create_v12 - -let create_v11 ~slice_sequence ~start_at ~end_at ~available_at ~received_at - ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations ~settlement_failures = - create_v12 ~slice_sequence ~start_at ~end_at ~available_at ~received_at ~bars - ~fx_rates ~corporate_actions ~borrow_observations ~cash_rate_observations - ~settlement_failures ~lifecycle_events:[] - -let create_v10 ~slice_sequence ~start_at ~end_at ~available_at ~received_at - ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations = - create_v11 ~slice_sequence ~start_at ~end_at ~available_at ~received_at ~bars - ~fx_rates ~corporate_actions ~borrow_observations ~cash_rate_observations - ~settlement_failures:[] - -let create ~slice_sequence ~start_at ~end_at ~available_at ~received_at ~bars - ~fx_rates ~corporate_actions = - create_v10 ~slice_sequence ~start_at ~end_at ~available_at ~received_at ~bars - ~fx_rates ~corporate_actions ~borrow_observations:[] - ~cash_rate_observations:[] - let bar state instrument_id = List.find_opt (fun bar -> Id.Instrument.equal bar.Bar.instrument_id instrument_id) diff --git a/lib/market_slice.mli b/lib/market_slice.mli index 7182f96..8f4eee7 100644 --- a/lib/market_slice.mli +++ b/lib/market_slice.mli @@ -23,107 +23,6 @@ type t = private { } val create : - slice_sequence:int64 -> - start_at:Ptime.t -> - end_at:Ptime.t -> - available_at:Ptime.t -> - received_at:Ptime.t -> - bars:Bar.t list -> - fx_rates:fx_mark list -> - corporate_actions:Corporate_action.t list -> - (t, string) result - -val create_v10 : - slice_sequence:int64 -> - start_at:Ptime.t -> - end_at:Ptime.t -> - available_at:Ptime.t -> - received_at:Ptime.t -> - bars:Bar.t list -> - fx_rates:fx_mark list -> - corporate_actions:Corporate_action.t list -> - borrow_observations:Financing.borrow_observation list -> - cash_rate_observations:Financing.cash_rate_observation list -> - (t, string) result - -val create_v11 : - slice_sequence:int64 -> - start_at:Ptime.t -> - end_at:Ptime.t -> - available_at:Ptime.t -> - received_at:Ptime.t -> - bars:Bar.t list -> - fx_rates:fx_mark list -> - corporate_actions:Corporate_action.t list -> - borrow_observations:Financing.borrow_observation list -> - cash_rate_observations:Financing.cash_rate_observation list -> - settlement_failures:Settlement.failure list -> - (t, string) result - -val create_v12 : - slice_sequence:int64 -> - start_at:Ptime.t -> - end_at:Ptime.t -> - available_at:Ptime.t -> - received_at:Ptime.t -> - bars:Bar.t list -> - fx_rates:fx_mark list -> - corporate_actions:Corporate_action.t list -> - borrow_observations:Financing.borrow_observation list -> - cash_rate_observations:Financing.cash_rate_observation list -> - settlement_failures:Settlement.failure list -> - lifecycle_events:Instrument_lifecycle.event list -> - (t, string) result - -val create_v13 : - slice_sequence:int64 -> - start_at:Ptime.t -> - end_at:Ptime.t -> - available_at:Ptime.t -> - received_at:Ptime.t -> - bars:Bar.t list -> - fx_rates:fx_mark list -> - corporate_actions:Corporate_action.t list -> - borrow_observations:Financing.borrow_observation list -> - cash_rate_observations:Financing.cash_rate_observation list -> - settlement_failures:Settlement.failure list -> - lifecycle_events:Instrument_lifecycle.event list -> - (t, string) result - -val create_v14 : - slice_sequence:int64 -> - start_at:Ptime.t -> - end_at:Ptime.t -> - available_at:Ptime.t -> - received_at:Ptime.t -> - bars:Bar.t list -> - fx_rates:fx_mark list -> - corporate_actions:Corporate_action.t list -> - borrow_observations:Financing.borrow_observation list -> - cash_rate_observations:Financing.cash_rate_observation list -> - settlement_failures:Settlement.failure list -> - lifecycle_events:Instrument_lifecycle.event list -> - market_events:Market_event.t list -> - (t, string) result - -val create_v15 : - slice_sequence:int64 -> - start_at:Ptime.t -> - end_at:Ptime.t -> - available_at:Ptime.t -> - received_at:Ptime.t -> - bars:Bar.t list -> - fx_rates:fx_mark list -> - corporate_actions:Corporate_action.t list -> - borrow_observations:Financing.borrow_observation list -> - cash_rate_observations:Financing.cash_rate_observation list -> - settlement_failures:Settlement.failure list -> - lifecycle_events:Instrument_lifecycle.event list -> - market_events:Market_event.t list -> - order_book_events:Order_book_event.t list -> - (t, string) result - -val create_v16 : slice_sequence:int64 -> start_at:Ptime.t -> end_at:Ptime.t -> diff --git a/lib/order.ml b/lib/order.ml index 8301f1e..6698210 100644 --- a/lib/order.ml +++ b/lib/order.ml @@ -55,14 +55,14 @@ type t = { status : status; } -let compatibility_time_in_force = function Market -> Ioc | _ -> Gtc +let default_time_in_force = function Market -> Ioc | _ -> Gtc let valid_stop_limit side trigger_price limit_price = match side with | Buy -> Scalar.Price.compare limit_price trigger_price >= 0 | Sell -> Scalar.Price.compare limit_price trigger_price <= 0 -let request_v8 ~instrument_id ~side ~quantity ~kind ~time_in_force ~origin = +let request ~instrument_id ~side ~quantity ~kind ~time_in_force ~origin = if not (Scalar.Quantity.is_positive quantity) then Error "order quantity must be positive" else @@ -74,11 +74,6 @@ let request_v8 ~instrument_id ~side ~quantity ~kind ~time_in_force ~origin = prices require limit <= trigger" | _ -> Ok { instrument_id; side; quantity; kind; time_in_force; origin } -let request ~instrument_id ~side ~quantity ~kind ~origin = - request_v8 ~instrument_id ~side ~quantity ~kind - ~time_in_force:(compatibility_time_in_force kind) - ~origin - let make ~id ~created_event_id ~sequence ~created_at ~eligible_after_slice_sequence ~request ~status = if Int64.compare sequence 0L < 0 then diff --git a/lib/order.mli b/lib/order.mli index 482409b..5f6bf0f 100644 --- a/lib/order.mli +++ b/lib/order.mli @@ -54,19 +54,9 @@ type t = private { status : status; } -val compatibility_time_in_force : kind -> time_in_force -(** Preserve the pre-v8 mapping: market orders are IOC and all other kinds are - GTC. *) +val default_time_in_force : kind -> time_in_force val request : - instrument_id:Id.Instrument.t -> - side:side -> - quantity:Scalar.Quantity.t -> - kind:kind -> - origin:origin -> - (request, string) result - -val request_v8 : instrument_id:Id.Instrument.t -> side:side -> quantity:Scalar.Quantity.t -> diff --git a/lib/replay.ml b/lib/replay.ml index aa9c7bb..cfdd9ec 100644 --- a/lib/replay.ml +++ b/lib/replay.ml @@ -70,35 +70,8 @@ let add_audit_count count events = let engine_config ~contract_version ~risk ~venue_calendars ~execution_model ~execution ~financing ~settlement ~max_internal_events = - match (financing, settlement) with - | None, None -> - Engine.config_v8 ~contract_version ~risk ~venue_calendars ~execution_model - ~execution ~max_internal_events - | Some financing, None -> - Engine.config_v10 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~max_internal_events - | Some financing, Some settlement -> - if List.mem contract_version [ "16"; "15" ] then - Engine.config_v16 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else if String.equal contract_version "14" then - Engine.config_v14 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else if String.equal contract_version "13" then - Engine.config_v13 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else if String.equal contract_version "12" then - Engine.config_v12 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - else - Engine.config_v11 ~contract_version ~risk ~venue_calendars - ~execution_model ~execution ~financing ~settlement - ~max_internal_events - | None, Some _ -> Error "settlement requires financing configuration" + Engine.config ~contract_version ~risk ~venue_calendars ~execution_model + ~execution ~financing ~settlement ~max_internal_events let run ~scenario_sha256 ?journal_path ?(durability = Artifact_writer.Buffered) scenario = @@ -114,13 +87,8 @@ let run ~scenario_sha256 ?journal_path ?(durability = Artifact_writer.Buffered) |> reducer_result in let* initial = - (match scenario.initial_portfolio with - | None -> - Runner.create ~run_id:scenario.run_id ~scenario_sha256 ~config - ~initial_cash:scenario.initial_cash ~strategy_state - | Some initial_portfolio -> - Runner.create_with_portfolio ~run_id:scenario.run_id ~scenario_sha256 - ~config ~initial_portfolio ~strategy_state) + Runner.create ~run_id:scenario.run_id ~scenario_sha256 ~config + ~initial_portfolio:scenario.initial_portfolio ~strategy_state |> reducer_result in let journal_result = @@ -197,15 +165,8 @@ let run_stream_pass ~scenario_sha256 ~journal channel = | Error _ as error -> error | Ok config -> ( match - (match header.initial_portfolio with - | None -> - Runner.create ~run_id:header.run_id ~scenario_sha256 - ~config ~initial_cash:header.initial_cash - ~strategy_state - | Some initial_portfolio -> - Runner.create_with_portfolio ~run_id:header.run_id - ~scenario_sha256 ~config ~initial_portfolio - ~strategy_state) + Runner.create ~run_id:header.run_id ~scenario_sha256 ~config + ~initial_portfolio:header.initial_portfolio ~strategy_state |> reducer_result with | Error _ as error -> error diff --git a/lib/risk.ml b/lib/risk.ml index 13378b9..8f5d058 100644 --- a/lib/risk.ml +++ b/lib/risk.ml @@ -1,5 +1,4 @@ type t = { - versioned : bool; base_currency : string; instruments : Instrument.t Id.Instrument.Map.t; instrument_policies : instrument_policy Id.Instrument.Map.t; @@ -11,7 +10,6 @@ type t = { max_leverage : Scalar.Ratio.t; initial_margin_bps : int; maintenance_margin_bps : int; - short_borrow_bps : int; } and instrument_policy = { @@ -194,102 +192,14 @@ let create_group ~group_id ~group_kind ~instrument_ids ~limits = limits; } -let create ~base_currency ~instruments ~max_order_quantity ~max_long_position - ~max_short_position ~max_gross_exposure ~max_leverage ~initial_margin_bps - ~maintenance_margin_bps ~short_borrow_bps = - if not (valid_label base_currency) then - Error "base currency must not be empty or contain whitespace" - else if not (Scalar.Quantity.is_positive max_order_quantity) then - Error "maximum order quantity must be positive" - else if not (Scalar.Quantity.is_positive max_long_position) then - Error "maximum long position must be positive" - else if not (Scalar.Quantity.is_positive max_short_position) then - Error "maximum short position must be positive" - else if Scalar.Money.compare max_gross_exposure Scalar.Money.zero <= 0 then - Error "maximum gross exposure must be positive" - else if initial_margin_bps <= 0 || initial_margin_bps > 10_000 then - Error "initial margin basis points must be between 1 and 10000" - else if maintenance_margin_bps <= 0 || maintenance_margin_bps > 10_000 then - Error "maintenance margin basis points must be between 1 and 10000" - else if initial_margin_bps < maintenance_margin_bps then - Error "initial margin must not be below maintenance margin" - else if short_borrow_bps < 0 || short_borrow_bps > 10_000 then - Error "short borrow basis points must be between 0 and 10000" - else if instruments = [] then Error "risk must define at least one instrument" - else if - List.exists - (fun instrument -> - Scalar.Quantity.compare max_order_quantity - instrument.Instrument.lot_size - < 0) - instruments - then Error "maximum order quantity must cover every instrument lot size" - else if - List.exists - (fun instrument -> - Scalar.Quantity.compare max_long_position instrument.Instrument.lot_size - < 0) - instruments - then Error "maximum long position must cover every instrument lot size" - else if - List.exists - (fun instrument -> - Scalar.Quantity.compare max_short_position - instrument.Instrument.lot_size - < 0) - instruments - then Error "maximum short position must cover every instrument lot size" - else - let add result instrument = - let* map = result in - if Id.Instrument.Map.mem instrument.Instrument.id map then - Error "instrument IDs must be unique" - else Ok (Id.Instrument.Map.add instrument.id instrument map) - in - let* instruments = - List.fold_left add (Ok Id.Instrument.Map.empty) instruments - in - let* instrument_policies = - Id.Instrument.Map.bindings instruments - |> List.fold_left - (fun result (_, instrument) -> - let* policies = result in - let* policy = - create_instrument_policy ~instrument ~max_order_quantity - ~max_long_position ~max_short_position - ~max_notional_exposure:None ~initial_margin_bps - ~maintenance_margin_bps ~shorting_allowed:true - in - Ok (Id.Instrument.Map.add instrument.Instrument.id policy policies)) - (Ok Id.Instrument.Map.empty) - in - Ok - { - versioned = false; - base_currency; - instruments; - instrument_policies; - groups = []; - max_order_quantity; - max_long_position; - max_short_position; - max_gross_exposure; - max_leverage; - initial_margin_bps; - maintenance_margin_bps; - short_borrow_bps; - } - -let create_v7 ~base_currency ~instruments +let create ~base_currency ~instruments ~(instrument_policies : instrument_policy list) ~(groups : group list) - ~max_gross_exposure ~max_leverage ~short_borrow_bps = + ~max_gross_exposure ~max_leverage = if not (valid_label base_currency) then Error "base currency must not be empty or contain whitespace" else if instruments = [] then Error "risk must define at least one instrument" else if Scalar.Money.compare max_gross_exposure Scalar.Money.zero <= 0 then Error "maximum gross exposure must be positive" - else if short_borrow_bps < 0 || short_borrow_bps > 10_000 then - Error "short borrow basis points must be between 0 and 10000" else let add_instrument result instrument = let* map = result in @@ -334,7 +244,6 @@ let create_v7 ~base_currency ~instruments let representative = List.hd instrument_policies in Ok { - versioned = true; base_currency; instruments = instrument_map; instrument_policies = policy_map; @@ -350,7 +259,6 @@ let create_v7 ~base_currency ~instruments max_leverage; initial_margin_bps = representative.initial_margin_bps; maintenance_margin_bps = representative.maintenance_margin_bps; - short_borrow_bps; } let base_currency state = state.base_currency @@ -375,7 +283,6 @@ let max_gross_exposure state = state.max_gross_exposure let max_leverage state = state.max_leverage let initial_margin_bps state = state.initial_margin_bps let maintenance_margin_bps state = state.maintenance_margin_bps -let short_borrow_bps state = state.short_borrow_bps let max_order_quantity_for state instrument_id = Option.map @@ -421,7 +328,7 @@ let group_exposure_from_positions group ~equity positions = concentration; } -let group_exposures state valuation = +let group_exposures state (valuation : Account.valuation) = List.fold_left (fun result group -> let* exposures = result in @@ -433,39 +340,28 @@ let group_exposures state valuation = (Ok []) state.groups |> Result.map List.rev -let margin_snapshot state valuation = +let margin_snapshot state (valuation : Account.valuation) = let requirements = - if not state.versioned then - let* initial = - Scalar.Money.bps_ceil valuation.Account.gross_exposure - ~bps:state.initial_margin_bps - in - let* maintenance = - Scalar.Money.bps_ceil valuation.gross_exposure - ~bps:state.maintenance_margin_bps - in - Ok (initial, maintenance) - else - List.fold_left - (fun result (position : Account.position_attribution) -> - let* initial, maintenance = result in - let* notional = Scalar.Money.absolute position.base_market_value in - let* policy = - match instrument_policy state position.instrument_id with - | Some policy -> Ok policy - | None -> Error "valuation position has no instrument risk policy" - in - let* item_initial = - Scalar.Money.bps_ceil notional ~bps:policy.initial_margin_bps - in - let* item_maintenance = - Scalar.Money.bps_ceil notional ~bps:policy.maintenance_margin_bps - in - let* initial = Scalar.Money.add initial item_initial in - let* maintenance = Scalar.Money.add maintenance item_maintenance in - Ok (initial, maintenance)) - (Ok (Scalar.Money.zero, Scalar.Money.zero)) - valuation.positions + List.fold_left + (fun result (position : Account.position_attribution) -> + let* initial, maintenance = result in + let* notional = Scalar.Money.absolute position.base_market_value in + let* policy = + match instrument_policy state position.instrument_id with + | Some policy -> Ok policy + | None -> Error "valuation position has no instrument risk policy" + in + let* item_initial = + Scalar.Money.bps_ceil notional ~bps:policy.initial_margin_bps + in + let* item_maintenance = + Scalar.Money.bps_ceil notional ~bps:policy.maintenance_margin_bps + in + let* initial = Scalar.Money.add initial item_initial in + let* maintenance = Scalar.Money.add maintenance item_maintenance in + Ok (initial, maintenance)) + (Ok (Scalar.Money.zero, Scalar.Money.zero)) + valuation.positions in let* initial_requirement, maintenance_requirement = requirements in let* initial_excess = @@ -486,139 +382,113 @@ let margin_snapshot state valuation = group_exposures; } -let check_initial_values state ~equity ~gross_exposure = - if Scalar.Money.compare gross_exposure state.max_gross_exposure > 0 then - Error "portfolio would exceed maximum gross exposure" - else - let* leveraged_equity = - Scalar.Money.multiply_ratio equity state.max_leverage - in - if Scalar.Money.compare gross_exposure leveraged_equity > 0 then - Error "portfolio would exceed maximum leverage" +let check_initial state valuation = + let* () = + if + Scalar.Money.compare valuation.Account.gross_exposure + state.max_gross_exposure + > 0 + then Error "portfolio would exceed maximum gross exposure" else - let* initial_requirement = - Scalar.Money.bps_ceil gross_exposure ~bps:state.initial_margin_bps + let* leveraged_equity = + Scalar.Money.multiply_ratio valuation.equity state.max_leverage in - let* initial_excess = Scalar.Money.subtract equity initial_requirement in - if Scalar.Money.compare initial_excess Scalar.Money.zero < 0 then - Error "portfolio would violate initial margin" - else Ok () - -let check_initial state valuation = - if not state.versioned then - check_initial_values state ~equity:valuation.Account.equity - ~gross_exposure:valuation.gross_exposure - else - let* () = - if - Scalar.Money.compare valuation.Account.gross_exposure - state.max_gross_exposure - > 0 - then Error "portfolio would exceed maximum gross exposure" - else - let* leveraged_equity = - Scalar.Money.multiply_ratio valuation.equity state.max_leverage - in - if Scalar.Money.compare valuation.gross_exposure leveraged_equity > 0 - then Error "portfolio would exceed maximum leverage" - else Ok () - in - let* () = - List.fold_left - (fun result (position : Account.position_attribution) -> - let* () = result in - let* policy = - match instrument_policy state position.instrument_id with - | Some policy -> Ok policy - | None -> Error "initial position has no instrument risk policy" - in - let* minimum_short = - Scalar.Quantity.negate policy.max_short_position - in - let* () = - if - Scalar.Quantity.compare position.quantity policy.max_long_position - > 0 - then Error "initial position exceeds its maximum long position" - else if Scalar.Quantity.compare position.quantity minimum_short < 0 - then Error "initial position exceeds its maximum short position" - else if - (not policy.shorting_allowed) - && Scalar.Quantity.is_negative position.quantity - then Error "initial position violates its shorting policy" - else Ok () - in - let* notional = Scalar.Money.absolute position.base_market_value in - match policy.max_notional_exposure with - | Some limit when Scalar.Money.compare notional limit > 0 -> - Error - "initial position exceeds the instrument maximum notional \ - exposure" - | _ -> Ok ()) - (Ok ()) valuation.positions - in - let* margin = margin_snapshot state valuation in - let* () = - if Scalar.Money.compare margin.initial_excess Scalar.Money.zero < 0 then - Error "portfolio would violate instrument initial margin requirements" + if Scalar.Money.compare valuation.gross_exposure leveraged_equity > 0 then + Error "portfolio would exceed maximum leverage" else Ok () - in + in + let* () = List.fold_left - (fun result (group : group) -> + (fun result (position : Account.position_attribution) -> let* () = result in - let* exposure = - match - List.find_opt - (fun item -> Id.Risk_group.equal item.group_id group.group_id) - margin.group_exposures - with - | Some exposure -> Ok exposure - | None -> Error "initial valuation omitted a configured risk group" + let* policy = + match instrument_policy state position.instrument_id with + | Some policy -> Ok policy + | None -> Error "initial position has no instrument risk policy" in - let* absolute_net = Scalar.Money.absolute exposure.net_exposure in - let exceeds option observed = - Option.exists - (fun limit -> Scalar.Money.compare observed limit > 0) - option + let* minimum_short = Scalar.Quantity.negate policy.max_short_position in + let* () = + if + Scalar.Quantity.compare position.quantity policy.max_long_position + > 0 + then Error "initial position exceeds its maximum long position" + else if Scalar.Quantity.compare position.quantity minimum_short < 0 + then Error "initial position exceeds its maximum short position" + else if + (not policy.shorting_allowed) + && Scalar.Quantity.is_negative position.quantity + then Error "initial position violates its shorting policy" + else Ok () in - let group_name = Id.Risk_group.to_string group.group_id in - if exceeds group.limits.max_gross_exposure exposure.gross_exposure then - Error - (Printf.sprintf - "initial portfolio exceeds group %s maximum gross exposure" - group_name) - else if exceeds group.limits.max_long_exposure exposure.long_exposure - then - Error - (Printf.sprintf - "initial portfolio exceeds group %s maximum long exposure" - group_name) - else if exceeds group.limits.max_short_exposure exposure.short_exposure - then - Error - (Printf.sprintf - "initial portfolio exceeds group %s maximum short exposure" - group_name) - else if exceeds group.limits.max_absolute_net_exposure absolute_net then - Error - (Printf.sprintf - "initial portfolio exceeds group %s maximum absolute net \ - exposure" - group_name) - else - match group.limits.max_concentration with - | None -> Ok () - | Some limit -> - let* threshold = - Scalar.Money.multiply_ratio valuation.equity limit - in - if Scalar.Money.compare exposure.gross_exposure threshold > 0 then - Error - (Printf.sprintf - "initial portfolio exceeds group %s maximum concentration" - group_name) - else Ok ()) - (Ok ()) state.groups + let* notional = Scalar.Money.absolute position.base_market_value in + match policy.max_notional_exposure with + | Some limit when Scalar.Money.compare notional limit > 0 -> + Error + "initial position exceeds the instrument maximum notional \ + exposure" + | _ -> Ok ()) + (Ok ()) valuation.positions + in + let* margin = margin_snapshot state valuation in + let* () = + if Scalar.Money.compare margin.initial_excess Scalar.Money.zero < 0 then + Error "portfolio would violate instrument initial margin requirements" + else Ok () + in + List.fold_left + (fun result (group : group) -> + let* () = result in + let* exposure = + match + List.find_opt + (fun item -> Id.Risk_group.equal item.group_id group.group_id) + margin.group_exposures + with + | Some exposure -> Ok exposure + | None -> Error "initial valuation omitted a configured risk group" + in + let* absolute_net = Scalar.Money.absolute exposure.net_exposure in + let exceeds option observed = + Option.exists + (fun limit -> Scalar.Money.compare observed limit > 0) + option + in + let group_name = Id.Risk_group.to_string group.group_id in + if exceeds group.limits.max_gross_exposure exposure.gross_exposure then + Error + (Printf.sprintf + "initial portfolio exceeds group %s maximum gross exposure" + group_name) + else if exceeds group.limits.max_long_exposure exposure.long_exposure then + Error + (Printf.sprintf + "initial portfolio exceeds group %s maximum long exposure" + group_name) + else if exceeds group.limits.max_short_exposure exposure.short_exposure + then + Error + (Printf.sprintf + "initial portfolio exceeds group %s maximum short exposure" + group_name) + else if exceeds group.limits.max_absolute_net_exposure absolute_net then + Error + (Printf.sprintf + "initial portfolio exceeds group %s maximum absolute net exposure" + group_name) + else + match group.limits.max_concentration with + | None -> Ok () + | Some limit -> + let* threshold = + Scalar.Money.multiply_ratio valuation.equity limit + in + if Scalar.Money.compare exposure.gross_exposure threshold > 0 then + Error + (Printf.sprintf + "initial portfolio exceeds group %s maximum concentration" + group_name) + else Ok ()) + (Ok ()) state.groups let invalid result = Result.map_error (fun message -> Invalid message) result @@ -742,10 +612,9 @@ let check_group_fill_limit state ~equity values = in check state.groups -let check_post_fill_for state ~instrument_id:_ ~before_position ~after_position - ~before ~after = - if state.versioned then Ok () - else check_post_fill state ~before_position ~after_position ~before ~after +let check_post_fill_for _state ~instrument_id:_ ~before_position:_ + ~after_position:_ ~before:_ ~after:_ = + Ok () let check_position state quantity = if Scalar.Quantity.compare quantity state.max_long_position > 0 then @@ -761,17 +630,11 @@ let check_position_for state instrument_id quantity = | None -> Error "position refers to an unknown instrument risk policy" | Some policy -> if Scalar.Quantity.compare quantity policy.max_long_position > 0 then - Error - (if state.versioned then - "position would exceed the instrument maximum long position" - else "position would exceed the maximum long position") + Error "position would exceed the instrument maximum long position" else let* minimum_short = Scalar.Quantity.negate policy.max_short_position in if Scalar.Quantity.compare quantity minimum_short < 0 then - Error - (if state.versioned then - "position would exceed the instrument maximum short position" - else "position would exceed the maximum short position") + Error "position would exceed the instrument maximum short position" else if (not policy.shorting_allowed) && Scalar.Quantity.is_negative quantity then Error "instrument policy does not allow short positions" @@ -970,9 +833,7 @@ let first_some checks = let check_projected_values state ~equity values = let* gross, _, _, _ = sum_values values in let* () = - if not state.versioned then - check_initial_values state ~equity ~gross_exposure:gross - else if Scalar.Money.compare gross state.max_gross_exposure > 0 then + if Scalar.Money.compare gross state.max_gross_exposure > 0 then Error "portfolio would exceed maximum gross exposure" else let* leveraged_equity = @@ -1080,100 +941,95 @@ let check_projected_values state ~equity values = let check_reserved_fill state ~account ~oms ~marks ~fx_rates ~(order : Order.t) ~filled_quantity ~after = - if not state.versioned then Ok () - else - let instrument_id = order.request.instrument_id in - let* quantities = - fill_projected_quantities state ~account ~oms ~order ~filled_quantity - |> invalid - in - let* values = - projected_values state ~marks ~fx_rates quantities |> invalid - in - let* policy = - match instrument_policy state instrument_id with - | Some policy -> Ok policy - | None -> Error (Invalid "fill has no instrument risk policy") - in - let* () = - List.fold_left - (fun result value -> - let* () = result in - let* item_policy = - match instrument_policy state value.instrument_id with - | Some policy -> Ok policy - | None -> Error (Invalid "fill projection has no risk policy") + let instrument_id = order.request.instrument_id in + let* quantities = + fill_projected_quantities state ~account ~oms ~order ~filled_quantity + |> invalid + in + let* values = projected_values state ~marks ~fx_rates quantities |> invalid in + let* policy = + match instrument_policy state instrument_id with + | Some policy -> Ok policy + | None -> Error (Invalid "fill has no instrument risk policy") + in + let* () = + List.fold_left + (fun result value -> + let* () = result in + let* item_policy = + match instrument_policy state value.instrument_id with + | Some policy -> Ok policy + | None -> Error (Invalid "fill projection has no risk policy") + in + if + Scalar.Quantity.compare value.quantity item_policy.max_long_position + > 0 + then + Error + (Limit + (Instrument_maximum_long_position + (value.instrument_id, item_policy.max_long_position))) + else + let* minimum_short = + Scalar.Quantity.negate item_policy.max_short_position |> invalid in - if - Scalar.Quantity.compare value.quantity item_policy.max_long_position - > 0 - then + if Scalar.Quantity.compare value.quantity minimum_short < 0 then Error (Limit - (Instrument_maximum_long_position - (value.instrument_id, item_policy.max_long_position))) + (Instrument_maximum_short_position + (value.instrument_id, item_policy.max_short_position))) + else if + (not item_policy.shorting_allowed) + && Scalar.Quantity.is_negative value.quantity + then Error (Limit (Instrument_shorting_disabled value.instrument_id)) else - let* minimum_short = - Scalar.Quantity.negate item_policy.max_short_position |> invalid - in - if Scalar.Quantity.compare value.quantity minimum_short < 0 then - Error - (Limit - (Instrument_maximum_short_position - (value.instrument_id, item_policy.max_short_position))) - else if - (not item_policy.shorting_allowed) - && Scalar.Quantity.is_negative value.quantity - then - Error (Limit (Instrument_shorting_disabled value.instrument_id)) - else - match item_policy.max_notional_exposure with - | Some limit - when Scalar.Money.compare value.absolute_value limit > 0 -> - Error - (Limit - (Instrument_maximum_notional (value.instrument_id, limit))) - | _ -> Ok ()) - (Ok ()) values - in - let* gross, _, _, _ = sum_values values |> invalid in - let* () = - if Scalar.Money.compare gross state.max_gross_exposure > 0 then - Error (Limit (Maximum_gross_exposure state.max_gross_exposure)) - else - let* leveraged_equity = - Scalar.Money.multiply_ratio after.Account.equity state.max_leverage + match item_policy.max_notional_exposure with + | Some limit + when Scalar.Money.compare value.absolute_value limit > 0 -> + Error + (Limit + (Instrument_maximum_notional (value.instrument_id, limit))) + | _ -> Ok ()) + (Ok ()) values + in + let* gross, _, _, _ = sum_values values |> invalid in + let* () = + if Scalar.Money.compare gross state.max_gross_exposure > 0 then + Error (Limit (Maximum_gross_exposure state.max_gross_exposure)) + else + let* leveraged_equity = + Scalar.Money.multiply_ratio after.Account.equity state.max_leverage + |> invalid + in + if Scalar.Money.compare gross leveraged_equity > 0 then + Error (Limit (Maximum_leverage state.max_leverage)) + else Ok () + in + let* initial_requirement = + List.fold_left + (fun result value -> + let* total = result in + let* item_policy = + match instrument_policy state value.instrument_id with + | Some policy -> Ok policy + | None -> Error (Invalid "fill projection has no risk policy") + in + let* requirement = + Scalar.Money.bps_ceil value.absolute_value + ~bps:item_policy.initial_margin_bps |> invalid in - if Scalar.Money.compare gross leveraged_equity > 0 then - Error (Limit (Maximum_leverage state.max_leverage)) - else Ok () - in - let* initial_requirement = - List.fold_left - (fun result value -> - let* total = result in - let* item_policy = - match instrument_policy state value.instrument_id with - | Some policy -> Ok policy - | None -> Error (Invalid "fill projection has no risk policy") - in - let* requirement = - Scalar.Money.bps_ceil value.absolute_value - ~bps:item_policy.initial_margin_bps - |> invalid - in - Scalar.Money.add total requirement |> invalid) - (Ok Scalar.Money.zero) values - in - let* excess = - Scalar.Money.subtract after.equity initial_requirement |> invalid - in - if Scalar.Money.compare excess Scalar.Money.zero < 0 then - Error - (Limit - (Instrument_initial_margin (instrument_id, policy.initial_margin_bps))) - else check_group_fill_limit state ~equity:after.equity values + Scalar.Money.add total requirement |> invalid) + (Ok Scalar.Money.zero) values + in + let* excess = + Scalar.Money.subtract after.equity initial_requirement |> invalid + in + if Scalar.Money.compare excess Scalar.Money.zero < 0 then + Error + (Limit + (Instrument_initial_margin (instrument_id, policy.initial_margin_bps))) + else check_group_fill_limit state ~equity:after.equity values let check state ~account ~oms ~marks ~fx_rates (request : Order.request) = match instrument state request.instrument_id with @@ -1187,11 +1043,7 @@ let check state ~account ~oms ~marks ~fx_rates (request : Order.request) = if Scalar.Quantity.compare request.Order.quantity policy.max_order_quantity > 0 - then - Error - (if state.versioned then - "order exceeds the instrument maximum order quantity" - else "order exceeds the maximum order quantity") + then Error "order exceeds the instrument maximum order quantity" else let* () = check_alignment instrument request in let* () = check_self_cross ~oms request in diff --git a/lib/risk.mli b/lib/risk.mli index 52d6455..6b0795c 100644 --- a/lib/risk.mli +++ b/lib/risk.mli @@ -74,14 +74,10 @@ type fill_check_error = Limit of fill_limit | Invalid of string val create : base_currency:string -> instruments:Instrument.t list -> - max_order_quantity:Scalar.Quantity.t -> - max_long_position:Scalar.Quantity.t -> - max_short_position:Scalar.Quantity.t -> + instrument_policies:instrument_policy list -> + groups:group list -> max_gross_exposure:Scalar.Money.t -> max_leverage:Scalar.Ratio.t -> - initial_margin_bps:int -> - maintenance_margin_bps:int -> - short_borrow_bps:int -> (t, string) result val create_instrument_policy : @@ -110,16 +106,6 @@ val create_group : limits:group_limits -> (group, string) result -val create_v7 : - base_currency:string -> - instruments:Instrument.t list -> - instrument_policies:instrument_policy list -> - groups:group list -> - max_gross_exposure:Scalar.Money.t -> - max_leverage:Scalar.Ratio.t -> - short_borrow_bps:int -> - (t, string) result - val base_currency : t -> string val instruments : t -> Instrument.t list val instrument : t -> Id.Instrument.t -> Instrument.t option @@ -133,7 +119,6 @@ val max_gross_exposure : t -> Scalar.Money.t val max_leverage : t -> Scalar.Ratio.t val initial_margin_bps : t -> int val maintenance_margin_bps : t -> int -val short_borrow_bps : t -> int val max_order_quantity_for : t -> Id.Instrument.t -> Scalar.Quantity.t option val check_position : t -> Scalar.Quantity.t -> (unit, string) result diff --git a/lib/scenario.ml b/lib/scenario.ml index 86a10f8..54d4607 100644 --- a/lib/scenario.ml +++ b/lib/scenario.ml @@ -3,15 +3,14 @@ type t = { metadata : Yojson.Safe.t; run_id : Id.Run.t; base_currency : string; - initial_cash : (string * Scalar.Money.t) list; - initial_portfolio : Initial_portfolio.t option; + initial_portfolio : Initial_portfolio.t; instruments : Instrument.t list; venue_calendars : Venue_calendar.t list; risk : Risk.t; execution_model : Execution_model.t; execution : Execution.t; - financing : Financing.policy option; - settlement : Settlement.policy option; + financing : Financing.policy; + settlement : Settlement.policy; max_internal_events : int; schedule : (int64 * Strategy.intent list) list; slices : Market_slice.t list; @@ -22,15 +21,14 @@ type stream_header = { metadata : Yojson.Safe.t; run_id : Id.Run.t; base_currency : string; - initial_cash : (string * Scalar.Money.t) list; - initial_portfolio : Initial_portfolio.t option; + initial_portfolio : Initial_portfolio.t; instruments : Instrument.t list; venue_calendars : Venue_calendar.t list; risk : Risk.t; execution_model : Execution_model.t; execution : Execution.t; - financing : Financing.policy option; - settlement : Settlement.policy option; + financing : Financing.policy; + settlement : Settlement.policy; max_internal_events : int; } @@ -327,48 +325,6 @@ let parse_instrument json = let* lot_size = parse_quantity ~name:"lot_size" lot_json in Instrument.create ~id ~symbol ~quote_currency ~tick_size ~lot_size -let parse_legacy_risk base_currency instruments json = - let* fields = - object_fields ~name:"risk" - ~expected: - [ - "max_order_quantity"; - "max_long_position"; - "max_short_position"; - "max_gross_exposure"; - "max_leverage"; - "initial_margin_bps"; - "maintenance_margin_bps"; - "short_borrow_bps"; - ] - json - in - let* order_json = field fields "max_order_quantity" in - let* max_order_quantity = - parse_quantity ~name:"max_order_quantity" order_json - in - let* long_json = field fields "max_long_position" in - let* max_long_position = parse_quantity ~name:"max_long_position" long_json in - let* short_json = field fields "max_short_position" in - let* max_short_position = - parse_quantity ~name:"max_short_position" short_json - in - let* gross_json = field fields "max_gross_exposure" in - let* max_gross_exposure = parse_money ~name:"max_gross_exposure" gross_json in - let* leverage_json = field fields "max_leverage" in - let* max_leverage = parse_ratio ~name:"max_leverage" leverage_json in - let* initial_json = field fields "initial_margin_bps" in - let* initial_margin_bps = integer ~name:"initial_margin_bps" initial_json in - let* maintenance_json = field fields "maintenance_margin_bps" in - let* maintenance_margin_bps = - integer ~name:"maintenance_margin_bps" maintenance_json - in - let* borrow_json = field fields "short_borrow_bps" in - let* short_borrow_bps = integer ~name:"short_borrow_bps" borrow_json in - Risk.create ~base_currency ~instruments ~max_order_quantity ~max_long_position - ~max_short_position ~max_gross_exposure ~max_leverage ~initial_margin_bps - ~maintenance_margin_bps ~short_borrow_bps - let parse_nullable parse ~name = function | `Null -> Ok None | json -> parse ~name json |> Result.map Option.some @@ -507,16 +463,12 @@ let parse_group json = in Risk.create_group ~group_id ~group_kind ~instrument_ids ~limits -let parse_v7_risk base_currency instruments json = +let parse_risk base_currency instruments json = let* fields = object_fields ~name:"risk" ~expected: [ - "max_gross_exposure"; - "max_leverage"; - "short_borrow_bps"; - "instrument_policies"; - "groups"; + "max_gross_exposure"; "max_leverage"; "instrument_policies"; "groups"; ] json in @@ -546,30 +498,8 @@ let parse_v7_risk base_currency instruments json = field fields "max_leverage" |> fun result -> Result.bind result (parse_ratio ~name:"max_leverage") in - let* short_borrow_bps = - field fields "short_borrow_bps" |> fun result -> - Result.bind result (integer ~name:"short_borrow_bps") - in - Risk.create_v7 ~base_currency ~instruments ~instrument_policies ~groups - ~max_gross_exposure ~max_leverage ~short_borrow_bps - -let parse_risk ~contract_version base_currency instruments json = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7" ] - then parse_v7_risk base_currency instruments json - else parse_legacy_risk base_currency instruments json - -let parse_execution_values fields = - let* participation_json = field fields "participation_bps" in - let* participation_bps = - integer ~name:"participation_bps" participation_json - in - let* fixed_json = field fields "fixed_fee" in - let* fixed_fee = parse_money ~name:"fixed_fee" fixed_json in - let* fee_json = field fields "fee_bps" in - let* fee_bps = integer ~name:"fee_bps" fee_json in - Execution.create ~participation_bps ~fixed_fee ~fee_bps + Risk.create ~base_currency ~instruments ~instrument_policies ~groups + ~max_gross_exposure ~max_leverage let parse_fee_component json = let* fields = @@ -683,11 +613,11 @@ let parse_execution_common instruments fields = in Ok (participation_bps, schedules) -let parse_execution_v2 instruments fields = +let parse_scheduled_execution instruments fields = let* participation_bps, schedules = parse_execution_common instruments fields in - Execution.create_v2 ~participation_bps ~fee_schedules:schedules + Execution.create ~participation_bps ~fee_schedules:schedules let parse_order_book_execution instruments fields = let* participation_bps, fee_schedules = @@ -755,28 +685,7 @@ let parse_conservative_execution instruments fields = Execution.create_conservative ~participation_bps ~fee_schedules ~half_spread_bps ~impact_coefficient_bps ~missing_volume_policy -let parse_legacy_execution ~contract_version json = - let* fields = - object_fields ~name:"execution" - ~expected:[ "model"; "participation_bps"; "fixed_fee"; "fee_bps" ] - json - in - let* model_json = field fields "model" in - let* model_name = string ~name:"execution model" model_json in - let* execution_model = Execution_model.find model_name in - let* () = - if Execution_model.supports_contract execution_model contract_version then - Ok () - else - Error - (Printf.sprintf - "execution model %S does not support scenario contract %S" model_name - contract_version) - in - let* execution = parse_execution_values fields in - Ok (execution_model, execution) - -let parse_versioned_execution ~contract_version ~instruments json = +let parse_execution ~contract_version ~instruments json = let* fields = object_fields ~name:"execution" ~expected:[ "model"; "configuration" ] json in @@ -819,20 +728,10 @@ let parse_versioned_execution ~contract_version ~instruments json = then parse_conservative_execution instruments configuration else if String.equal model_name "order_book_v1" then parse_order_book_execution instruments configuration - else if - String.equal model_name "quote_trade_v1" || String.equal version "2" - then parse_execution_v2 instruments configuration - else parse_execution_values configuration + else parse_scheduled_execution instruments configuration in Ok (execution_model, execution) -let parse_execution ~contract_version ~instruments json = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6"; "5" ] - then parse_versioned_execution ~contract_version ~instruments json - else parse_legacy_execution ~contract_version json - let parse_side json = let* value = string ~name:"side" json in match value with @@ -877,37 +776,23 @@ let parse_portfolio_intent ~name ~parse_target make json = let* targets = map_list parse_target targets_json in Ok (make targets) -let parse_submit_intent ~contract_version json = - let versioned = - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8" ] - in +let parse_submit_intent json = let* fields = object_fields ~name:"submit_order intent" ~expected: - (if versioned then - [ - "type"; - "instrument_id"; - "side"; - "quantity"; - "order_kind"; - "trigger_price"; - "limit_price"; - "time_in_force"; - "venue_id"; - "calendar_id"; - "expires_at"; - ] - else - [ - "type"; - "instrument_id"; - "side"; - "quantity"; - "order_kind"; - "limit_price"; - ]) + [ + "type"; + "instrument_id"; + "side"; + "quantity"; + "order_kind"; + "trigger_price"; + "limit_price"; + "time_in_force"; + "venue_id"; + "calendar_id"; + "expires_at"; + ] json in let* instrument_json = field fields "instrument_id" in @@ -921,19 +806,17 @@ let parse_submit_intent ~contract_version json = let* kind_json = field fields "order_kind" in let* kind_name = string ~name:"order_kind" kind_json in let* limit_json = field fields "limit_price" in - let* trigger_json = - if versioned then field fields "trigger_price" else Ok `Null - in + let* trigger_json = field fields "trigger_price" in let* kind = match (kind_name, trigger_json, limit_json) with | "market", `Null, `Null -> Ok Order.Market | "limit", `Null, value -> let* limit = parse_price ~name:"limit_price" value in Ok (Order.Limit limit) - | "stop", trigger, `Null when versioned -> + | "stop", trigger, `Null -> let* trigger = parse_price ~name:"trigger_price" trigger in Ok (Order.Stop trigger) - | "stop_limit", trigger, limit when versioned -> + | "stop_limit", trigger, limit -> let* trigger_price = parse_price ~name:"trigger_price" trigger in let* limit_price = parse_price ~name:"limit_price" limit in Ok (Order.Stop_limit { trigger_price; limit_price }) @@ -941,32 +824,30 @@ let parse_submit_intent ~contract_version json = Error "market order trigger_price and limit_price must be null" | _ -> Error "invalid order_kind" in + let* tif_json = field fields "time_in_force" in + let* tif = string ~name:"time_in_force" tif_json in + let* venue_json = field fields "venue_id" in + let* calendar_json = field fields "calendar_id" in + let* expires_json = field fields "expires_at" in let* time_in_force = - if not versioned then Ok (Order.compatibility_time_in_force kind) - else - let* tif_json = field fields "time_in_force" in - let* tif = string ~name:"time_in_force" tif_json in - let* venue_json = field fields "venue_id" in - let* calendar_json = field fields "calendar_id" in - let* expires_json = field fields "expires_at" in - match (tif, venue_json, calendar_json, expires_json) with - | "gtc", `Null, `Null, `Null -> Ok Order.Gtc - | "ioc", `Null, `Null, `Null -> Ok Order.Ioc - | "fok", `Null, `Null, `Null -> Ok Order.Fok - | "day", venue, calendar, `Null -> - let* venue_id = parse_id Id.Venue.of_string ~name:"venue_id" venue in - let* calendar_id = - parse_id Id.Venue_calendar.of_string ~name:"calendar_id" calendar - in - Ok (Order.Day { venue_id; calendar_id }) - | "gtd", `Null, `Null, expires -> - let* value = string ~name:"expires_at" expires in - let* expires_at = Codec.ptime_of_string value in - Ok (Order.Gtd expires_at) - | _ -> Error "time_in_force companion fields are inconsistent" + match (tif, venue_json, calendar_json, expires_json) with + | "gtc", `Null, `Null, `Null -> Ok Order.Gtc + | "ioc", `Null, `Null, `Null -> Ok Order.Ioc + | "fok", `Null, `Null, `Null -> Ok Order.Fok + | "day", venue, calendar, `Null -> + let* venue_id = parse_id Id.Venue.of_string ~name:"venue_id" venue in + let* calendar_id = + parse_id Id.Venue_calendar.of_string ~name:"calendar_id" calendar + in + Ok (Order.Day { venue_id; calendar_id }) + | "gtd", `Null, `Null, expires -> + let* value = string ~name:"expires_at" expires in + let* expires_at = Codec.ptime_of_string value in + Ok (Order.Gtd expires_at) + | _ -> Error "time_in_force companion fields are inconsistent" in let* request = - Order.request_v8 ~instrument_id ~side ~quantity ~kind ~time_in_force + Order.request ~instrument_id ~side ~quantity ~kind ~time_in_force ~origin:Order.Direct in Ok (Strategy.Submit_order request) @@ -980,88 +861,73 @@ let parse_cancel_intent json = let* order_id = parse_id Id.Order.of_string ~name:"order_id" order_json in Ok (Strategy.Cancel_order order_id) -let parse_metric_intent ~contract_version json = - if not (String.equal contract_version "16") then - let* fields = - object_fields ~name:"emit_metric intent" - ~expected:[ "type"; "name"; "value" ] - json - in - let* name_json = field fields "name" in - let* name = string ~name:"metric name" name_json in - let* value_json = field fields "value" in - let* value = string ~name:"metric value" value_json in - let* metric = Metric.create ~name ~value:(Metric.String value) () in - Ok (Strategy.Emit_metric metric) - else - let* fields = - match json with - | `Assoc fields -> - let names = List.map fst fields in - let unique = List.sort_uniq String.compare names in - let allowed = - [ "aggregation"; "dimensions"; "name"; "type"; "unit"; "value" ] - in - if List.length names <> List.length unique then - Error "emit_metric intent must not contain duplicate fields" - else if - not - (List.for_all (fun name -> List.mem name allowed) unique - && List.for_all - (fun name -> List.mem name unique) - [ "type"; "name"; "value" ]) - then Error "emit_metric intent has unknown or missing fields" - else Ok fields - | _ -> Error "emit_metric intent must be a JSON object" - in - let* name_json = field fields "name" in - let* name = string ~name:"metric name" name_json in - let* value = - let* json = field fields "value" in - let* value_fields = - object_fields ~name:"metric value" ~expected:[ "type"; "value" ] json - in - let* type_json = field value_fields "type" in - let* value_type = string ~name:"metric value type" type_json in - let* value_json = field value_fields "value" in - match (value_type, value_json) with - | "numeric", `String value -> - Metric.numeric_of_string value - |> Result.map (fun value -> Metric.Numeric value) - | "string", `String value -> Ok (Metric.String value) - | "boolean", `Bool value -> Ok (Metric.Boolean value) - | _ -> Error "metric value does not match its declared type" - in - let* unit_ = - match List.assoc_opt "unit" fields with - | None -> Ok None - | Some json -> string ~name:"metric unit" json |> Result.map Option.some - in - let* dimensions = - match List.assoc_opt "dimensions" fields with - | None -> Ok [] - | Some (`Assoc dimensions) -> - List.fold_left - (fun result (key, json) -> - let* values = result in - let* value = string ~name:"metric dimension value" json in - Ok ((key, value) :: values)) - (Ok []) dimensions - | Some _ -> Error "metric dimensions must be an object" - in - let* aggregation = - match List.assoc_opt "aggregation" fields with - | None -> Ok None - | Some json -> - let* value = string ~name:"metric aggregation" json in - Metric.aggregation_of_string value |> Result.map Option.some - in - let* metric = - Metric.create ~name ~value ?unit_ ~dimensions ?aggregation () +let parse_metric_intent json = + let* fields = + match json with + | `Assoc fields -> + let names = List.map fst fields in + let unique = List.sort_uniq String.compare names in + let allowed = + [ "aggregation"; "dimensions"; "name"; "type"; "unit"; "value" ] + in + if List.length names <> List.length unique then + Error "emit_metric intent must not contain duplicate fields" + else if + not + (List.for_all (fun name -> List.mem name allowed) unique + && List.for_all + (fun name -> List.mem name unique) + [ "type"; "name"; "value" ]) + then Error "emit_metric intent has unknown or missing fields" + else Ok fields + | _ -> Error "emit_metric intent must be a JSON object" + in + let* name_json = field fields "name" in + let* name = string ~name:"metric name" name_json in + let* value = + let* json = field fields "value" in + let* value_fields = + object_fields ~name:"metric value" ~expected:[ "type"; "value" ] json in - Ok (Strategy.Emit_metric metric) - -let parse_intent ~contract_version json = + let* type_json = field value_fields "type" in + let* value_type = string ~name:"metric value type" type_json in + let* value_json = field value_fields "value" in + match (value_type, value_json) with + | "numeric", `String value -> + Metric.numeric_of_string value + |> Result.map (fun value -> Metric.Numeric value) + | "string", `String value -> Ok (Metric.String value) + | "boolean", `Bool value -> Ok (Metric.Boolean value) + | _ -> Error "metric value does not match its declared type" + in + let* unit_ = + match List.assoc_opt "unit" fields with + | None -> Ok None + | Some json -> string ~name:"metric unit" json |> Result.map Option.some + in + let* dimensions = + match List.assoc_opt "dimensions" fields with + | None -> Ok [] + | Some (`Assoc dimensions) -> + List.fold_left + (fun result (key, json) -> + let* values = result in + let* value = string ~name:"metric dimension value" json in + Ok ((key, value) :: values)) + (Ok []) dimensions + | Some _ -> Error "metric dimensions must be an object" + in + let* aggregation = + match List.assoc_opt "aggregation" fields with + | None -> Ok None + | Some json -> + let* value = string ~name:"metric aggregation" json in + Metric.aggregation_of_string value |> Result.map Option.some + in + let* metric = Metric.create ~name ~value ?unit_ ~dimensions ?aggregation () in + Ok (Strategy.Emit_metric metric) + +let parse_intent json = match json with | `Assoc fields -> ( match List.assoc_opt "type" fields with @@ -1075,22 +941,20 @@ let parse_intent ~contract_version json = ~parse_target:parse_quantity_target (fun targets -> Strategy.Target_quantities targets) json - | Some (`String "submit_order") -> - parse_submit_intent ~contract_version json + | Some (`String "submit_order") -> parse_submit_intent json | Some (`String "cancel_order") -> parse_cancel_intent json - | Some (`String "emit_metric") -> - parse_metric_intent ~contract_version json + | Some (`String "emit_metric") -> parse_metric_intent json | Some _ -> Error "unsupported intent type" | None -> Error "intent is missing type") | _ -> Error "intent must be a JSON object" -let intent_of_yojson ?(contract_version = Contract.previous_version) json = - parse_intent ~contract_version json +let intent_of_yojson json = + parse_intent json |> Result.map_error (fun message -> Diagnostic.make ~code:Diagnostic.Scenario_invalid ~phase:Diagnostic.Validation ~json_path:"$" message) -let parse_schedule_item ~contract_version json = +let parse_schedule_item json = let* fields = object_fields ~name:"schedule item" ~expected:[ "after_slice_sequence"; "intents" ] @@ -1105,7 +969,7 @@ let parse_schedule_item ~contract_version json = (Printf.sprintf "intent count is %d; limit is %d" (List.length intents_json) Resource_limits.intents_per_batch) else - let* intents = map_list (parse_intent ~contract_version) intents_json in + let* intents = map_list parse_intent intents_json in Ok (sequence, intents) let parse_volume = function @@ -1919,45 +1783,26 @@ let parse_order_book_event json = ~ingest_sequence ~book_sequence ~price ~quantity ~aggressor_side | _ -> assert false -let parse_slice ~contract_version json = - let financing_fields = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] - then [ "borrow_observations"; "cash_rate_observations" ] - else [] - in - let settlement_fields = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] then - [ "settlement_failures" ] - else [] - in - let lifecycle_fields = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12" ] then - [ "lifecycle_events" ] - else [] - in - let market_event_fields = - if List.mem contract_version [ "16"; "15"; "14" ] then [ "market_events" ] - else [] - in - let order_book_event_fields = - if List.mem contract_version [ "16"; "15" ] then [ "order_book_events" ] - else [] - in +let parse_slice json = let* fields = object_fields ~name:"market slice" ~expected: - ([ - "slice_sequence"; - "start_at"; - "end_at"; - "available_at"; - "received_at"; - "bars"; - "fx_rates"; - "corporate_actions"; - ] - @ financing_fields @ settlement_fields @ lifecycle_fields - @ market_event_fields @ order_book_event_fields) + [ + "slice_sequence"; + "start_at"; + "end_at"; + "available_at"; + "received_at"; + "bars"; + "fx_rates"; + "corporate_actions"; + "borrow_observations"; + "cash_rate_observations"; + "settlement_failures"; + "lifecycle_events"; + "market_events"; + "order_book_events"; + ] json in let* sequence_json = field fields "slice_sequence" in @@ -1979,81 +1824,46 @@ let parse_slice ~contract_version json = let* actions_json = field fields "corporate_actions" in let* actions_json = list ~name:"corporate_actions" actions_json in let* corporate_actions = map_list parse_corporate_action actions_json in - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] then - let* borrow_json = - Result.bind - (field fields "borrow_observations") - (list ~name:"borrow_observations") - in - let* borrow_observations = map_list parse_borrow_observation borrow_json in - let* cash_json = - Result.bind - (field fields "cash_rate_observations") - (list ~name:"cash_rate_observations") - in - let* cash_rate_observations = - map_list parse_cash_rate_observation cash_json - in - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] then - let* failures_json = - Result.bind - (field fields "settlement_failures") - (list ~name:"settlement_failures") - in - let* settlement_failures = - map_list parse_settlement_failure failures_json - in - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12" ] then - let* lifecycle_json = - Result.bind - (field fields "lifecycle_events") - (list ~name:"lifecycle_events") - in - let* lifecycle_events = map_list parse_lifecycle_event lifecycle_json in - if List.mem contract_version [ "16"; "15"; "14" ] then - let* events_json = - Result.bind - (field fields "market_events") - (list ~name:"market_events") - in - let* market_events = map_list parse_market_event events_json in - if List.mem contract_version [ "16"; "15" ] then - let* book_events_json = - Result.bind - (field fields "order_book_events") - (list ~name:"order_book_events") - in - let* order_book_events = - map_list parse_order_book_event book_events_json - in - Market_slice.create_v15 ~slice_sequence ~start_at ~end_at - ~available_at ~received_at ~bars ~fx_rates ~corporate_actions - ~borrow_observations ~cash_rate_observations ~settlement_failures - ~lifecycle_events ~market_events ~order_book_events - else - Market_slice.create_v14 ~slice_sequence ~start_at ~end_at - ~available_at ~received_at ~bars ~fx_rates ~corporate_actions - ~borrow_observations ~cash_rate_observations ~settlement_failures - ~lifecycle_events ~market_events - else - let create = - if String.equal contract_version "13" then Market_slice.create_v13 - else Market_slice.create_v12 - in - create ~slice_sequence ~start_at ~end_at ~available_at ~received_at - ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations ~settlement_failures ~lifecycle_events - else - Market_slice.create_v11 ~slice_sequence ~start_at ~end_at ~available_at - ~received_at ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations ~settlement_failures - else - Market_slice.create_v10 ~slice_sequence ~start_at ~end_at ~available_at - ~received_at ~bars ~fx_rates ~corporate_actions ~borrow_observations - ~cash_rate_observations - else - Market_slice.create ~slice_sequence ~start_at ~end_at ~available_at - ~received_at ~bars ~fx_rates ~corporate_actions + let* borrow_json = + Result.bind + (field fields "borrow_observations") + (list ~name:"borrow_observations") + in + let* borrow_observations = map_list parse_borrow_observation borrow_json in + let* cash_json = + Result.bind + (field fields "cash_rate_observations") + (list ~name:"cash_rate_observations") + in + let* cash_rate_observations = + map_list parse_cash_rate_observation cash_json + in + let* failures_json = + Result.bind + (field fields "settlement_failures") + (list ~name:"settlement_failures") + in + let* settlement_failures = map_list parse_settlement_failure failures_json in + let* lifecycle_json = + Result.bind + (field fields "lifecycle_events") + (list ~name:"lifecycle_events") + in + let* lifecycle_events = map_list parse_lifecycle_event lifecycle_json in + let* events_json = + Result.bind (field fields "market_events") (list ~name:"market_events") + in + let* market_events = map_list parse_market_event events_json in + let* book_events_json = + Result.bind + (field fields "order_book_events") + (list ~name:"order_book_events") + in + let* order_book_events = map_list parse_order_book_event book_events_json in + Market_slice.create ~slice_sequence ~start_at ~end_at ~available_at + ~received_at ~bars ~fx_rates ~corporate_actions ~borrow_observations + ~cash_rate_observations ~settlement_failures ~lifecycle_events + ~market_events ~order_book_events let child root field = root ^ "." ^ field @@ -2085,28 +1895,11 @@ let construct_header ~root ~contract_path ~contract_version string ~name:"base_currency" shape.base_currency |> at (child root "base_currency") in - let* initial_cash, initial_portfolio = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then - let* portfolio = - parse_initial_portfolio ~base_currency shape.initial_state - |> at (child root "initial_portfolio") - in - Ok (portfolio.Initial_portfolio.cash, Some portfolio) - else - let* initial_cash_json = - list ~name:"initial_cash" shape.initial_state - |> at (child root "initial_cash") - in - let* initial_cash = - map_list_at - (child root "initial_cash") - parse_cash_balance initial_cash_json - in - Ok (initial_cash, None) + let* initial_portfolio = + parse_initial_portfolio ~base_currency shape.initial_state + |> at (child root "initial_portfolio") in + let initial_cash = initial_portfolio.Initial_portfolio.cash in let* instruments_json = list ~name:"instruments" shape.instruments |> at (child root "instruments") @@ -2116,7 +1909,8 @@ let construct_header ~root ~contract_path ~contract_version in let* venue_calendars = match shape.venue_calendars with - | None -> Ok [] + | None -> + Error "missing venue calendars" |> at (child root "venue_calendars") | Some calendars_json -> let* calendars_json = list ~name:"venue_calendars" calendars_json @@ -2131,45 +1925,30 @@ let construct_header ~root ~contract_path ~contract_version |> at (child root "max_internal_events") in let* currencies, catalog = - Scenario_validation.header ~root ~contract_version ~base_currency - ~initial_cash ~instruments ~venue_calendars ~max_internal_events + Scenario_validation.header ~root ~base_currency ~initial_cash ~instruments + ~venue_calendars ~max_internal_events in let* risk = - parse_risk ~contract_version base_currency instruments shape.risk - |> at (child root "risk") + parse_risk base_currency instruments shape.risk |> at (child root "risk") in let* () = - match initial_portfolio with - | None -> Ok () - | Some portfolio -> - Scenario_validation.initial_portfolio ~root ~currencies ~catalog - ~instruments ~risk portfolio + Scenario_validation.initial_portfolio ~root ~currencies ~catalog + ~instruments ~risk initial_portfolio in let* execution_model, execution = parse_execution ~contract_version ~instruments shape.execution |> at (child root "execution") in let* financing = - match (contract_version, shape.financing) with - | ("12" | "11" | "10"), Some json -> - parse_financing json |> at (child root "financing") - | ("12" | "11" | "10"), None -> - Error "missing financing policy" |> at (child root "financing") - | _, _ -> Ok Financing.legacy_policy - in - let financing = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] - then Some financing - else None + match shape.financing with + | Some json -> parse_financing json |> at (child root "financing") + | None -> Error "missing financing policy" |> at (child root "financing") in let* settlement = - match (contract_version, shape.settlement) with - | ("12" | "11"), Some json -> - let* policy = parse_settlement json |> at (child root "settlement") in - Ok (Some policy) - | ("12" | "11"), None -> + match shape.settlement with + | Some json -> parse_settlement json |> at (child root "settlement") + | None -> Error "missing settlement policy" |> at (child root "settlement") - | _, _ -> Ok None in let header : stream_header = { @@ -2177,7 +1956,6 @@ let construct_header ~root ~contract_path ~contract_version metadata; run_id; base_currency; - initial_cash; initial_portfolio; instruments; venue_calendars; @@ -2203,15 +1981,9 @@ let construct_batch (shape : Scenario_shape.batch) = let* schedule_json = list ~name:"schedule" shape.schedule |> at "$.schedule" in - let* schedule = - map_list_at "$.schedule" - (parse_schedule_item ~contract_version) - schedule_json - in + let* schedule = map_list_at "$.schedule" parse_schedule_item schedule_json in let* slices_json = list ~name:"slices" shape.slices |> at "$.slices" in - let* slices = - map_list_at "$.slices" (parse_slice ~contract_version) slices_json - in + let* slices = map_list_at "$.slices" parse_slice slices_json in let* () = Scenario_validation.batch ~root ~base_currency:header.base_currency ~currencies ~instruments:header.instruments ~risk:header.risk ~catalog @@ -2223,7 +1995,6 @@ let construct_batch (shape : Scenario_shape.batch) = metadata = header.metadata; run_id = header.run_id; base_currency = header.base_currency; - initial_cash = header.initial_cash; initial_portfolio = header.initial_portfolio; instruments = header.instruments; venue_calendars = header.venue_calendars; @@ -2291,8 +2062,7 @@ let stream_header_of_yojson ~contract_version json = in let* () = check_stream_header_limits json in let* shape = - Scenario_shape.stream_header ~contract_version json - |> Result.map_error (diagnostic code) + Scenario_shape.stream_header json |> Result.map_error (diagnostic code) in construct_header ~root:"$.payload" ~contract_path:"$.contract_version" ~contract_version shape @@ -2306,7 +2076,7 @@ let stream_item_of_yojson header ~previous json = Scenario_shape.stream_item json |> Result.map_error (diagnostic code) in let* market_slice = - parse_slice ~contract_version:header.contract_version shape.market_slice + parse_slice shape.market_slice |> at "$.payload.market_slice" |> Result.map_error (diagnostic code) in @@ -2316,9 +2086,7 @@ let stream_item_of_yojson header ~previous json = |> Result.map_error (diagnostic code) in let* intents = - map_list_at "$.payload.intents" - (parse_intent ~contract_version:header.contract_version) - intents_json + map_list_at "$.payload.intents" parse_intent intents_json |> Result.map_error (diagnostic code) in let previous_slice, previous_intents, prior_action_ids = diff --git a/lib/scenario.mli b/lib/scenario.mli index 245281c..29ff2af 100644 --- a/lib/scenario.mli +++ b/lib/scenario.mli @@ -5,15 +5,14 @@ type t = private { metadata : Yojson.Safe.t; run_id : Id.Run.t; base_currency : string; - initial_cash : (string * Scalar.Money.t) list; - initial_portfolio : Initial_portfolio.t option; + initial_portfolio : Initial_portfolio.t; instruments : Instrument.t list; venue_calendars : Venue_calendar.t list; risk : Risk.t; execution_model : Execution_model.t; execution : Execution.t; - financing : Financing.policy option; - settlement : Settlement.policy option; + financing : Financing.policy; + settlement : Settlement.policy; max_internal_events : int; schedule : (int64 * Strategy.intent list) list; slices : Market_slice.t list; @@ -24,15 +23,14 @@ type stream_header = private { metadata : Yojson.Safe.t; run_id : Id.Run.t; base_currency : string; - initial_cash : (string * Scalar.Money.t) list; - initial_portfolio : Initial_portfolio.t option; + initial_portfolio : Initial_portfolio.t; instruments : Instrument.t list; venue_calendars : Venue_calendar.t list; risk : Risk.t; execution_model : Execution_model.t; execution : Execution.t; - financing : Financing.policy option; - settlement : Settlement.policy option; + financing : Financing.policy; + settlement : Settlement.policy; max_internal_events : int; } @@ -45,11 +43,7 @@ type stream_item = private { val of_yojson : Yojson.Safe.t -> (t, Diagnostic.t) result val of_string : string -> (t, Diagnostic.t) result val read_file : string -> (t, Diagnostic.t) result - -val intent_of_yojson : - ?contract_version:string -> - Yojson.Safe.t -> - (Strategy.intent, Diagnostic.t) result +val intent_of_yojson : Yojson.Safe.t -> (Strategy.intent, Diagnostic.t) result val stream_header_of_yojson : contract_version:string -> diff --git a/lib/scenario_shape.ml b/lib/scenario_shape.ml index 71de814..40bed59 100644 --- a/lib/scenario_shape.ml +++ b/lib/scenario_shape.ml @@ -65,38 +65,17 @@ let field ~root fields name = Error (error ~json_path:(root ^ "." ^ name) ("missing JSON field: " ^ name)) -let common ~root ~contract_version fields = +let common ~root fields = let* metadata = field ~root fields "metadata" in let* run_id = field ~root fields "run_id" in let* base_currency = field ~root fields "base_currency" in - let initial_field = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then "initial_portfolio" - else "initial_cash" - in - let* initial_state = field ~root fields initial_field in + let* initial_state = field ~root fields "initial_portfolio" in let* instruments = field ~root fields "instruments" in - let venue_calendars = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6"; "5" ] - then List.assoc_opt "venue_calendars" fields - else None - in + let venue_calendars = List.assoc_opt "venue_calendars" fields in let* risk = field ~root fields "risk" in let* execution = field ~root fields "execution" in - let financing = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] - then List.assoc_opt "financing" fields - else None - in - let settlement = - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] then - List.assoc_opt "settlement" fields - else None - in + let financing = List.assoc_opt "financing" fields in + let settlement = List.assoc_opt "settlement" fields in let* max_internal_events = field ~root fields "max_internal_events" in Ok { @@ -120,99 +99,55 @@ let batch json = | `Assoc fields -> field ~root fields "contract_version" | _ -> Error (error ~json_path:root "scenario must be a JSON object") in - let contract_version = - match preliminary with `String value -> value | _ -> "" - in - let calendar_fields = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6"; "5" ] - then [ "venue_calendars" ] - else [] - in - let initial_field = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then "initial_portfolio" - else "initial_cash" - in + let _ = preliminary in let* fields = object_fields ~json_path:root ~name:"scenario" ~expected: - ([ - "contract_version"; - "metadata"; - "run_id"; - "base_currency"; - initial_field; - "instruments"; - "risk"; - "execution"; - "max_internal_events"; - "schedule"; - "slices"; - ] - @ calendar_fields - @ (if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] - then [ "financing" ] - else []) - @ - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] then - [ "settlement" ] - else []) + [ + "contract_version"; + "metadata"; + "run_id"; + "base_currency"; + "initial_portfolio"; + "instruments"; + "venue_calendars"; + "risk"; + "execution"; + "financing"; + "settlement"; + "max_internal_events"; + "schedule"; + "slices"; + ] json in let* contract_version_json = field ~root fields "contract_version" in - let* common = common ~root ~contract_version fields in + let* common = common ~root fields in let* schedule = field ~root fields "schedule" in let* slices = field ~root fields "slices" in Ok { contract_version = contract_version_json; common; schedule; slices } -let stream_header ~contract_version json = +let stream_header json = let root = "$.payload" in - let calendar_fields = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6"; "5" ] - then [ "venue_calendars" ] - else [] - in - let initial_field = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then "initial_portfolio" - else "initial_cash" - in let* fields = object_fields ~json_path:root ~name:"scenario stream header payload" ~expected: - ([ - "metadata"; - "run_id"; - "base_currency"; - initial_field; - "instruments"; - "risk"; - "execution"; - "max_internal_events"; - ] - @ calendar_fields - @ (if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10" ] - then [ "financing" ] - else []) - @ - if List.mem contract_version [ "16"; "15"; "14"; "13"; "12"; "11" ] then - [ "settlement" ] - else []) + [ + "metadata"; + "run_id"; + "base_currency"; + "initial_portfolio"; + "instruments"; + "venue_calendars"; + "risk"; + "execution"; + "financing"; + "settlement"; + "max_internal_events"; + ] json in - common ~root ~contract_version fields + common ~root fields let stream_item json = let root = "$.payload" in diff --git a/lib/scenario_shape.mli b/lib/scenario_shape.mli index dda3d07..8b32093 100644 --- a/lib/scenario_shape.mli +++ b/lib/scenario_shape.mli @@ -27,8 +27,5 @@ type stream_item = { market_slice : Yojson.Safe.t; intents : Yojson.Safe.t } val error : json_path:string -> string -> error val batch : Yojson.Safe.t -> (batch, error) result - -val stream_header : - contract_version:string -> Yojson.Safe.t -> (common, error) result - +val stream_header : Yojson.Safe.t -> (common, error) result val stream_item : Yojson.Safe.t -> (stream_item, error) result diff --git a/lib/scenario_validation.ml b/lib/scenario_validation.ml index 06bed98..fa38b4d 100644 --- a/lib/scenario_validation.ml +++ b/lib/scenario_validation.ml @@ -45,18 +45,8 @@ let validate_venue_calendars ~root catalog venue_calendars = "venue calendars must cover every configured instrument exactly once" else Ok () -let header ~root ~contract_version ~base_currency ~initial_cash ~instruments - ~venue_calendars ~max_internal_events = - let* () = - if - List.mem contract_version - [ "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then Ok () - else - Account.create ~base_currency ~initial_cash - |> Result.map (fun _ -> ()) - |> at (child root "initial_cash") - in +let header ~root ~base_currency ~initial_cash ~instruments ~venue_calendars + ~max_internal_events = if instruments = [] then fail ~json_path:(child root "instruments") "scenario must define at least one instrument" @@ -68,15 +58,7 @@ let header ~root ~contract_version ~base_currency ~initial_cash ~instruments if Id.Instrument.Set.cardinal catalog <> List.length instruments then fail ~json_path:(child root "instruments") "instrument IDs must be unique" else - let* () = - if - List.mem contract_version - [ - "16"; "15"; "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6"; "5"; - ] - then validate_venue_calendars ~root catalog venue_calendars - else Ok () - in + let* () = validate_venue_calendars ~root catalog venue_calendars in let currencies = base_currency :: List.map @@ -89,25 +71,7 @@ let header ~root ~contract_version ~base_currency ~initial_cash ~instruments in if cash_currencies <> currencies then fail - ~json_path: - (child root - (if - List.mem contract_version - [ - "16"; - "15"; - "14"; - "13"; - "12"; - "11"; - "10"; - "9"; - "8"; - "7"; - "6"; - ] - then "initial_portfolio.cash" - else "initial_cash")) + ~json_path:(child root "initial_portfolio.cash") "initial cash must contain every scenario currency exactly once" else if max_internal_events <= 0 then fail diff --git a/lib/scenario_validation.mli b/lib/scenario_validation.mli index 3582d2d..63cf608 100644 --- a/lib/scenario_validation.mli +++ b/lib/scenario_validation.mli @@ -2,7 +2,6 @@ val header : root:string -> - contract_version:string -> base_currency:string -> initial_cash:(string * Scalar.Money.t) list -> instruments:Instrument.t list -> diff --git a/lib/strategy_process.ml b/lib/strategy_process.ml index a4ae59f..a6fe339 100644 --- a/lib/strategy_process.ml +++ b/lib/strategy_process.ml @@ -7,7 +7,6 @@ type t = { transcript : Strategy_transcript.t; effects : Boundary_effects.t; timeout : float; - protocol_version : string; mutable next_sequence : int64; } @@ -259,8 +258,7 @@ let exchange session ~stage ~expected_sequence request = in let* response = response in match - Strategy_protocol.response_of_string - ~protocol_version:session.protocol_version ~expected_sequence response + Strategy_protocol.response_of_string ~expected_sequence response |> Result.map_error (Diagnostic.annotate ~sequence:expected_sequence ~json_path:"$") with @@ -299,8 +297,7 @@ let on_event session context event = let* sequence = next_sequence session in let* response = exchange_at session ~stage:"strategy event" ~sequence (fun ~sequence -> - Strategy_protocol.event_message - ~protocol_version:session.protocol_version ~sequence context event) + Strategy_protocol.event_message ~sequence context event) in match response with | Strategy_protocol.Intents intents -> Ok intents @@ -317,8 +314,7 @@ let shutdown session = let* sequence = next_sequence session in let* response = exchange_at session ~stage:"strategy shutdown" ~sequence - (Strategy_protocol.shutdown_message_for - ~protocol_version:session.protocol_version) + Strategy_protocol.shutdown_message in match response with | Strategy_protocol.Stopped -> Ok () @@ -461,7 +457,6 @@ let run_session ~effects ~env ~command ~executable ~timeout ~transcript transcript; effects; timeout; - protocol_version = Strategy_protocol.protocol_version initialization; next_sequence = 1L; } in diff --git a/lib/strategy_protocol.ml b/lib/strategy_protocol.ml index 8cbc699..e08afdd 100644 --- a/lib/strategy_protocol.ml +++ b/lib/strategy_protocol.ml @@ -7,15 +7,14 @@ type initialization = { metadata : Yojson.Safe.t; run_id : Id.Run.t; base_currency : string; - initial_cash : (string * Scalar.Money.t) list; - initial_portfolio : Initial_portfolio.t option; + initial_portfolio : Initial_portfolio.t; instruments : Instrument.t list; venue_calendars : Venue_calendar.t list; risk : Risk.t; execution_model : Execution_model.t; execution : Execution.t; - financing : Financing.policy option; - settlement : Settlement.policy option; + financing : Financing.policy; + settlement : Settlement.policy; } type identity = { name : Id.Strategy.t; version : string option } @@ -41,10 +40,10 @@ let ratio value = string (Scalar.Ratio.to_decimal_string value) let timestamp value = string (Codec.ptime_to_string value) let instrument_id value = string (Id.Instrument.to_string value) -let message ~protocol_version ~sequence:message_sequence ~message_type payload = +let message ~sequence:message_sequence ~message_type payload = `Assoc [ - ("strategy_protocol_version", string protocol_version); + ("strategy_protocol_version", string version); ("strategy_sequence", sequence message_sequence); ("message_type", string message_type); ("payload", payload); @@ -102,10 +101,6 @@ let group_kind_to_string = function let nullable render = Option.fold ~none:`Null ~some:render -let modern_protocol protocol_version = - List.mem protocol_version - [ "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6"; "5" ] - let financing_to_yojson policy = `Assoc [ @@ -186,33 +181,19 @@ let group_to_yojson (group : Risk.group) = ] ); ] -let risk_to_yojson ~protocol_version risk = - if modern_protocol protocol_version then - `Assoc - [ - ("max_gross_exposure", money (Risk.max_gross_exposure risk)); - ("max_leverage", ratio (Risk.max_leverage risk)); - ("short_borrow_bps", `Int (Risk.short_borrow_bps risk)); - ( "instrument_policies", - `List - (List.map instrument_policy_to_yojson - (Risk.instrument_policies risk)) ); - ("groups", `List (List.map group_to_yojson (Risk.groups risk))); - ] - else - `Assoc - [ - ("max_order_quantity", quantity (Risk.max_order_quantity risk)); - ("max_long_position", quantity (Risk.max_long_position risk)); - ("max_short_position", quantity (Risk.max_short_position risk)); - ("max_gross_exposure", money (Risk.max_gross_exposure risk)); - ("max_leverage", ratio (Risk.max_leverage risk)); - ("initial_margin_bps", `Int (Risk.initial_margin_bps risk)); - ("maintenance_margin_bps", `Int (Risk.maintenance_margin_bps risk)); - ("short_borrow_bps", `Int (Risk.short_borrow_bps risk)); - ] +let risk_to_yojson risk = + `Assoc + [ + ("max_gross_exposure", money (Risk.max_gross_exposure risk)); + ("max_leverage", ratio (Risk.max_leverage risk)); + ( "instrument_policies", + `List + (List.map instrument_policy_to_yojson (Risk.instrument_policies risk)) + ); + ("groups", `List (List.map group_to_yojson (Risk.groups risk))); + ] -let execution_to_yojson ~protocol_version model execution = +let execution_to_yojson model execution = let fee_component_to_yojson component = let value = match Fee_schedule.component_basis component with @@ -253,149 +234,61 @@ let execution_to_yojson ~protocol_version model execution = (Fee_schedule.components schedule)) ); ] in - if - List.mem protocol_version [ "14"; "13"; "12"; "11" ] - && List.mem - (Execution_model.name model) - [ "completed_bar_next_open_v1"; "completed_bar_adverse_touch_v1" ] - then - let costs = Execution.cost_model execution |> Option.get in - `Assoc - [ - ("model", string (Execution_model.name model)); - ( "configuration", - `Assoc - [ - ("version", string "1"); - ("participation_bps", `Int (Execution.participation_bps execution)); - ( "fee_schedules", - `List - (List.map fee_schedule_to_yojson - (Execution.fee_schedules execution)) ); - ( "spread_model", - `Assoc - [ - ("model", string "fixed_half_spread_v1"); - ("half_spread_bps", `Int costs.half_spread_bps); - ] ); - ( "impact_model", - `Assoc - [ - ("model", string "linear_participation_v1"); - ("coefficient_bps", `Int costs.impact_coefficient_bps); - ( "missing_volume_policy", - string - (match costs.missing_volume_policy with - | Execution.Reject_missing_volume -> "reject" - | Zero_impact -> "zero_impact") ); - ] ); - ] ); - ] - else if - List.mem protocol_version [ "14"; "13"; "12" ] - && String.equal (Execution_model.name model) "quote_trade_v1" - then - `Assoc - [ - ("model", string (Execution_model.name model)); - ( "configuration", - `Assoc - [ - ("version", string "1"); - ("participation_bps", `Int (Execution.participation_bps execution)); - ( "fee_schedules", - `List - (List.map fee_schedule_to_yojson - (Execution.fee_schedules execution)) ); - ] ); - ] - else if - List.mem protocol_version [ "14"; "13" ] - && String.equal (Execution_model.name model) "order_book_v1" - then - `Assoc - [ - ("model", string (Execution_model.name model)); - ( "configuration", - `Assoc - [ - ("version", string "1"); - ("participation_bps", `Int (Execution.participation_bps execution)); - ( "fee_schedules", - `List - (List.map fee_schedule_to_yojson - (Execution.fee_schedules execution)) ); - ( "max_depth_levels", - `Int (Option.get (Execution.book_depth_limit execution)) ); - ] ); - ] - else if - List.mem protocol_version [ "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7" ] - then - `Assoc - [ - ("model", string (Execution_model.name model)); - ( "configuration", - `Assoc - [ - ("version", string "2"); - ("participation_bps", `Int (Execution.participation_bps execution)); - ( "fee_schedules", - `List - (List.map fee_schedule_to_yojson - (Execution.fee_schedules execution)) ); - ] ); - ] - else if modern_protocol protocol_version then - `Assoc - [ - ("model", string (Execution_model.name model)); - ( "configuration", - `Assoc - [ - ("version", string "1"); - ("participation_bps", `Int (Execution.participation_bps execution)); - ("fixed_fee", money (Execution.fixed_fee execution)); - ("fee_bps", `Int (Execution.fee_bps execution)); - ] ); - ] - else - `Assoc - [ - ("model", string (Execution_model.name model)); - ("participation_bps", `Int (Execution.participation_bps execution)); - ("fixed_fee", money (Execution.fixed_fee execution)); - ("fee_bps", `Int (Execution.fee_bps execution)); - ] - -let protocol_version initialization = - match initialization.scenario_contract_version with - | "16" -> "14" - | "15" -> "13" - | "14" -> "12" - | "13" -> "11" - | "12" -> "10" - | "11" -> "9" - | "10" -> "8" - | "9" -> "7" - | "8" -> "6" - | "7" -> "5" - | "6" -> "4" - | _ -> "3" + let configuration = + [ + ("version", string "1"); + ("participation_bps", `Int (Execution.participation_bps execution)); + ( "fee_schedules", + `List + (List.map fee_schedule_to_yojson (Execution.fee_schedules execution)) + ); + ] + in + let configuration = + match Execution_model.name model with + | "completed_bar_next_open_v1" | "completed_bar_adverse_touch_v1" -> + let costs = Execution.cost_model execution |> Option.get in + configuration + @ [ + ( "spread_model", + `Assoc + [ + ("model", string "fixed_half_spread_v1"); + ("half_spread_bps", `Int costs.half_spread_bps); + ] ); + ( "impact_model", + `Assoc + [ + ("model", string "linear_participation_v1"); + ("coefficient_bps", `Int costs.impact_coefficient_bps); + ( "missing_volume_policy", + string + (match costs.missing_volume_policy with + | Execution.Reject_missing_volume -> "reject" + | Zero_impact -> "zero_impact") ); + ] ); + ] + | "order_book_v1" -> + configuration + @ [ + ( "max_depth_levels", + `Int (Option.get (Execution.book_depth_limit execution)) ); + ] + | _ -> configuration + in + `Assoc + [ + ("model", string (Execution_model.name model)); + ("configuration", `Assoc configuration); + ] let initialize_message ~sequence:message_sequence initialization = - let protocol_version = protocol_version initialization in let instruments = List.sort (fun left right -> Id.Instrument.compare left.Instrument.id right.Instrument.id) initialization.instruments in - let initial_cash = - List.sort - (fun (left, _) (right, _) -> String.compare left right) - initialization.initial_cash - in let venue_calendars = List.sort (fun left right -> @@ -410,111 +303,48 @@ let initialize_message ~sequence:message_sequence initialization = ("scenario_sha256", string initialization.scenario_sha256); ("run_id", string (Id.Run.to_string initialization.run_id)); ("base_currency", string initialization.base_currency); - ("initial_cash", `List (List.map cash_balance_to_yojson initial_cash)); + ( "initial_portfolio", + Codec.initial_portfolio_to_yojson initialization.initial_portfolio ); + ( "venue_calendars", + `List (List.map venue_calendar_to_yojson venue_calendars) ); + ("financing", financing_to_yojson initialization.financing); + ("settlement", settlement_to_yojson initialization.settlement); ("instruments", `List (List.map instrument_to_yojson instruments)); - ("risk", risk_to_yojson ~protocol_version initialization.risk); + ("risk", risk_to_yojson initialization.risk); ( "execution", - execution_to_yojson ~protocol_version initialization.execution_model + execution_to_yojson initialization.execution_model initialization.execution ); ("metadata", initialization.metadata); ] in - let fields = - if - List.mem protocol_version - [ "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then - let initial_portfolio = - Option.fold ~none:`Null ~some:Codec.initial_portfolio_to_yojson - initialization.initial_portfolio - in - List.concat - [ - List.take 6 fields; - [ - ("initial_portfolio", initial_portfolio); - ( "venue_calendars", - `List (List.map venue_calendar_to_yojson venue_calendars) ); - ]; - (if - List.mem protocol_version - [ "14"; "13"; "12"; "11"; "10"; "9"; "8" ] - then - [ - ( "financing", - Option.fold ~none:`Null ~some:financing_to_yojson - initialization.financing ); - ] - else []); - (if List.mem protocol_version [ "14"; "13"; "12"; "11"; "10"; "9" ] - then - [ - ( "settlement", - Option.fold ~none:`Null ~some:settlement_to_yojson - initialization.settlement ); - ] - else []); - List.drop 6 fields; - ] - else if modern_protocol protocol_version then - let initial_portfolio = - Option.fold ~none:`Null ~some:Codec.initial_portfolio_to_yojson - initialization.initial_portfolio - in - List.concat - [ - List.take 6 fields; - [ ("initial_portfolio", initial_portfolio) ]; - List.drop 6 fields; - ] - else fields - in - message ~protocol_version ~sequence:message_sequence - ~message_type:"initialize" (`Assoc fields) + message ~sequence:message_sequence ~message_type:"initialize" (`Assoc fields) -let cash_attribution_to_yojson ~protocol_version - (balance : Account.cash_attribution) = +let cash_attribution_to_yojson (balance : Account.cash_attribution) = `Assoc - ([ - ("currency", string balance.currency); - ("amount", money balance.amount); - ("fx_rate", price balance.fx_rate); - ("base_value", money balance.base_value); - ] - @ (if List.mem protocol_version [ "14"; "13"; "12"; "11"; "10"; "9"; "8" ] - then - [ - ("interest", money balance.interest); - ("base_interest", money balance.base_interest); - ] - else []) - @ - if List.mem protocol_version [ "14"; "13"; "12"; "11"; "10"; "9" ] then - [ - ("settled_amount", money balance.settled_amount); - ("unsettled_amount", money balance.unsettled_amount); - ("base_settled_value", money balance.base_settled_value); - ("base_unsettled_value", money balance.base_unsettled_value); - ] - else []) + [ + ("currency", string balance.currency); + ("amount", money balance.amount); + ("fx_rate", price balance.fx_rate); + ("base_value", money balance.base_value); + ("interest", money balance.interest); + ("base_interest", money balance.base_interest); + ("settled_amount", money balance.settled_amount); + ("unsettled_amount", money balance.unsettled_amount); + ("base_settled_value", money balance.base_settled_value); + ("base_unsettled_value", money balance.base_unsettled_value); + ] -let marked_position_to_yojson ~protocol_version - (position : Strategy.marked_position) = +let marked_position_to_yojson (position : Strategy.marked_position) = `Assoc - ([ - ("instrument_id", instrument_id position.instrument_id); - ("quantity", quantity position.quantity); - ("mark", price position.mark); - ("base_market_value", money position.base_market_value); - ("weight", Option.fold ~none:`Null ~some:weight position.weight); - ] - @ - if List.mem protocol_version [ "14"; "13"; "12"; "11"; "10"; "9" ] then - [ - ("settled_quantity", quantity position.settled_quantity); - ("unsettled_quantity", quantity position.unsettled_quantity); - ] - else []) + [ + ("instrument_id", instrument_id position.instrument_id); + ("quantity", quantity position.quantity); + ("mark", price position.mark); + ("base_market_value", money position.base_market_value); + ("weight", Option.fold ~none:`Null ~some:weight position.weight); + ("settled_quantity", quantity position.settled_quantity); + ("unsettled_quantity", quantity position.unsettled_quantity); + ] let group_exposure_to_yojson (exposure : Risk.group_exposure) = `Assoc @@ -528,7 +358,7 @@ let group_exposure_to_yojson (exposure : Risk.group_exposure) = Option.fold ~none:`Null ~some:weight exposure.concentration ); ] -let context_to_yojson ~protocol_version context = +let context_to_yojson context = let portfolio = Strategy.portfolio context in let cash_balances = List.sort @@ -566,103 +396,50 @@ let context_to_yojson ~protocol_version context = ("weights_available", `Bool (Option.is_some portfolio.cash_weight)); ("cash_weight", Option.fold ~none:`Null ~some:weight portfolio.cash_weight); ( "cash_balances", - `List - (List.map - (cash_attribution_to_yojson ~protocol_version) - cash_balances) ); - ( "positions", - `List (List.map (marked_position_to_yojson ~protocol_version) positions) - ); + `List (List.map cash_attribution_to_yojson cash_balances) ); + ("positions", `List (List.map marked_position_to_yojson positions)); + ( "group_exposures", + `List (List.map group_exposure_to_yojson portfolio.group_exposures) ); ] in - let portfolio_fields = - if modern_protocol protocol_version then - portfolio_fields - @ [ - ( "group_exposures", - `List (List.map group_exposure_to_yojson portfolio.group_exposures) - ); - ] - else portfolio_fields - in `Assoc [ ("now", timestamp (Strategy.now context)); ("portfolio", `Assoc portfolio_fields); - ( "working_orders", - `List - (List.map - (if - List.mem protocol_version - [ "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then Codec.order_to_yojson_v8 - else Codec.order_to_yojson) - working_orders) ); + ("working_orders", `List (List.map Codec.order_to_yojson working_orders)); ("latest_bars", `List (List.map Codec.bar_to_yojson latest_bars)); ] -let event_to_yojson ~protocol_version = function +let event_to_yojson = function | Strategy.Market_slice_closed market_slice -> `Assoc [ ("type", string "market_slice_closed"); - ( "market_slice", - if String.equal protocol_version "14" then - Codec.market_slice_to_yojson_v16 market_slice - else if String.equal protocol_version "13" then - Codec.market_slice_to_yojson_v15 market_slice - else if String.equal protocol_version "12" then - Codec.market_slice_to_yojson_v14 market_slice - else if String.equal protocol_version "11" then - Codec.market_slice_to_yojson_v13 market_slice - else if String.equal protocol_version "10" then - Codec.market_slice_to_yojson_v12 market_slice - else if String.equal protocol_version "9" then - Codec.market_slice_to_yojson_v11 market_slice - else if String.equal protocol_version "8" then - Codec.market_slice_to_yojson_v10 market_slice - else Codec.market_slice_to_yojson market_slice ); + ("market_slice", Codec.market_slice_to_yojson market_slice); ] | Strategy.Fill_received fill -> `Assoc [ - ("type", string "fill_received"); - ( "fill", - if - List.mem protocol_version - [ "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7" ] - then Codec.fill_to_yojson_v9 fill - else Codec.fill_to_yojson fill ); + ("type", string "fill_received"); ("fill", Codec.fill_to_yojson fill); ] | Strategy.Order_updated order -> `Assoc [ ("type", string "order_updated"); - ( "order", - if - List.mem protocol_version - [ "14"; "13"; "12"; "11"; "10"; "9"; "8"; "7"; "6" ] - then Codec.order_to_yojson_v8 order - else Codec.order_to_yojson order ); + ("order", Codec.order_to_yojson order); ] | Strategy.Intent_rejected reason -> `Assoc [ ("type", string "intent_rejected"); ("reason", string reason) ] -let event_message ?(protocol_version = version) ~sequence:message_sequence - context event = - message ~protocol_version ~sequence:message_sequence ~message_type:"event" +let event_message ~sequence:message_sequence context event = + message ~sequence:message_sequence ~message_type:"event" (`Assoc [ - ("context", context_to_yojson ~protocol_version context); - ("event", event_to_yojson ~protocol_version event); + ("context", context_to_yojson context); ("event", event_to_yojson event); ]) -let shutdown_message_for ~protocol_version ~sequence:message_sequence = - message ~protocol_version ~sequence:message_sequence ~message_type:"shutdown" - (`Assoc []) - let shutdown_message ~sequence = - shutdown_message_for ~protocol_version:version ~sequence + message ~sequence ~message_type:"shutdown" (`Assoc []) let object_fields ~name ~expected = function | `Assoc fields -> @@ -712,7 +489,7 @@ let parse_ready_payload json = let* version = optional_string ~name:"strategy_version" version_json in Ok (Ready { name; version }) -let parse_intents_payload ~protocol_version json = +let parse_intents_payload json = let* fields = object_fields ~name:"strategy intents payload" ~expected:[ "intents" ] json in @@ -727,19 +504,7 @@ let parse_intents_payload ~protocol_version json = (fun result value -> let* intents = result in let* intent = - Scenario.intent_of_yojson - ~contract_version: - (if String.equal protocol_version "14" then "16" - else if List.mem protocol_version [ "14"; "13" ] then "15" - else if String.equal protocol_version "12" then "14" - else if String.equal protocol_version "11" then "13" - else if String.equal protocol_version "10" then "12" - else if String.equal protocol_version "9" then "11" - else if String.equal protocol_version "8" then "10" - else if String.equal protocol_version "7" then "9" - else if String.equal protocol_version "6" then "8" - else "7") - value + Scenario.intent_of_yojson value |> Result.map_error Diagnostic.to_human in Ok (intent :: intents)) @@ -751,7 +516,7 @@ let parse_stopped_payload json = let* _ = object_fields ~name:"strategy stopped payload" ~expected:[] json in Ok Stopped -let response_of_yojson_result ~protocol_version ~expected_sequence json = +let response_of_yojson_result ~expected_sequence json = let* fields = object_fields ~name:"strategy response" ~expected: @@ -767,7 +532,7 @@ let response_of_yojson_result ~protocol_version ~expected_sequence json = let* supplied_version = required_string ~name:"strategy_protocol_version" version_json in - if not (String.equal supplied_version protocol_version) then + if not (String.equal supplied_version version) then Error ("unsupported strategy protocol version: " ^ supplied_version) else let* sequence_json = field fields "strategy_sequence" in @@ -787,20 +552,19 @@ let response_of_yojson_result ~protocol_version ~expected_sequence json = let* payload = field fields "payload" in match message_type with | "ready" -> parse_ready_payload payload - | "intents" -> parse_intents_payload ~protocol_version payload + | "intents" -> parse_intents_payload payload | "stopped" -> parse_stopped_payload payload | "error" -> parse_error_payload payload |> Result.map (fun message -> Failed message) | value -> Error ("unsupported strategy response type: " ^ value) -let response_of_yojson ?(protocol_version = version) ~expected_sequence json = +let response_of_yojson ~expected_sequence json = let json_path = match json with | `Assoc fields -> ( match List.assoc_opt "strategy_protocol_version" fields with - | Some (`String supplied) - when not (String.equal supplied protocol_version) -> + | Some (`String supplied) when not (String.equal supplied version) -> "$.strategy_protocol_version" | _ -> ( match List.assoc_opt "strategy_sequence" fields with @@ -832,14 +596,13 @@ let response_of_yojson ?(protocol_version = version) ~expected_sequence json = (Printf.sprintf "intent count is %d; limit is %d" observed Resource_limits.intents_per_batch)) | _ -> - response_of_yojson_result ~protocol_version ~expected_sequence json + response_of_yojson_result ~expected_sequence json |> Result.map_error (fun message -> Diagnostic.make ~code:Diagnostic.Strategy_protocol ~phase:Diagnostic.Strategy ~sequence:expected_sequence ~json_path message) -let response_of_string ?(protocol_version = version) ~expected_sequence document - = +let response_of_string ~expected_sequence document = if String.length document > max_message_bytes then Error (Diagnostic.make ~code:Diagnostic.Resource_limit @@ -849,7 +612,7 @@ let response_of_string ?(protocol_version = version) ~expected_sequence document else try let json = Yojson.Safe.from_string document in - response_of_yojson ~protocol_version ~expected_sequence json + response_of_yojson ~expected_sequence json |> Result.map (fun response -> (response, json)) with Yojson.Json_error message as exception_ -> Error @@ -863,17 +626,9 @@ let direction_to_string = function | Strategy_to_engine -> "strategy_to_engine" let transcript_record ~transcript_sequence ~direction ~message = - let protocol_version = - match message with - | `Assoc fields -> ( - match List.assoc_opt "strategy_protocol_version" fields with - | Some (`String value) -> value - | _ -> version) - | _ -> version - in `Assoc [ - ("strategy_protocol_version", string protocol_version); + ("strategy_protocol_version", string version); ("transcript_sequence", sequence transcript_sequence); ("direction", string (direction_to_string direction)); ("message", message); diff --git a/lib/strategy_protocol.mli b/lib/strategy_protocol.mli index ab15974..54cc26f 100644 --- a/lib/strategy_protocol.mli +++ b/lib/strategy_protocol.mli @@ -9,15 +9,14 @@ type initialization = { metadata : Yojson.Safe.t; run_id : Id.Run.t; base_currency : string; - initial_cash : (string * Scalar.Money.t) list; - initial_portfolio : Initial_portfolio.t option; + initial_portfolio : Initial_portfolio.t; instruments : Instrument.t list; venue_calendars : Venue_calendar.t list; risk : Risk.t; execution_model : Execution_model.t; execution : Execution.t; - financing : Financing.policy option; - settlement : Settlement.policy option; + financing : Financing.policy; + settlement : Settlement.policy; } type identity = private { name : Id.Strategy.t; version : string option } @@ -30,29 +29,17 @@ type response = type direction = Engine_to_strategy | Strategy_to_engine -val protocol_version : initialization -> string val initialize_message : sequence:int64 -> initialization -> Yojson.Safe.t val event_message : - ?protocol_version:string -> - sequence:int64 -> - Strategy.context -> - Strategy.event -> - Yojson.Safe.t - -val shutdown_message_for : - protocol_version:string -> sequence:int64 -> Yojson.Safe.t + sequence:int64 -> Strategy.context -> Strategy.event -> Yojson.Safe.t val shutdown_message : sequence:int64 -> Yojson.Safe.t val response_of_yojson : - ?protocol_version:string -> - expected_sequence:int64 -> - Yojson.Safe.t -> - (response, Diagnostic.t) result + expected_sequence:int64 -> Yojson.Safe.t -> (response, Diagnostic.t) result val response_of_string : - ?protocol_version:string -> expected_sequence:int64 -> string -> (response * Yojson.Safe.t, Diagnostic.t) result diff --git a/mkdocs.yml b/mkdocs.yml index ec574e8..a5b8e0f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,5 +1,5 @@ site_name: Trading Engine -site_description: Deterministic execution, replay contracts, and OCaml API reference +site_description: Deterministic OCaml trading replay engine site_url: https://fallblu.github.io/trading-engine/ repo_url: https://github.com/fallblu/trading-engine repo_name: fallblu/trading-engine @@ -31,18 +31,9 @@ nav: - Diagnostics: - Current v1: contracts/diagnostic/v1/README.md - Scenario and journal: - - Current v16: contracts/v16/README.md - - Transitional v5: contracts/v5/README.md - - Transitional v4: contracts/v4/README.md - - Transitional v3: contracts/v3/README.md - - Frozen v2: contracts/v2/README.md - - Historical v1: contracts/v1/README.md + - Current v1: contracts/v1/README.md - External strategy: - - Current v14: contracts/strategy/v14/README.md - - Historical v13: contracts/strategy/v13/README.md - - Historical v3: contracts/strategy/v3/README.md - - Historical v2: contracts/strategy/v2/README.md - - Historical v1: contracts/strategy/v1/README.md + - Current v1: contracts/strategy/v1/README.md - API reference: docs/api-reference.md - Engineering: - Continuous integration: docs/continuous-integration.md diff --git a/scripts/check-deterministic-journals b/scripts/check-deterministic-journals index b05c7df..55304ec 100755 --- a/scripts/check-deterministic-journals +++ b/scripts/check-deterministic-journals @@ -16,21 +16,18 @@ export TZ=UTC compare_journal() { name=$1 - scenario=$2 - expected=$3 actual="$temporary_root/$name.journal.jsonl" - standard_output="$temporary_root/$name.stdout" - standard_error="$temporary_root/$name.stderr" "$engine" \ - --input "$repository_root/$scenario" \ + --input "$repository_root/contracts/v1/fixtures/$name.scenario.json" \ --journal "$actual" \ - >"$standard_output" \ - 2>"$standard_error" + >"$temporary_root/$name.stdout" \ + 2>"$temporary_root/$name.stderr" - if ! cmp -s "$repository_root/$expected" "$actual"; then + expected="$repository_root/contracts/v1/fixtures/$name.journal.jsonl" + if ! cmp -s "$expected" "$actual"; then printf '%s\n' "error: $name journal differs from its canonical bytes" >&2 - diff -u "$repository_root/$expected" "$actual" >&2 || true + diff -u "$expected" "$actual" >&2 || true exit 1 fi @@ -38,111 +35,7 @@ compare_journal() { printf '%s\n' "$name: exact journal match ($byte_count bytes)" } -compare_journal \ - v3-demo \ - contracts/v3/fixtures/demo.scenario.json \ - contracts/v3/fixtures/demo.journal.jsonl -compare_journal \ - v5-demo \ - contracts/v5/fixtures/demo.scenario.json \ - contracts/v5/fixtures/demo.journal.jsonl -compare_journal \ - v5-fill-clipped \ - contracts/v5/fixtures/fill-clipped.scenario.json \ - contracts/v5/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v8-demo \ - contracts/v8/fixtures/demo.scenario.json \ - contracts/v8/fixtures/demo.journal.jsonl -compare_journal \ - v8-fill-clipped \ - contracts/v8/fixtures/fill-clipped.scenario.json \ - contracts/v8/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v9-demo \ - contracts/v9/fixtures/demo.scenario.json \ - contracts/v9/fixtures/demo.journal.jsonl -compare_journal \ - v9-fill-clipped \ - contracts/v9/fixtures/fill-clipped.scenario.json \ - contracts/v9/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v10-demo \ - contracts/v10/fixtures/demo.scenario.json \ - contracts/v10/fixtures/demo.journal.jsonl -compare_journal \ - v10-fill-clipped \ - contracts/v10/fixtures/fill-clipped.scenario.json \ - contracts/v10/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v11-demo \ - contracts/v11/fixtures/demo.scenario.json \ - contracts/v11/fixtures/demo.journal.jsonl -compare_journal \ - v11-fill-clipped \ - contracts/v11/fixtures/fill-clipped.scenario.json \ - contracts/v11/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v12-demo \ - contracts/v12/fixtures/demo.scenario.json \ - contracts/v12/fixtures/demo.journal.jsonl -compare_journal \ - v12-fill-clipped \ - contracts/v12/fixtures/fill-clipped.scenario.json \ - contracts/v12/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v13-demo \ - contracts/v13/fixtures/demo.scenario.json \ - contracts/v13/fixtures/demo.journal.jsonl -compare_journal \ - v13-fill-clipped \ - contracts/v13/fixtures/fill-clipped.scenario.json \ - contracts/v13/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v14-demo \ - contracts/v14/fixtures/demo.scenario.json \ - contracts/v14/fixtures/demo.journal.jsonl -compare_journal \ - v14-fill-clipped \ - contracts/v14/fixtures/fill-clipped.scenario.json \ - contracts/v14/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v14-quote-trade \ - contracts/v14/fixtures/quote-trade.scenario.json \ - contracts/v14/fixtures/quote-trade.journal.jsonl -compare_journal \ - v15-demo \ - contracts/v15/fixtures/demo.scenario.json \ - contracts/v15/fixtures/demo.journal.jsonl -compare_journal \ - v15-fill-clipped \ - contracts/v15/fixtures/fill-clipped.scenario.json \ - contracts/v15/fixtures/fill-clipped.journal.jsonl -compare_journal \ - v15-quote-trade \ - contracts/v15/fixtures/quote-trade.scenario.json \ - contracts/v15/fixtures/quote-trade.journal.jsonl -compare_journal \ - v15-order-book \ - contracts/v15/fixtures/order-book.scenario.json \ - contracts/v15/fixtures/order-book.journal.jsonl - -compare_journal \ - v16-demo \ - contracts/v16/fixtures/demo.scenario.json \ - contracts/v16/fixtures/demo.journal.jsonl - -compare_journal \ - v16-fill-clipped \ - contracts/v16/fixtures/fill-clipped.scenario.json \ - contracts/v16/fixtures/fill-clipped.journal.jsonl - -compare_journal \ - v16-quote-trade \ - contracts/v16/fixtures/quote-trade.scenario.json \ - contracts/v16/fixtures/quote-trade.journal.jsonl - -compare_journal \ - v16-order-book \ - contracts/v16/fixtures/order-book.scenario.json \ - contracts/v16/fixtures/order-book.journal.jsonl +compare_journal demo +compare_journal fill-clipped +compare_journal quote-trade +compare_journal order-book diff --git a/scripts/check-documentation.py b/scripts/check-documentation.py index 5ae4a7b..dfe9d50 100644 --- a/scripts/check-documentation.py +++ b/scripts/check-documentation.py @@ -27,15 +27,7 @@ "SECURITY.md", "contracts/conformance/README.md", "contracts/cli/v1/README.md", - "contracts/v16/README.md", - "contracts/v5/README.md", - "contracts/v4/README.md", - "contracts/v3/README.md", - "contracts/v2/README.md", "contracts/v1/README.md", - "contracts/strategy/v14/README.md", - "contracts/strategy/v3/README.md", - "contracts/strategy/v2/README.md", "contracts/strategy/v1/README.md", "docs/api-reference.md", "docs/continuous-integration.md", @@ -166,9 +158,6 @@ def site_failures(root: Path = REPOSITORY_ROOT) -> list[str]: site / "docs" / "repository-governance" / "index.html", site / "SECURITY" / "index.html", site / "docs" / "api-reference" / "index.html", - site / "contracts" / "v4" / "index.html", - site / "contracts" / "v3" / "index.html", - site / "contracts" / "v2" / "index.html", site / "contracts" / "v1" / "index.html", site / "api" / "trading_engine" / "Trading_engine" / "index.html", ) diff --git a/scripts/release_artifacts.py b/scripts/release_artifacts.py index aceeddc..b967524 100644 --- a/scripts/release_artifacts.py +++ b/scripts/release_artifacts.py @@ -376,8 +376,8 @@ def verify_release( ( "bin/trading-engine", "lib/trading_engine/opam", - "share/trading_engine/contracts/v16/scenario.schema.json", - "share/trading_engine/contracts/v16/fixtures/demo.scenario.json", + "share/trading_engine/contracts/v1/scenario.schema.json", + "share/trading_engine/contracts/v1/fixtures/demo.scenario.json", "share/trading_engine/contracts/cli/v1/result.schema.json", "doc/trading_engine/README.md", ), @@ -389,7 +389,7 @@ def verify_release( ( "trading_engine.opam", "contracts/v1/scenario.schema.json", - "contracts/v16/fixtures/demo.scenario.json", + "contracts/v1/fixtures/demo.scenario.json", "contracts/cli/v1/result.schema.json", "docs/architecture.md", ".github/workflows/release-candidate.yml", @@ -402,8 +402,8 @@ def verify_release( ( "contracts/conformance/manifest.json", "contracts/v1/scenario.schema.json", - "contracts/v16/fixtures/demo.scenario.json", - "contracts/strategy/v14/message.schema.json", + "contracts/v1/fixtures/demo.scenario.json", + "contracts/strategy/v1/message.schema.json", "contracts/cli/v1/result.schema.json", ), epoch, @@ -415,7 +415,7 @@ def verify_release( "index.html", "docs/architecture/index.html", "contracts/v1/index.html", - "contracts/v16/scenario.schema.json", + "contracts/v1/scenario.schema.json", "contracts/cli/v1/result.schema.json", "api/trading_engine/Trading_engine/index.html", ), diff --git a/test/cli.t b/test/cli.t index 22bbca7..87cbaf6 100644 --- a/test/cli.t +++ b/test/cli.t @@ -2,27 +2,27 @@ 1.0.0 $ ../bin/main.exe --capabilities - {"engine_version":"1.0.0","scenario_contract_versions":["16","15","14","13","12","11","10","9","8","7","6","5","4","3"],"journal_contract_versions":["16","15","14","13","12","11","10","9","8","7","6","5","4","3"],"scenario_formats":["json","jsonl"],"journal_formats":["jsonl"],"execution_models":["completed_bar_v1","completed_bar_next_open_v1","completed_bar_adverse_touch_v1","quote_trade_v1","order_book_v1"],"execution_model_contracts":[{"name":"completed_bar_v1","configuration_versions":["2","1"],"scenario_contract_versions":["16","15","14","13","12","11","10","9","8","7","6","5","4","3"],"required_fields":["version","participation_bps","fee_schedules"],"configuration_required_fields":{"2":["version","participation_bps","fee_schedules"],"1":["version","participation_bps","fixed_fee","fee_bps"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["completed_ohlcv_bars"],"limits":{"participation_bps":{"minimum":0,"maximum":10000},"fee_bps":{"minimum":0,"maximum":10000},"fixed_fee":{"minimum":"0","unit":"money"}}},{"name":"completed_bar_next_open_v1","configuration_versions":["1"],"scenario_contract_versions":["16","15","14","13"],"required_fields":["version","participation_bps","fee_schedules","spread_model","impact_model"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules","spread_model","impact_model"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["completed_ohlcv_bars","bar_volume_for_linear_impact"],"limits":{"participation_bps":{"minimum":0,"maximum":10000},"half_spread_bps":{"minimum":0,"maximum":10000},"impact_coefficient_bps":{"minimum":0,"maximum":10000}}},{"name":"completed_bar_adverse_touch_v1","configuration_versions":["1"],"scenario_contract_versions":["16","15","14","13"],"required_fields":["version","participation_bps","fee_schedules","spread_model","impact_model"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules","spread_model","impact_model"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["completed_ohlcv_bars","bar_volume_for_linear_impact"],"limits":{"participation_bps":{"minimum":0,"maximum":10000},"half_spread_bps":{"minimum":0,"maximum":10000},"impact_coefficient_bps":{"minimum":0,"maximum":10000}}},{"name":"quote_trade_v1","configuration_versions":["1"],"scenario_contract_versions":["16","15","14"],"required_fields":["version","participation_bps","fee_schedules"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["causally_ordered_bid_ask_quotes","aggressor_classified_trades_for_passive_fills","completed_bars_for_valuation"],"limits":{"participation_bps":{"minimum":0,"maximum":10000}}},{"name":"order_book_v1","configuration_versions":["1"],"scenario_contract_versions":["16","15"],"required_fields":["version","participation_bps","fee_schedules","max_depth_levels"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules","max_depth_levels"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["slice_open_level_two_snapshot","contiguous_absolute_level_updates","aggressor_classified_depth_consuming_trades","completed_bars_for_valuation"],"limits":{"participation_bps":{"minimum":0,"maximum":10000},"max_depth_levels":{"minimum":1,"maximum":1024}}}],"strategy_protocol_versions":["14","13","12","11","10","9","8","7","6","5","4","3"],"resource_limits":{"version":"1","scenario_record_bytes":1048576,"strategy_message_bytes":1048576,"internal_events":100000,"catalog_instruments":4096,"intents_per_batch":4096,"artifact_record_bytes":2097152}} + {"engine_version":"1.0.0","scenario_contract_versions":["1"],"journal_contract_versions":["1"],"scenario_formats":["json","jsonl"],"journal_formats":["jsonl"],"execution_models":["completed_bar_v1","completed_bar_next_open_v1","completed_bar_adverse_touch_v1","quote_trade_v1","order_book_v1"],"execution_model_contracts":[{"name":"completed_bar_v1","configuration_versions":["1"],"scenario_contract_versions":["1"],"required_fields":["version","participation_bps","fee_schedules"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["completed_ohlcv_bars"],"limits":{"participation_bps":{"minimum":0,"maximum":10000}}},{"name":"completed_bar_next_open_v1","configuration_versions":["1"],"scenario_contract_versions":["1"],"required_fields":["version","participation_bps","fee_schedules","spread_model","impact_model"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules","spread_model","impact_model"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["completed_ohlcv_bars","bar_volume_for_linear_impact"],"limits":{"participation_bps":{"minimum":0,"maximum":10000},"half_spread_bps":{"minimum":0,"maximum":10000},"impact_coefficient_bps":{"minimum":0,"maximum":10000}}},{"name":"completed_bar_adverse_touch_v1","configuration_versions":["1"],"scenario_contract_versions":["1"],"required_fields":["version","participation_bps","fee_schedules","spread_model","impact_model"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules","spread_model","impact_model"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["completed_ohlcv_bars","bar_volume_for_linear_impact"],"limits":{"participation_bps":{"minimum":0,"maximum":10000},"half_spread_bps":{"minimum":0,"maximum":10000},"impact_coefficient_bps":{"minimum":0,"maximum":10000}}},{"name":"quote_trade_v1","configuration_versions":["1"],"scenario_contract_versions":["1"],"required_fields":["version","participation_bps","fee_schedules"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["causally_ordered_bid_ask_quotes","aggressor_classified_trades_for_passive_fills","completed_bars_for_valuation"],"limits":{"participation_bps":{"minimum":0,"maximum":10000}}},{"name":"order_book_v1","configuration_versions":["1"],"scenario_contract_versions":["1"],"required_fields":["version","participation_bps","fee_schedules","max_depth_levels"],"configuration_required_fields":{"1":["version","participation_bps","fee_schedules","max_depth_levels"]},"supported_order_types":["market","limit","stop","stop_limit"],"data_requirements":["slice_open_level_two_snapshot","contiguous_absolute_level_updates","aggressor_classified_depth_consuming_trades","completed_bars_for_valuation"],"limits":{"participation_bps":{"minimum":0,"maximum":10000},"max_depth_levels":{"minimum":1,"maximum":1024}}}],"strategy_protocol_versions":["1"],"resource_limits":{"version":"1","scenario_record_bytes":1048576,"strategy_message_bytes":1048576,"internal_events":100000,"catalog_instruments":4096,"intents_per_batch":4096,"artifact_record_bytes":2097152}} - $ ../bin/main.exe --validate-only --input ../contracts/v8/fixtures/demo.scenario.json - valid run=demo instruments=1 schedule=2 slices=4 scenario_sha256=85f7c99e0666159579c79256b3d0dc5f9c328e1275b79465fe1d4c93883e68f1 + $ ../bin/main.exe --validate-only --input ../contracts/v1/fixtures/demo.scenario.json + valid run=demo instruments=1 schedule=2 slices=4 scenario_sha256=e2227af76072fab8151c3e1bd86f401293d16a736e32040efdaf8761cd397574 - $ ../bin/main.exe --validate-only --input-format jsonl --input ../contracts/v8/fixtures/demo.scenario.jsonl - valid run=demo instruments=1 schedule=2 slices=4 scenario_sha256=786f38d8bd10faac03b6b15c7aa8ae0a867eedc609ca6eaa75cfd93ae3ffdcae + $ ../bin/main.exe --validate-only --input-format jsonl --input ../contracts/v1/fixtures/demo.scenario.jsonl + valid run=demo instruments=1 schedule=2 slices=4 scenario_sha256=cb5cf2c600829b54be763809138137fe53ed61fd41f50c5b4d98cb27ee528eb4 - $ ../bin/main.exe --output-format json --validate-only --input ../contracts/v8/fixtures/demo.scenario.json | python3 -c 'import json, sys; result=json.load(sys.stdin); print(result["result_version"], result["status"], result["operation"], result["run_id"]); print(result["counts"]["instruments"], result["counts"]["slices"], result["counts"]["audits"], result["valuation"]["equity"]); print(result["hashes"]["journal_sha256"], result["artifacts"]["journal"])' + $ ../bin/main.exe --output-format json --validate-only --input ../contracts/v1/fixtures/demo.scenario.json | python3 -c 'import json, sys; result=json.load(sys.stdin); print(result["result_version"], result["status"], result["operation"], result["run_id"]); print(result["counts"]["instruments"], result["counts"]["slices"], result["counts"]["audits"], result["valuation"]["equity"]); print(result["hashes"]["journal_sha256"], result["artifacts"]["journal"])' 1 success validate demo - 1 4 22 10111.65392 + 1 4 34 10111.979929 None None - $ ../bin/main.exe --input-format jsonl --input ../contracts/v8/fixtures/demo.scenario.jsonl --journal streamed.journal.jsonl --durable-artifacts - run=demo audits=22 orders=3 active=0 filled=2 rejected=0 - cash=9846.65392 equity=10111.65392 gross=265 realized=18.965682 unrealized=7.688238 fees=3.16608 + $ ../bin/main.exe --input-format jsonl --input ../contracts/v1/fixtures/demo.scenario.jsonl --journal streamed.journal.jsonl --durable-artifacts + run=demo audits=34 orders=3 active=0 filled=2 rejected=0 + cash=9846.979929 equity=10111.979929 gross=265 realized=19.134573 unrealized=7.845356 fees=3.157896 journal=streamed.journal.jsonl $ wc -l < streamed.journal.jsonl - 22 + 34 - $ head -n 5 ../contracts/v8/fixtures/demo.scenario.jsonl > truncated.scenario.jsonl + $ head -n 5 ../contracts/v1/fixtures/demo.scenario.jsonl > truncated.scenario.jsonl $ ../bin/main.exe --validate-only --input-format jsonl --input truncated.scenario.jsonl trading-engine: scenario_end must terminate the scenario stream [123] @@ -43,23 +43,23 @@ $ ../bin/main.exe --output-format json --validate-only --input missing.scenario.json 2>&1 >/dev/null | python3 -c 'import json, sys; diagnostic=json.load(sys.stdin); print(diagnostic["code"], diagnostic["phase"])' input.io input - $ sed 's/"open": "100"/"open": "100.001"/' ../contracts/v8/fixtures/demo.scenario.json > invalid-tick.json + $ sed 's/"open": "100"/"open": "100.001"/' ../contracts/v1/fixtures/demo.scenario.json > invalid-tick.json $ ../bin/main.exe --validate-only --input invalid-tick.json trading-engine: market prices and volumes must align with instrument increments [123] - $ ../bin/main.exe --input ../contracts/v8/fixtures/demo.scenario.json + $ ../bin/main.exe --input ../contracts/v1/fixtures/demo.scenario.json trading-engine: --journal is required unless --validate-only is set [123] - $ ../bin/main.exe --validate-only --input ../contracts/v8/fixtures/demo.scenario.json --journal validation.journal.jsonl + $ ../bin/main.exe --validate-only --input ../contracts/v1/fixtures/demo.scenario.json --journal validation.journal.jsonl trading-engine: --journal cannot be used with --validate-only [123] $ test ! -e validation.journal.jsonl - $ ../bin/main.exe --input-format jsonl --input ../contracts/v8/fixtures/demo.scenario.jsonl --journal piped-file.journal.jsonl >/dev/null - $ cat ../contracts/v8/fixtures/demo.scenario.jsonl | ../bin/main.exe --input-format jsonl --input - --journal - > piped-stdout.journal.jsonl 2> piped-summary.txt + $ ../bin/main.exe --input-format jsonl --input ../contracts/v1/fixtures/demo.scenario.jsonl --journal piped-file.journal.jsonl >/dev/null + $ cat ../contracts/v1/fixtures/demo.scenario.jsonl | ../bin/main.exe --input-format jsonl --input - --journal - > piped-stdout.journal.jsonl 2> piped-summary.txt $ cmp piped-file.journal.jsonl piped-stdout.journal.jsonl $ python3 - piped-summary.txt piped-stdout.journal.jsonl <<'PY' > import hashlib @@ -73,9 +73,9 @@ > print(len(journal_bytes.splitlines()), hashlib.sha256(journal_bytes).hexdigest() == hashlib.sha256(open("piped-file.journal.jsonl", "rb").read()).hexdigest()) > PY True run_completed - 22 True + 34 True - $ ../bin/main.exe --output-format json --input-format jsonl --input ../contracts/v8/fixtures/demo.scenario.jsonl --journal - > piped-json.journal.jsonl 2> piped-json-summary.json + $ ../bin/main.exe --output-format json --input-format jsonl --input ../contracts/v1/fixtures/demo.scenario.jsonl --journal - > piped-json.journal.jsonl 2> piped-json-summary.json $ python3 -c 'import json; result=json.load(open("piped-json-summary.json")); print(result["result_version"], result["operation"], result["artifacts"]["journal"], result["hashes"]["journal_sha256"] is not None)' 1 replay stdout True $ cmp piped-file.journal.jsonl piped-json.journal.jsonl @@ -84,43 +84,43 @@ trading-engine: standard input requires --input-format jsonl; batch JSON is not supported [123] - $ ../bin/main.exe --input-format jsonl --input ../contracts/v8/fixtures/demo.scenario.jsonl --journal - --durable-artifacts + $ ../bin/main.exe --input-format jsonl --input ../contracts/v1/fixtures/demo.scenario.jsonl --journal - --durable-artifacts trading-engine: --durable-artifacts cannot be used when --journal writes to standard output [123] - $ ../bin/main.exe --validate-only --durable-artifacts --input ../contracts/v8/fixtures/demo.scenario.json + $ ../bin/main.exe --validate-only --durable-artifacts --input ../contracts/v1/fixtures/demo.scenario.json trading-engine: --durable-artifacts cannot be used with --validate-only [123] - $ ../bin/main.exe --input ../contracts/v8/fixtures/demo.scenario.json --journal ignored.journal.jsonl --strategy-timeout 5 + $ ../bin/main.exe --input ../contracts/v1/fixtures/demo.scenario.json --journal ignored.journal.jsonl --strategy-timeout 5 trading-engine: --strategy-arg, --strategy-timeout, and --strategy-transcript require --strategy-executable [123] $ test ! -e ignored.journal.jsonl $ mkdir external - $ ../bin/main.exe --input ../contracts/strategy/v6/fixtures/external.scenario.json --journal external/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript external/run.strategy.jsonl --strategy-timeout 5 --durable-artifacts - run=external-demo audits=12 orders=1 active=0 filled=1 rejected=0 + $ ../bin/main.exe --input ../contracts/strategy/v1/fixtures/external.scenario.json --journal external/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript external/run.strategy.jsonl --strategy-timeout 5 --durable-artifacts + run=external-demo audits=13 orders=1 active=0 filled=1 rejected=0 cash=9793.544 equity=10007.544 gross=214 realized=0 unrealized=7.544 fees=0.456 journal=external/run.journal.jsonl strategy_transcript=external/run.strategy.jsonl $ python3 -c 'from pathlib import Path; print(len(Path("external/run.journal.jsonl").read_text().splitlines()), len(Path("external/run.strategy.jsonl").read_text().splitlines()))' - 12 14 - $ diff -u ../contracts/strategy/v6/fixtures/external.strategy.jsonl external/run.strategy.jsonl + 13 14 + $ diff -u ../contracts/strategy/v1/fixtures/external.strategy.jsonl external/run.strategy.jsonl $ mkdir external-json - $ ../bin/main.exe --output-format json --input ../contracts/strategy/v6/fixtures/external.scenario.json --journal external-json/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript external-json/run.strategy.jsonl --strategy-timeout 5 | python3 -c 'import hashlib, json, sys; result=json.load(sys.stdin); digest=lambda path: hashlib.sha256(open(path, "rb").read()).hexdigest(); print(result["operation"], result["run_id"], result["artifacts"]["strategy_transcript"]); print(result["hashes"]["journal_sha256"] == digest(result["artifacts"]["journal"]), result["hashes"]["strategy_transcript_sha256"] == digest(result["artifacts"]["strategy_transcript"]))' + $ ../bin/main.exe --output-format json --input ../contracts/strategy/v1/fixtures/external.scenario.json --journal external-json/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript external-json/run.strategy.jsonl --strategy-timeout 5 | python3 -c 'import hashlib, json, sys; result=json.load(sys.stdin); digest=lambda path: hashlib.sha256(open(path, "rb").read()).hexdigest(); print(result["operation"], result["run_id"], result["artifacts"]["strategy_transcript"]); print(result["hashes"]["journal_sha256"] == digest(result["artifacts"]["journal"]), result["hashes"]["strategy_transcript_sha256"] == digest(result["artifacts"]["strategy_transcript"]))' replay external-demo external-json/run.strategy.jsonl True True - $ ../bin/main.exe --input ../contracts/strategy/v6/fixtures/external.scenario.json --journal ignored-stdout.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript - + $ ../bin/main.exe --input ../contracts/strategy/v1/fixtures/external.scenario.json --journal ignored-stdout.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript - trading-engine: --strategy-transcript does not support standard output; choose a file path [123] $ test ! -e ignored-stdout.journal.jsonl $ mkdir callback-ordering - $ ../bin/main.exe --input ../contracts/strategy/v6/fixtures/external.scenario.json --journal callback-ordering/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-arg cancel-next --strategy-transcript callback-ordering/run.strategy.jsonl --strategy-timeout 5 - run=external-demo audits=12 orders=2 active=0 filled=1 rejected=0 + $ ../bin/main.exe --input ../contracts/strategy/v1/fixtures/external.scenario.json --journal callback-ordering/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-arg cancel-next --strategy-transcript callback-ordering/run.strategy.jsonl --strategy-timeout 5 + run=external-demo audits=13 orders=2 active=0 filled=1 rejected=0 cash=9896.647 equity=10003.647 gross=107 realized=0 unrealized=3.647 fees=0.353 journal=callback-ordering/run.journal.jsonl strategy_transcript=callback-ordering/run.strategy.jsonl @@ -130,7 +130,7 @@ 107 107 $ mkdir failed-external - $ ../bin/main.exe --input ../contracts/strategy/v6/fixtures/external.scenario.json --journal failed-external/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-arg stall --strategy-transcript failed-external/run.strategy.jsonl --strategy-timeout 0.01 + $ ../bin/main.exe --input ../contracts/strategy/v1/fixtures/external.scenario.json --journal failed-external/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-arg stall --strategy-transcript failed-external/run.strategy.jsonl --strategy-timeout 0.01 trading-engine: strategy initialization: external strategy timed out [123] $ test ! -e failed-external/run.journal.jsonl @@ -143,7 +143,7 @@ > expected="$2" > directory="fault-$mode" > mkdir "$directory" - > output=$(../bin/main.exe --input ../contracts/strategy/v6/fixtures/external.scenario.json --journal "$directory/run.journal.jsonl" --strategy-executable ./fake_strategy.py --strategy-arg "$mode" --strategy-transcript "$directory/run.strategy.jsonl" --strategy-timeout 5 2>&1) + > output=$(../bin/main.exe --input ../contracts/strategy/v1/fixtures/external.scenario.json --journal "$directory/run.journal.jsonl" --strategy-executable ./fake_strategy.py --strategy-arg "$mode" --strategy-transcript "$directory/run.strategy.jsonl" --strategy-timeout 5 2>&1) > status=$? > test "$status" -eq 123 || return 1 > case "$output" in *"$expected"*) ;; *) return 1 ;; esac @@ -188,7 +188,7 @@ > if mode == "bad-sequence": > assert response["strategy_sequence"] == "999" > elif mode == "wrong-version": - > assert response["strategy_protocol_version"] == "1" + > assert response["strategy_protocol_version"] == "2" > elif mode == "unknown-field": > assert response["unexpected"] is True > PY @@ -220,7 +220,7 @@ > directory="process-tree-$mode" > mkdir "$directory" > pid_path="$directory/grandchild.pid" - > output=$(../bin/main.exe --input ../contracts/strategy/v6/fixtures/external.scenario.json --journal "$directory/run.journal.jsonl" --strategy-executable ./fake_strategy.py --strategy-arg "$mode" --strategy-arg "$pid_path" --strategy-transcript "$directory/run.strategy.jsonl" --strategy-timeout 0.2 2>&1) + > output=$(../bin/main.exe --input ../contracts/strategy/v1/fixtures/external.scenario.json --journal "$directory/run.journal.jsonl" --strategy-executable ./fake_strategy.py --strategy-arg "$mode" --strategy-arg "$pid_path" --strategy-transcript "$directory/run.strategy.jsonl" --strategy-timeout 0.2 2>&1) > status=$? > test "$status" -eq 123 || return 1 > case "$output" in *"$expected"*) ;; *) return 1 ;; esac @@ -249,8 +249,8 @@ grandchild-malformed: process tree reaped $ mkdir external-stream - $ ../bin/main.exe --input-format jsonl --input ../contracts/strategy/v6/fixtures/external.scenario.jsonl --journal external-stream/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript external-stream/run.strategy.jsonl --strategy-timeout 5 - run=external-demo audits=12 orders=1 active=0 filled=1 rejected=0 + $ ../bin/main.exe --input-format jsonl --input ../contracts/strategy/v1/fixtures/external.scenario.jsonl --journal external-stream/run.journal.jsonl --strategy-executable ./fake_strategy.py --strategy-transcript external-stream/run.strategy.jsonl --strategy-timeout 5 + run=external-demo audits=13 orders=1 active=0 filled=1 rejected=0 cash=9793.544 equity=10007.544 gross=214 realized=0 unrealized=7.544 fees=0.456 journal=external-stream/run.journal.jsonl strategy_transcript=external-stream/run.strategy.jsonl diff --git a/test/dune b/test/dune index aba6db0..34999af 100644 --- a/test/dune +++ b/test/dune @@ -22,109 +22,7 @@ test_scenario test_engine) (deps - ../contracts/v7/fixtures/demo.journal.jsonl - ../contracts/v7/fixtures/demo.scenario.json - ../contracts/v7/fixtures/demo.scenario.jsonl - ../contracts/v7/fixtures/fill-clipped.journal.jsonl - ../contracts/v7/fixtures/fill-clipped.scenario.json - ../contracts/v7/journal.schema.json - ../contracts/v7/scenario-stream.schema.json - ../contracts/v7/scenario.schema.json - ../contracts/v8/fixtures/demo.journal.jsonl - ../contracts/v8/fixtures/demo.scenario.json - ../contracts/v8/fixtures/demo.scenario.jsonl - ../contracts/v8/fixtures/fill-clipped.journal.jsonl - ../contracts/v8/fixtures/fill-clipped.scenario.json - ../contracts/v8/journal.schema.json - ../contracts/v8/scenario-stream.schema.json - ../contracts/v8/scenario.schema.json - ../contracts/v9/fixtures/demo.journal.jsonl - ../contracts/v9/fixtures/demo.scenario.json - ../contracts/v9/fixtures/demo.scenario.jsonl - ../contracts/v9/fixtures/fill-clipped.journal.jsonl - ../contracts/v9/fixtures/fill-clipped.scenario.json - ../contracts/v9/journal.schema.json - ../contracts/v9/scenario-stream.schema.json - ../contracts/v9/scenario.schema.json - ../contracts/v10/fixtures/demo.journal.jsonl - ../contracts/v10/fixtures/demo.scenario.json - ../contracts/v10/fixtures/demo.scenario.jsonl - ../contracts/v10/fixtures/fill-clipped.journal.jsonl - ../contracts/v10/fixtures/fill-clipped.scenario.json - ../contracts/v10/journal.schema.json - ../contracts/v10/scenario-stream.schema.json - ../contracts/v10/scenario.schema.json - ../contracts/v11/fixtures/demo.journal.jsonl - ../contracts/v11/fixtures/demo.scenario.json - ../contracts/v11/fixtures/demo.scenario.jsonl - ../contracts/v11/fixtures/fill-clipped.journal.jsonl - ../contracts/v11/fixtures/fill-clipped.scenario.json - ../contracts/v11/journal.schema.json - ../contracts/v11/scenario-stream.schema.json - ../contracts/v11/scenario.schema.json - ../contracts/v12/fixtures/demo.journal.jsonl - ../contracts/v12/fixtures/demo.scenario.json - ../contracts/v12/fixtures/demo.scenario.jsonl - ../contracts/v12/fixtures/fill-clipped.journal.jsonl - ../contracts/v12/fixtures/fill-clipped.scenario.json - ../contracts/v12/journal.schema.json - ../contracts/v12/scenario-stream.schema.json - ../contracts/v12/scenario.schema.json - ../contracts/v13/fixtures/demo.journal.jsonl - ../contracts/v13/fixtures/demo.scenario.json - ../contracts/v13/fixtures/demo.scenario.jsonl - ../contracts/v13/fixtures/fill-clipped.journal.jsonl - ../contracts/v13/fixtures/fill-clipped.scenario.json - ../contracts/v13/journal.schema.json - ../contracts/v13/scenario-stream.schema.json - ../contracts/v13/scenario.schema.json - ../contracts/v15/fixtures/demo.journal.jsonl - ../contracts/v15/fixtures/demo.scenario.json - ../contracts/v15/fixtures/demo.scenario.jsonl - ../contracts/v15/fixtures/fill-clipped.journal.jsonl - ../contracts/v15/fixtures/fill-clipped.scenario.json - ../contracts/v15/fixtures/quote-trade.journal.jsonl - ../contracts/v15/fixtures/quote-trade.scenario.json - ../contracts/v15/fixtures/quote-trade.scenario.jsonl - ../contracts/v15/fixtures/order-book.journal.jsonl - ../contracts/v15/fixtures/order-book.scenario.json - ../contracts/v15/fixtures/order-book.scenario.jsonl - ../contracts/v15/journal.schema.json - ../contracts/v15/scenario-stream.schema.json - ../contracts/v15/scenario.schema.json - ../contracts/v6/fixtures/demo.scenario.json - ../contracts/v6/fixtures/demo.scenario.jsonl - ../contracts/v5/fixtures/demo.scenario.json - ../contracts/v5/fixtures/demo.scenario.jsonl - ../contracts/v4/fixtures/demo.scenario.json - ../contracts/v3/fixtures/demo.journal.jsonl - ../contracts/v3/fixtures/demo.scenario.json - ../contracts/v3/fixtures/demo.scenario.jsonl - ../contracts/conformance/cases.json - ../contracts/strategy/v5/fixtures/external.strategy.jsonl - ../contracts/strategy/v6/fixtures/external.strategy.jsonl - ../contracts/strategy/v7/fixtures/external.strategy.jsonl - ../contracts/strategy/v8/fixtures/external.strategy.jsonl - ../contracts/strategy/v9/fixtures/external.strategy.jsonl - ../contracts/strategy/v10/fixtures/external.strategy.jsonl - ../contracts/strategy/v11/fixtures/external.strategy.jsonl - ../contracts/strategy/v13/fixtures/external.strategy.jsonl - ../contracts/strategy/v14/fixtures/external.strategy.jsonl - ../contracts/v16/fixtures/demo.journal.jsonl - ../contracts/v16/fixtures/demo.scenario.json - ../contracts/v16/fixtures/demo.scenario.jsonl - ../contracts/v16/fixtures/fill-clipped.journal.jsonl - ../contracts/v16/fixtures/fill-clipped.scenario.json - ../contracts/v16/fixtures/order-book.journal.jsonl - ../contracts/v16/fixtures/order-book.scenario.json - ../contracts/v16/fixtures/order-book.scenario.jsonl - ../contracts/v16/fixtures/quote-trade.journal.jsonl - ../contracts/v16/fixtures/quote-trade.scenario.json - ../contracts/v16/fixtures/quote-trade.scenario.jsonl - ../contracts/v16/journal.schema.json - ../contracts/v16/scenario-stream.schema.json - ../contracts/v16/scenario.schema.json - ../contracts/strategy/v4/fixtures/external.strategy.jsonl + (source_tree ../contracts) fake_strategy.py) (libraries trading_engine @@ -146,358 +44,43 @@ (alias runtest) (deps validate_schemas.py - ../contracts/v15/fixtures/demo.journal.jsonl - ../contracts/v15/fixtures/demo.scenario.json - ../contracts/v15/fixtures/demo.scenario.jsonl - ../contracts/v15/journal.schema.json - ../contracts/v15/scenario-stream.schema.json - ../contracts/v15/scenario.schema.json) + ../contracts/v1/scenario.schema.json + ../contracts/v1/scenario-stream.schema.json + ../contracts/v1/journal.schema.json + ../contracts/v1/fixtures/demo.scenario.json + ../contracts/v1/fixtures/demo.scenario.jsonl + ../contracts/v1/fixtures/demo.journal.jsonl) (action (run python3 %{dep:validate_schemas.py} - %{dep:../contracts/v15/scenario.schema.json} - %{dep:../contracts/v15/scenario-stream.schema.json} - %{dep:../contracts/v15/journal.schema.json} - %{dep:../contracts/v15/fixtures/demo.scenario.json} - %{dep:../contracts/v15/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v15/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v15/fixtures/quote-trade.journal.jsonl - ../contracts/v15/fixtures/quote-trade.scenario.json - ../contracts/v15/fixtures/quote-trade.scenario.jsonl - ../contracts/v15/journal.schema.json - ../contracts/v15/scenario-stream.schema.json - ../contracts/v15/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v15/scenario.schema.json} - %{dep:../contracts/v15/scenario-stream.schema.json} - %{dep:../contracts/v15/journal.schema.json} - %{dep:../contracts/v15/fixtures/quote-trade.scenario.json} - %{dep:../contracts/v15/fixtures/quote-trade.scenario.jsonl} - %{dep:../contracts/v15/fixtures/quote-trade.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_strategy_schema.py - ../contracts/v15/scenario.schema.json - ../contracts/v15/journal.schema.json - ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v13/message.schema.json - ../contracts/strategy/v13/transcript.schema.json - ../contracts/strategy/v13/fixtures/external.strategy.jsonl) - (action - (run - python3 - %{dep:validate_strategy_schema.py} - %{dep:../contracts/v15/scenario.schema.json} - %{dep:../contracts/v15/journal.schema.json} - %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v13/message.schema.json} - %{dep:../contracts/strategy/v13/transcript.schema.json} - %{dep:../contracts/strategy/v13/fixtures/external.strategy.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v15/fixtures/order-book.journal.jsonl - ../contracts/v15/fixtures/order-book.scenario.json - ../contracts/v15/fixtures/order-book.scenario.jsonl - ../contracts/v15/journal.schema.json - ../contracts/v15/scenario-stream.schema.json - ../contracts/v15/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v15/scenario.schema.json} - %{dep:../contracts/v15/scenario-stream.schema.json} - %{dep:../contracts/v15/journal.schema.json} - %{dep:../contracts/v15/fixtures/order-book.scenario.json} - %{dep:../contracts/v15/fixtures/order-book.scenario.jsonl} - %{dep:../contracts/v15/fixtures/order-book.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v13/fixtures/demo.journal.jsonl - ../contracts/v13/fixtures/demo.scenario.json - ../contracts/v13/fixtures/demo.scenario.jsonl - ../contracts/v13/journal.schema.json - ../contracts/v13/scenario-stream.schema.json - ../contracts/v13/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v13/scenario.schema.json} - %{dep:../contracts/v13/scenario-stream.schema.json} - %{dep:../contracts/v13/journal.schema.json} - %{dep:../contracts/v13/fixtures/demo.scenario.json} - %{dep:../contracts/v13/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v13/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v13/fixtures/fill-clipped.journal.jsonl - ../contracts/v13/fixtures/fill-clipped.scenario.json - ../contracts/v13/fixtures/demo.scenario.jsonl - ../contracts/v13/journal.schema.json - ../contracts/v13/scenario-stream.schema.json - ../contracts/v13/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v13/scenario.schema.json} - %{dep:../contracts/v13/scenario-stream.schema.json} - %{dep:../contracts/v13/journal.schema.json} - %{dep:../contracts/v13/fixtures/fill-clipped.scenario.json} - %{dep:../contracts/v13/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v13/fixtures/fill-clipped.journal.jsonl}))) + %{dep:../contracts/v1/scenario.schema.json} + %{dep:../contracts/v1/scenario-stream.schema.json} + %{dep:../contracts/v1/journal.schema.json} + %{dep:../contracts/v1/fixtures/demo.scenario.json} + %{dep:../contracts/v1/fixtures/demo.scenario.jsonl} + %{dep:../contracts/v1/fixtures/demo.journal.jsonl}))) (rule (alias runtest) (deps validate_strategy_schema.py - ../contracts/v13/scenario.schema.json - ../contracts/v13/journal.schema.json + ../contracts/v1/scenario.schema.json + ../contracts/v1/journal.schema.json ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v11/message.schema.json - ../contracts/strategy/v11/transcript.schema.json - ../contracts/strategy/v11/fixtures/external.strategy.jsonl) + ../contracts/strategy/v1/message.schema.json + ../contracts/strategy/v1/transcript.schema.json + ../contracts/strategy/v1/fixtures/external.strategy.jsonl) (action (run python3 %{dep:validate_strategy_schema.py} - %{dep:../contracts/v13/scenario.schema.json} - %{dep:../contracts/v13/journal.schema.json} + %{dep:../contracts/v1/scenario.schema.json} + %{dep:../contracts/v1/journal.schema.json} %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v11/message.schema.json} - %{dep:../contracts/strategy/v11/transcript.schema.json} - %{dep:../contracts/strategy/v11/fixtures/external.strategy.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v12/fixtures/demo.journal.jsonl - ../contracts/v12/fixtures/demo.scenario.json - ../contracts/v12/fixtures/demo.scenario.jsonl - ../contracts/v12/journal.schema.json - ../contracts/v12/scenario-stream.schema.json - ../contracts/v12/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v12/scenario.schema.json} - %{dep:../contracts/v12/scenario-stream.schema.json} - %{dep:../contracts/v12/journal.schema.json} - %{dep:../contracts/v12/fixtures/demo.scenario.json} - %{dep:../contracts/v12/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v12/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v12/fixtures/fill-clipped.journal.jsonl - ../contracts/v12/fixtures/fill-clipped.scenario.json - ../contracts/v12/fixtures/demo.scenario.jsonl - ../contracts/v12/journal.schema.json - ../contracts/v12/scenario-stream.schema.json - ../contracts/v12/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v12/scenario.schema.json} - %{dep:../contracts/v12/scenario-stream.schema.json} - %{dep:../contracts/v12/journal.schema.json} - %{dep:../contracts/v12/fixtures/fill-clipped.scenario.json} - %{dep:../contracts/v12/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v12/fixtures/fill-clipped.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_strategy_schema.py - ../contracts/v12/scenario.schema.json - ../contracts/v12/journal.schema.json - ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v10/message.schema.json - ../contracts/strategy/v10/transcript.schema.json - ../contracts/strategy/v10/fixtures/external.strategy.jsonl) - (action - (run - python3 - %{dep:validate_strategy_schema.py} - %{dep:../contracts/v12/scenario.schema.json} - %{dep:../contracts/v12/journal.schema.json} - %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v10/message.schema.json} - %{dep:../contracts/strategy/v10/transcript.schema.json} - %{dep:../contracts/strategy/v10/fixtures/external.strategy.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v11/fixtures/demo.journal.jsonl - ../contracts/v11/fixtures/demo.scenario.json - ../contracts/v11/fixtures/demo.scenario.jsonl - ../contracts/v11/journal.schema.json - ../contracts/v11/scenario-stream.schema.json - ../contracts/v11/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v11/scenario.schema.json} - %{dep:../contracts/v11/scenario-stream.schema.json} - %{dep:../contracts/v11/journal.schema.json} - %{dep:../contracts/v11/fixtures/demo.scenario.json} - %{dep:../contracts/v11/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v11/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v11/fixtures/fill-clipped.journal.jsonl - ../contracts/v11/fixtures/fill-clipped.scenario.json - ../contracts/v11/fixtures/demo.scenario.jsonl - ../contracts/v11/journal.schema.json - ../contracts/v11/scenario-stream.schema.json - ../contracts/v11/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v11/scenario.schema.json} - %{dep:../contracts/v11/scenario-stream.schema.json} - %{dep:../contracts/v11/journal.schema.json} - %{dep:../contracts/v11/fixtures/fill-clipped.scenario.json} - %{dep:../contracts/v11/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v11/fixtures/fill-clipped.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_strategy_schema.py - ../contracts/v11/scenario.schema.json - ../contracts/v11/journal.schema.json - ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v9/message.schema.json - ../contracts/strategy/v9/transcript.schema.json - ../contracts/strategy/v9/fixtures/external.strategy.jsonl) - (action - (run - python3 - %{dep:validate_strategy_schema.py} - %{dep:../contracts/v11/scenario.schema.json} - %{dep:../contracts/v11/journal.schema.json} - %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v9/message.schema.json} - %{dep:../contracts/strategy/v9/transcript.schema.json} - %{dep:../contracts/strategy/v9/fixtures/external.strategy.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v10/fixtures/demo.journal.jsonl - ../contracts/v10/fixtures/demo.scenario.json - ../contracts/v10/fixtures/demo.scenario.jsonl - ../contracts/v10/journal.schema.json - ../contracts/v10/scenario-stream.schema.json - ../contracts/v10/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v10/scenario.schema.json} - %{dep:../contracts/v10/scenario-stream.schema.json} - %{dep:../contracts/v10/journal.schema.json} - %{dep:../contracts/v10/fixtures/demo.scenario.json} - %{dep:../contracts/v10/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v10/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v10/fixtures/fill-clipped.journal.jsonl - ../contracts/v10/fixtures/fill-clipped.scenario.json - ../contracts/v10/fixtures/demo.scenario.jsonl - ../contracts/v10/journal.schema.json - ../contracts/v10/scenario-stream.schema.json - ../contracts/v10/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v10/scenario.schema.json} - %{dep:../contracts/v10/scenario-stream.schema.json} - %{dep:../contracts/v10/journal.schema.json} - %{dep:../contracts/v10/fixtures/fill-clipped.scenario.json} - %{dep:../contracts/v10/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v10/fixtures/fill-clipped.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v9/fixtures/demo.journal.jsonl - ../contracts/v9/fixtures/demo.scenario.json - ../contracts/v9/fixtures/demo.scenario.jsonl - ../contracts/v9/journal.schema.json - ../contracts/v9/scenario-stream.schema.json - ../contracts/v9/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v9/scenario.schema.json} - %{dep:../contracts/v9/scenario-stream.schema.json} - %{dep:../contracts/v9/journal.schema.json} - %{dep:../contracts/v9/fixtures/demo.scenario.json} - %{dep:../contracts/v9/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v9/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v9/fixtures/fill-clipped.journal.jsonl - ../contracts/v9/fixtures/fill-clipped.scenario.json - ../contracts/v9/fixtures/demo.scenario.jsonl - ../contracts/v9/journal.schema.json - ../contracts/v9/scenario-stream.schema.json - ../contracts/v9/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v9/scenario.schema.json} - %{dep:../contracts/v9/scenario-stream.schema.json} - %{dep:../contracts/v9/journal.schema.json} - %{dep:../contracts/v9/fixtures/fill-clipped.scenario.json} - %{dep:../contracts/v9/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v9/fixtures/fill-clipped.journal.jsonl}))) + %{dep:../contracts/strategy/v1/message.schema.json} + %{dep:../contracts/strategy/v1/transcript.schema.json} + %{dep:../contracts/strategy/v1/fixtures/external.strategy.jsonl}))) (rule (alias runtest) @@ -511,200 +94,11 @@ (deps ../bin/main.exe fake_strategy.py - ../contracts/strategy/v6/fixtures/external.scenario.json - ../contracts/strategy/v6/fixtures/external.scenario.jsonl - ../contracts/strategy/v6/fixtures/external.strategy.jsonl - ../contracts/v8/fixtures/demo.scenario.json - ../contracts/v8/fixtures/demo.scenario.jsonl)) - -(rule - (alias runtest) - (deps - validate_strategy_schema.py - ../contracts/v10/scenario.schema.json - ../contracts/v10/journal.schema.json - ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v8/message.schema.json - ../contracts/strategy/v8/transcript.schema.json - ../contracts/strategy/v8/fixtures/external.strategy.jsonl) - (action - (run - python3 - %{dep:validate_strategy_schema.py} - %{dep:../contracts/v10/scenario.schema.json} - %{dep:../contracts/v10/journal.schema.json} - %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v8/message.schema.json} - %{dep:../contracts/strategy/v8/transcript.schema.json} - %{dep:../contracts/strategy/v8/fixtures/external.strategy.jsonl}))) - -(rule - (alias runtest) - (deps - validate_strategy_schema.py - ../contracts/v9/scenario.schema.json - ../contracts/v9/journal.schema.json - ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v7/message.schema.json - ../contracts/strategy/v7/transcript.schema.json - ../contracts/strategy/v7/fixtures/external.strategy.jsonl) - (action - (run - python3 - %{dep:validate_strategy_schema.py} - %{dep:../contracts/v9/scenario.schema.json} - %{dep:../contracts/v9/journal.schema.json} - %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v7/message.schema.json} - %{dep:../contracts/strategy/v7/transcript.schema.json} - %{dep:../contracts/strategy/v7/fixtures/external.strategy.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v8/fixtures/demo.journal.jsonl - ../contracts/v8/fixtures/demo.scenario.json - ../contracts/v8/fixtures/demo.scenario.jsonl - ../contracts/v8/journal.schema.json - ../contracts/v8/scenario-stream.schema.json - ../contracts/v8/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v8/scenario.schema.json} - %{dep:../contracts/v8/scenario-stream.schema.json} - %{dep:../contracts/v8/journal.schema.json} - %{dep:../contracts/v8/fixtures/demo.scenario.json} - %{dep:../contracts/v8/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v8/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v8/fixtures/fill-clipped.journal.jsonl - ../contracts/v8/fixtures/fill-clipped.scenario.json - ../contracts/v8/fixtures/demo.scenario.jsonl - ../contracts/v8/journal.schema.json - ../contracts/v8/scenario-stream.schema.json - ../contracts/v8/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v8/scenario.schema.json} - %{dep:../contracts/v8/scenario-stream.schema.json} - %{dep:../contracts/v8/journal.schema.json} - %{dep:../contracts/v8/fixtures/fill-clipped.scenario.json} - %{dep:../contracts/v8/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v8/fixtures/fill-clipped.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v7/fixtures/demo.journal.jsonl - ../contracts/v7/fixtures/demo.scenario.json - ../contracts/v7/fixtures/demo.scenario.jsonl - ../contracts/v7/journal.schema.json - ../contracts/v7/scenario-stream.schema.json - ../contracts/v7/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v7/scenario.schema.json} - %{dep:../contracts/v7/scenario-stream.schema.json} - %{dep:../contracts/v7/journal.schema.json} - %{dep:../contracts/v7/fixtures/demo.scenario.json} - %{dep:../contracts/v7/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v7/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v7/fixtures/fill-clipped.journal.jsonl - ../contracts/v7/fixtures/fill-clipped.scenario.json - ../contracts/v7/fixtures/demo.scenario.jsonl - ../contracts/v7/journal.schema.json - ../contracts/v7/scenario-stream.schema.json - ../contracts/v7/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v7/scenario.schema.json} - %{dep:../contracts/v7/scenario-stream.schema.json} - %{dep:../contracts/v7/journal.schema.json} - %{dep:../contracts/v7/fixtures/fill-clipped.scenario.json} - %{dep:../contracts/v7/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v7/fixtures/fill-clipped.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_schemas.py - ../contracts/v3/fixtures/demo.journal.jsonl - ../contracts/v3/fixtures/demo.scenario.json - ../contracts/v3/fixtures/demo.scenario.jsonl - ../contracts/v3/journal.schema.json - ../contracts/v3/scenario-stream.schema.json - ../contracts/v3/scenario.schema.json) - (action - (run - python3 - %{dep:validate_schemas.py} - %{dep:../contracts/v3/scenario.schema.json} - %{dep:../contracts/v3/scenario-stream.schema.json} - %{dep:../contracts/v3/journal.schema.json} - %{dep:../contracts/v3/fixtures/demo.scenario.json} - %{dep:../contracts/v3/fixtures/demo.scenario.jsonl} - %{dep:../contracts/v3/fixtures/demo.journal.jsonl}))) - -(rule - (alias runtest) - (deps - validate_strategy_schema.py - ../contracts/v8/scenario.schema.json - ../contracts/v8/journal.schema.json - ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v6/message.schema.json - ../contracts/strategy/v6/transcript.schema.json - ../contracts/strategy/v6/fixtures/external.strategy.jsonl) - (action - (run - python3 - %{dep:validate_strategy_schema.py} - %{dep:../contracts/v8/scenario.schema.json} - %{dep:../contracts/v8/journal.schema.json} - %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v6/message.schema.json} - %{dep:../contracts/strategy/v6/transcript.schema.json} - %{dep:../contracts/strategy/v6/fixtures/external.strategy.jsonl}))) - -(rule - (alias runtest) - (deps - validate_strategy_schema.py - ../contracts/v7/scenario.schema.json - ../contracts/v7/journal.schema.json - ../contracts/diagnostic/v1/diagnostic.schema.json - ../contracts/strategy/v5/message.schema.json - ../contracts/strategy/v5/transcript.schema.json - ../contracts/strategy/v5/fixtures/external.strategy.jsonl) - (action - (run - python3 - %{dep:validate_strategy_schema.py} - %{dep:../contracts/v7/scenario.schema.json} - %{dep:../contracts/v7/journal.schema.json} - %{dep:../contracts/diagnostic/v1/diagnostic.schema.json} - %{dep:../contracts/strategy/v5/message.schema.json} - %{dep:../contracts/strategy/v5/transcript.schema.json} - %{dep:../contracts/strategy/v5/fixtures/external.strategy.jsonl}))) + ../contracts/strategy/v1/fixtures/external.scenario.json + ../contracts/strategy/v1/fixtures/external.scenario.jsonl + ../contracts/strategy/v1/fixtures/external.strategy.jsonl + ../contracts/v1/fixtures/demo.scenario.json + ../contracts/v1/fixtures/demo.scenario.jsonl)) (rule (alias runtest) @@ -752,7 +146,7 @@ (deps test_benchmark_replay.py ../bench/benchmark_replay.py - ../contracts/v9/fixtures/demo.scenario.json) + ../contracts/v1/fixtures/demo.scenario.json) (action (run python3 %{dep:test_benchmark_replay.py}))) @@ -761,14 +155,14 @@ (deps validate_cli_result.py ../contracts/cli/v1/result.schema.json - ../contracts/v16/journal.schema.json - ../contracts/v16/fixtures/demo.scenario.json + ../contracts/v1/journal.schema.json + ../contracts/v1/fixtures/demo.scenario.json ../bin/main.exe) (action (run python3 %{dep:validate_cli_result.py} %{dep:../contracts/cli/v1/result.schema.json} - %{dep:../contracts/v16/journal.schema.json} + %{dep:../contracts/v1/journal.schema.json} %{dep:../bin/main.exe} - %{dep:../contracts/v16/fixtures/demo.scenario.json}))) + %{dep:../contracts/v1/fixtures/demo.scenario.json}))) diff --git a/test/fake_strategy.py b/test/fake_strategy.py index 260725b..7590f31 100755 --- a/test/fake_strategy.py +++ b/test/fake_strategy.py @@ -98,7 +98,10 @@ def response(request: dict[str, object]) -> dict[str, object]: { "type": "emit_metric", "name": "fixture_signal", - "value": "2", + "value": {"type": "numeric", "value": "2"}, + "unit": "score", + "dimensions": {"source": "fixture"}, + "aggregation": "last", }, ] } @@ -151,7 +154,7 @@ def response(request: dict[str, object]) -> dict[str, object]: if MODE == "bad-sequence": message["strategy_sequence"] = "999" if MODE == "wrong-version": - message["strategy_protocol_version"] = "1" + message["strategy_protocol_version"] = "2" if MODE == "unknown-field": message["unexpected"] = True if MODE == "error" and request["message_type"] == "event": diff --git a/test/fuzz_protocol.ml b/test/fuzz_protocol.ml index 65442b8..8d74e4d 100644 --- a/test/fuzz_protocol.ml +++ b/test/fuzz_protocol.ml @@ -324,7 +324,7 @@ let hostile_seeds () = ("deep-nesting", deep_json 512); ("huge-token", huge_json_string); ( "duplicate-key", - "{\"contract_version\":\"4\",\"contract_version\":\"4\"}" ); + "{\"contract_version\":\"1\",\"contract_version\":\"1\"}" ); ("truncation", "{\"contract_version\":"); ] in diff --git a/test/test_accounting.ml b/test/test_accounting.ml index 39e93de..e611b32 100644 --- a/test/test_accounting.ml +++ b/test/test_accounting.ml @@ -249,7 +249,7 @@ let risk_reserves_partial_order_remainders () = (request ~side:T.Order.Buy ~quantity_value:"1" ())); Alcotest.(check string) "two units exceed the reserved long limit" - "position would exceed the maximum long position" + "position would exceed the instrument maximum long position" (risk_check configured ~account ~oms (request ~side:T.Order.Buy ~quantity_value:"2" ()) |> error) diff --git a/test/test_boundary_failures.ml b/test/test_boundary_failures.ml index 9319621..6cae1b4 100644 --- a/test/test_boundary_failures.ml +++ b/test/test_boundary_failures.ml @@ -323,15 +323,14 @@ let initialization () = metadata = `Assoc [ ("experiment", `String "boundary-failure") ]; run_id = run_id "boundary-failure"; base_currency = "USD"; - initial_cash = [ ("USD", money "10000") ]; - initial_portfolio = None; + initial_portfolio = initial_portfolio (); instruments = [ instrument ]; venue_calendars = []; risk = risk ~instruments:[ instrument ] (); execution_model = T.Execution_model.find "completed_bar_v1" |> ok; execution = execution (); - financing = None; - settlement = None; + financing = financing_policy (); + settlement = settlement_policy (); } let process_stages = diff --git a/test/test_checkpoint4.ml b/test/test_checkpoint4.ml index a350f59..e8f0852 100644 --- a/test/test_checkpoint4.ml +++ b/test/test_checkpoint4.ml @@ -2,37 +2,6 @@ open Test_support module T = Trading_engine module Runner = T.Engine.Make (T.Scripted_strategy) -module Margin_observing_strategy = struct - type state = { saw_liquidation_update : bool } - - let name = "margin-observer" - let initial = { saw_liquidation_update = false } - - let on_event state _context event = - match event with - | T.Strategy.Market_slice_closed market_slice - when Int64.equal market_slice.T.Market_slice.slice_sequence 1L -> - ( state, - [ - T.Strategy.Target_quantities - [ - T.Strategy. - { - instrument_id = instrument_id "test-equity"; - quantity = quantity "15"; - }; - ]; - ] ) - | T.Strategy.Order_updated order - when order.T.Order.request.origin = T.Order.Margin_liquidation -> - ({ saw_liquidation_update = true }, []) - | T.Strategy.Market_slice_closed _ | T.Strategy.Fill_received _ - | T.Strategy.Order_updated _ | T.Strategy.Intent_rejected _ -> - (state, []) -end - -module Margin_runner = T.Engine.Make (Margin_observing_strategy) - let euro_instrument () = instrument ~id:"euro-equity" ~symbol:"EURO" ~currency:"EUR" ~lot_size:"0.001" () @@ -51,6 +20,7 @@ let multi_currency_fractional_accounting () = T.Fill.create ~id:(fill_id "euro-fill") ~order_id:order.id ~instrument_id:euro.id ~quote_currency:"EUR" ~side:T.Order.Buy ~quantity:(quantity "1.5") ~price:(price "20") ~fee:(money "0.5") + ~fee_components:[] ~executed_at:(timestamp "2026-01-03T14:30:00Z") ~slice_sequence:2L |> ok @@ -146,7 +116,7 @@ let split_adjusts_working_order () = let config = engine_config () in let state = Runner.create ~run_id:(run_id "split-order") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok in @@ -190,7 +160,7 @@ let split_caps_adjusted_market_fill () = Runner.create ~run_id:(run_id "split-market-cap") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok in @@ -262,7 +232,7 @@ let split_caps_partially_filled_limit_remainder () = Runner.create ~run_id:(run_id "split-partial-limit") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok in @@ -348,7 +318,7 @@ let reverse_split_restores_order_below_maximum () = Runner.create ~run_id:(run_id "reverse-split-order") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok in @@ -390,98 +360,6 @@ let reverse_split_restores_order_below_maximum () = | _ -> false) events) -let margin_call_forces_deterministic_liquidation () = - let config = engine_config () in - let state = - Margin_runner.create ~run_id:(run_id "margin-call") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "1000") ] - ~strategy_state:Margin_observing_strategy.initial - |> ok - in - let state, _ = Margin_runner.process_slice state (market_slice 1L) |> ok in - let stressed_bar = - bar ~open_price:"100" ~high_price:"100" ~low_price:"40" ~close_price:"40" 2L - in - let state, call_events = - Margin_runner.process_slice state (market_slice ~bars:[ stressed_bar ] 2L) - |> ok - in - Alcotest.(check bool) - "margin call emitted" true - (List.exists - (fun event -> - String.equal (T.Audit.event_name event.T.Audit.event) "margin_call") - call_events); - let liquidation = - T.Oms.active_orders (Margin_runner.oms state) - |> List.find (fun order -> - order.T.Order.request.origin = T.Order.Margin_liquidation) - in - Alcotest.(check string) - "forced sell" "sell" - (T.Order.side_to_string liquidation.request.side); - Alcotest.(check bool) - "strategy observes liquidation order updates" true - (Margin_runner.strategy_state state).saw_liquidation_update; - let liquidation_bar = - bar ~open_price:"40" ~high_price:"40" ~low_price:"40" ~close_price:"40" 3L - in - let state, restored_events = - Margin_runner.process_slice state - (market_slice ~bars:[ liquidation_bar ] 3L) - |> ok - in - Alcotest.check quantity_testable "position flattened" T.Scalar.Quantity.zero - (T.Account.position_quantity - (Margin_runner.account state) - (instrument_id "test-equity")); - Alcotest.(check bool) - "margin restored emitted" true - (List.exists - (fun event -> - String.equal (T.Audit.event_name event.T.Audit.event) "margin_restored") - restored_events) - -let short_borrow_accrues_before_matching () = - let target = - T.Strategy.Target_quantities - [ - T.Strategy. - { - instrument_id = instrument_id "test-equity"; - quantity = quantity "-10"; - }; - ] - in - let strategy_state = T.Scripted_strategy.create [ (1L, [ target ]) ] |> ok in - let config = engine_config ~risk:(risk ~short_borrow_bps:3650 ()) () in - let state = - Runner.create ~run_id:(run_id "short-borrow") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "1000") ] - ~strategy_state - |> ok - in - let state, _ = Runner.process_slice state (market_slice 1L) |> ok in - let state, _ = Runner.process_slice state (market_slice 2L) |> ok in - let state, events = Runner.process_slice state (market_slice 3L) |> ok in - let borrow = - List.find_map - (fun event -> - match event.T.Audit.event with - | T.Audit.Borrow_fee_applied { fee; _ } -> Some fee - | _ -> None) - events - |> Option.get - in - Alcotest.(check bool) - "positive borrow fee" true - (T.Scalar.Money.compare borrow (money "0") > 0); - let position = - T.Account.position (Runner.account state) (instrument_id "test-equity") - in - Alcotest.check money_testable "borrow fee attributed" borrow - position.borrow_fees - let risk_allows_reducing_an_out_of_limit_position () = let configured_risk = risk ~max_long:"10" () in let account = test_account ~initial_cash:[ ("USD", money "10000") ] () in @@ -571,7 +449,8 @@ let engine_requires_complete_currency_ledgers () = "missing EUR ledger rejected" true (Result.is_error (Runner.create ~run_id:(run_id "missing-ledger") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "1000") ] + ~initial_portfolio: + (initial_portfolio ~cash:[ ("USD", money "1000") ] ()) ~strategy_state)) let tests = @@ -588,10 +467,6 @@ let tests = split_caps_partially_filled_limit_remainder; Alcotest.test_case "reverse split restores order below maximum" `Quick reverse_split_restores_order_below_maximum; - Alcotest.test_case "margin call forces liquidation" `Quick - margin_call_forces_deterministic_liquidation; - Alcotest.test_case "short borrow accrues" `Quick - short_borrow_accrues_before_matching; Alcotest.test_case "risk allows reduction above position cap" `Quick risk_allows_reducing_an_out_of_limit_position; Alcotest.test_case "fill clipping reason taxonomy is stable" `Quick diff --git a/test/test_contract_conformance.ml b/test/test_contract_conformance.ml index bd9b7f0..65e75dd 100644 --- a/test/test_contract_conformance.ml +++ b/test/test_contract_conformance.ml @@ -182,13 +182,7 @@ let runtime_result case = let expected_sequence = string_field "expected_sequence" case |> Int64.of_string in - let protocol_version = - match optional_field "protocol_version" case with - | Some (`String value) -> value - | _ -> T.Contract.strategy_protocol_version - in - T.Strategy_protocol.response_of_yojson ~protocol_version - ~expected_sequence response + T.Strategy_protocol.response_of_yojson ~expected_sequence response |> Result.map (fun _ -> ()) | kind -> Alcotest.failf "unsupported differential runtime kind %s" kind diff --git a/test/test_corporate_lifecycle.ml b/test/test_corporate_lifecycle.ml index afd7d58..ccffbba 100644 --- a/test/test_corporate_lifecycle.ml +++ b/test/test_corporate_lifecycle.ml @@ -320,7 +320,7 @@ let policy_and_transition_boundaries () = let lifecycle_slice ?(corporate_actions = []) ?(lifecycle_events = []) sequence = let date = Int64.to_int sequence + 1 in - T.Market_slice.create_v12 ~slice_sequence:sequence + T.Market_slice.create ~slice_sequence:sequence ~start_at:(timestamp (Printf.sprintf "2026-03-%02dT14:30:00Z" date)) ~end_at:(timestamp (Printf.sprintf "2026-03-%02dT21:00:00Z" date)) ~available_at:(timestamp (Printf.sprintf "2026-03-%02dT21:00:01Z" date)) @@ -328,14 +328,15 @@ let lifecycle_slice ?(corporate_actions = []) ?(lifecycle_events = []) sequence ~bars:[ bar sequence ] ~fx_rates:[ fx_mark () ] ~corporate_actions ~borrow_observations:[] ~cash_rate_observations:[] - ~settlement_failures:[] ~lifecycle_events + ~settlement_failures:[] ~lifecycle_events ~market_events:[] + ~order_book_events:[] |> ok let lifecycle_runner schedule run = - let config = engine_config ~contract_version:"12" () in + let config = engine_config ~contract_version:"1" () in let strategy_state = T.Scripted_strategy.create schedule |> ok in Runner.create ~run_id:(run_id run) ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok diff --git a/test/test_diagnostic.ml b/test/test_diagnostic.ml index 13ebe5b..89b337c 100644 --- a/test/test_diagnostic.ml +++ b/test/test_diagnostic.ml @@ -133,26 +133,10 @@ let capabilities_describe_execution_contracts () = | _ -> Alcotest.fail (name ^ " must be an array") in Alcotest.(check (list string)) - "configuration versions" [ "2"; "1" ] + "configuration versions" [ "1" ] (strings "configuration_versions"); Alcotest.(check (list string)) - "scenario contracts" - [ - "16"; - "15"; - "14"; - "13"; - "12"; - "11"; - "10"; - "9"; - "8"; - "7"; - "6"; - "5"; - "4"; - "3"; - ] + "scenario contracts" [ "1" ] (strings "scenario_contract_versions"); Alcotest.(check (list string)) "required fields" diff --git a/test/test_domain.ml b/test/test_domain.ml index 2a607ec..5597946 100644 --- a/test/test_domain.ml +++ b/test/test_domain.ml @@ -12,6 +12,29 @@ let identifier_validation () = "round trip" "order-1" (T.Id.Order.of_string_exn "order-1" |> T.Id.Order.to_string) +let instrument_validation () = + let create ?(symbol = "TEST") ?(quote_currency = "USD") + ?(lot_size = quantity "1") () = + T.Instrument.create + ~id:(instrument_id "test-equity") + ~symbol ~quote_currency ~tick_size:(price "0.01") ~lot_size + in + Alcotest.(check bool) + "empty symbol rejected" true + (Result.is_error (create ~symbol:"" ())); + Alcotest.(check bool) + "symbol whitespace rejected" true + (Result.is_error (create ~symbol:"BAD SYMBOL" ())); + Alcotest.(check bool) + "quote currency whitespace rejected" true + (Result.is_error (create ~quote_currency:" BAD" ())); + Alcotest.(check bool) + "zero lot size rejected" true + (Result.is_error (create ~lot_size:T.Scalar.Quantity.zero ())); + Alcotest.(check string) + "rendered instrument" "TEST (test-equity)" + (Format.asprintf "%a" T.Instrument.pp (create () |> ok)) + let scalar_decimal_round_trip () = let values = [ "0"; "1"; "1.25"; "-0.5"; "999999.000001" ] in List.iter @@ -95,7 +118,9 @@ let market_slice_validation () = ~received_at ~bars:[ bar 1L ] ~fx_rates:[ fx_mark () ] - ~corporate_actions:[] + ~corporate_actions:[] ~borrow_observations:[] ~cash_rate_observations:[] + ~settlement_failures:[] ~lifecycle_events:[] ~market_events:[] + ~order_book_events:[] in Alcotest.(check bool) "premature availability rejected" true (Result.is_error result) @@ -187,7 +212,7 @@ let market_event_validation () = Alcotest.(check bool) "nonmonotonic ingest rejected" true (Result.is_error - (T.Market_slice.create_v14 ~slice_sequence:base.slice_sequence + (T.Market_slice.create ~slice_sequence:base.slice_sequence ~start_at:base.start_at ~end_at:base.end_at ~available_at:base.available_at ~received_at:base.received_at ~bars:base.bars ~fx_rates:base.fx_rates @@ -196,7 +221,7 @@ let market_event_validation () = ~cash_rate_observations:base.cash_rate_observations ~settlement_failures:base.settlement_failures ~lifecycle_events:base.lifecycle_events - ~market_events:[ first; second ])) + ~market_events:[ first; second ] ~order_book_events:[])) let order_book_event_validation () = let instrument_id = instrument_id "book-validation" in @@ -477,23 +502,19 @@ let risk_limits_cover_lots () = Alcotest.(check bool) "order limit smaller than lot rejected" true (Result.is_error - (T.Risk.create ~base_currency:"USD" ~instruments:[ configured ] + (T.Risk.create_instrument_policy ~instrument:configured ~max_order_quantity:(quantity "5") ~max_long_position:(quantity "100") - ~max_short_position:(quantity "100") - ~max_gross_exposure:(money "1000000") - ~max_leverage:(T.Scalar.Ratio.of_decimal_string "2" |> ok) + ~max_short_position:(quantity "100") ~max_notional_exposure:None ~initial_margin_bps:5000 ~maintenance_margin_bps:2500 - ~short_borrow_bps:100)); + ~shorting_allowed:true)); Alcotest.(check bool) "position limit smaller than lot rejected" true (Result.is_error - (T.Risk.create ~base_currency:"USD" ~instruments:[ configured ] + (T.Risk.create_instrument_policy ~instrument:configured ~max_order_quantity:(quantity "100") ~max_long_position:(quantity "5") - ~max_short_position:(quantity "100") - ~max_gross_exposure:(money "1000000") - ~max_leverage:(T.Scalar.Ratio.of_decimal_string "2" |> ok) + ~max_short_position:(quantity "100") ~max_notional_exposure:None ~initial_margin_bps:5000 ~maintenance_margin_bps:2500 - ~short_borrow_bps:100)) + ~shorting_allowed:true)) let typed_metric_validation () = let numeric = T.Metric.numeric_of_string "-12.5" |> ok in @@ -543,6 +564,7 @@ let typed_metric_validation () = let tests = [ Alcotest.test_case "identifier validation" `Quick identifier_validation; + Alcotest.test_case "instrument validation" `Quick instrument_validation; Alcotest.test_case "fixed-point decimal round trip" `Quick scalar_decimal_round_trip; Alcotest.test_case "checked overflow" `Quick scalar_overflow_is_rejected; diff --git a/test/test_execution.ml b/test/test_execution.ml index 24856fb..e088e97 100644 --- a/test/test_execution.ml +++ b/test/test_execution.ml @@ -63,7 +63,7 @@ let trade_event ?(sequence = 2L) ?(second = 2) ?(price_value = "100") let quote_trade_slice events = let base = market_slice 2L in - T.Market_slice.create_v14 ~slice_sequence:base.slice_sequence + T.Market_slice.create ~slice_sequence:base.slice_sequence ~start_at:base.start_at ~end_at:base.end_at ~available_at:base.available_at ~received_at:base.received_at ~bars:base.bars ~fx_rates:base.fx_rates ~corporate_actions:base.corporate_actions @@ -71,11 +71,12 @@ let quote_trade_slice events = ~cash_rate_observations:base.cash_rate_observations ~settlement_failures:base.settlement_failures ~lifecycle_events:base.lifecycle_events ~market_events:events + ~order_book_events:[] |> ok let quote_trade_execution ?(participation_bps = 10_000) () = let fees = conservative_execution () |> T.Execution.fee_schedules in - T.Execution.create_v2 ~participation_bps ~fee_schedules:fees |> ok + T.Execution.create ~participation_bps ~fee_schedules:fees |> ok let book_level price_value quantity_value = T.Order_book_event.level ~price:(price price_value) @@ -123,7 +124,7 @@ let book_trade ?(sequence = 2L) ?(second = 2) ?(price_value = "99") let order_book_slice events = let base = market_slice 2L in - T.Market_slice.create_v15 ~slice_sequence:base.slice_sequence + T.Market_slice.create ~slice_sequence:base.slice_sequence ~start_at:base.start_at ~end_at:base.end_at ~available_at:base.available_at ~received_at:base.received_at ~bars:base.bars ~fx_rates:base.fx_rates ~corporate_actions:base.corporate_actions @@ -231,8 +232,7 @@ let quote_trade_limits_fok_and_continuations () = (Result.is_error (continue (quantity "-1"))) | _ -> Alcotest.fail "marketable limit did not execute"); let oms, _ = - oms_with_order - (request_v8 ~kind:T.Order.Market ~time_in_force:T.Order.Fok ()) + oms_with_order (request ~kind:T.Order.Market ~time_in_force:T.Order.Fok ()) in let cursor = T.Execution.start_slice_quote_trade (quote_trade_execution ()) @@ -248,9 +248,7 @@ let quote_trade_limits_fok_and_continuations () = let quote_trade_stop_and_event_boundaries () = let oms, order = oms_with_order - (request_v8 - ~kind:(T.Order.Stop (price "100")) - ~time_in_force:T.Order.Gtc ()) + (request ~kind:(T.Order.Stop (price "100")) ~time_in_force:T.Order.Gtc ()) in let cursor = T.Execution.start_slice_quote_trade (quote_trade_execution ()) @@ -344,8 +342,7 @@ let order_book_walks_depth_and_rejects_inconsistent_updates () = second.price | _ -> Alcotest.fail "second ask did not produce a fill"); let fok_oms, _ = - oms_with_order - (request_v8 ~kind:T.Order.Market ~time_in_force:T.Order.Fok ()) + oms_with_order (request ~kind:T.Order.Market ~time_in_force:T.Order.Fok ()) in let fok_cursor = T.Execution.start_slice_order_book (order_book_execution ()) @@ -501,7 +498,7 @@ let order_book_walks_depth_and_rejects_inconsistent_updates () = let triggered_stop side trigger = let oms, order = oms_with_order - (request_v8 ~side + (request ~side ~kind:(T.Order.Stop (price trigger)) ~time_in_force:T.Order.Gtc ()) in @@ -527,9 +524,7 @@ let order_book_walks_depth_and_rejects_inconsistent_updates () = triggered_stop T.Order.Sell "100"; let waiting_stop_oms, _ = oms_with_order - (request_v8 - ~kind:(T.Order.Stop (price "200")) - ~time_in_force:T.Order.Gtc ()) + (request ~kind:(T.Order.Stop (price "200")) ~time_in_force:T.Order.Gtc ()) in let waiting_stop_cursor = T.Execution.start_slice_order_book (order_book_execution ()) @@ -542,8 +537,7 @@ let order_book_walks_depth_and_rejects_inconsistent_updates () = | T.Execution.Finished _ -> () | _ -> Alcotest.fail "untriggered order-book stop should remain dormant"); let shallow_fok_oms, _ = - oms_with_order - (request_v8 ~kind:T.Order.Market ~time_in_force:T.Order.Fok ()) + oms_with_order (request ~kind:T.Order.Market ~time_in_force:T.Order.Fok ()) in let shallow_fok_cursor = T.Execution.start_slice_order_book (order_book_execution ()) @@ -732,14 +726,14 @@ let conservative_configuration_is_bounded () = (Result.is_error (create spread impact))) [ (-1, 0); (10_001, 0); (0, -1); (0, 10_001) ]; Alcotest.(check bool) - "v2 participation bound enforced" true + "participation bound enforced" true (Result.is_error - (T.Execution.create_v2 ~participation_bps:(-1) ~fee_schedules:schedules)); + (T.Execution.create ~participation_bps:(-1) ~fee_schedules:schedules)); let schedule = List.hd schedules in Alcotest.(check bool) "duplicate fee schedules rejected" true (Result.is_error - (T.Execution.create_v2 ~participation_bps:10_000 + (T.Execution.create ~participation_bps:10_000 ~fee_schedules:[ schedule; schedule ])); Alcotest.(check bool) "missing instrument fee schedule rejected" true diff --git a/test/test_fee_schedules.ml b/test/test_fee_schedules.ml index b94e6cb..6d6b6f4 100644 --- a/test/test_fee_schedules.ml +++ b/test/test_fee_schedules.ml @@ -106,7 +106,7 @@ let rebate_settles_and_is_attributed () = Alcotest.check money_testable "negative rebate" (money "-0.1") fee; let request = request ~quantity_value:"1" () in let fill = - T.Fill.create_v9 ~id:(fill_id "rebate-fill") + T.Fill.create ~id:(fill_id "rebate-fill") ~order_id:(order_id "rebate-order") ~instrument_id:request.instrument_id ~quote_currency:"USD" ~side:T.Order.Buy ~quantity:(quantity "1") ~price:(price "100") ~fee ~fee_components diff --git a/test/test_financing.ml b/test/test_financing.ml index f8908fd..fa40cb3 100644 --- a/test/test_financing.ml +++ b/test/test_financing.ml @@ -152,11 +152,13 @@ let financing_slice ?(borrow_observations = []) ?(cash_rate_observations = []) let end_at = timestamp (Printf.sprintf "2026-01-%02dT21:00:00Z" day) in let available_at = timestamp (Printf.sprintf "2026-01-%02dT21:00:01Z" day) in let received_at = timestamp (Printf.sprintf "2026-01-%02dT21:00:02Z" day) in - T.Market_slice.create_v10 ~slice_sequence:sequence ~start_at ~end_at - ~available_at ~received_at + T.Market_slice.create ~slice_sequence:sequence ~start_at ~end_at ~available_at + ~received_at ~bars:[ bar sequence ] ~fx_rates:[ fx_mark () ] ~corporate_actions:[] ~borrow_observations ~cash_rate_observations + ~settlement_failures:[] ~lifecycle_events:[] ~market_events:[] + ~order_book_events:[] |> ok let borrow_observation ?(available = "5") ?(rate = 3600) ?(recalled = false) @@ -173,11 +175,11 @@ let cash_rate effective_at = |> ok let financing_config financing = - T.Engine.config_v10 ~contract_version:T.Contract.version - ~risk:(risk ~short_borrow_bps:0 ()) + T.Engine.config ~contract_version:T.Contract.version ~risk:(risk ()) ~venue_calendars:[] ~execution_model:(T.Execution_model.find "completed_bar_v1" |> ok) - ~execution:(execution ()) ~financing ~max_internal_events:1000 + ~execution:(execution ()) ~financing ~settlement:(settlement_policy ()) + ~max_internal_events:1000 |> ok let empty_strategy () = T.Scripted_strategy.create [] |> ok @@ -186,7 +188,7 @@ let missing_data_policies_are_explicit () = let cash_state = Runner.create ~run_id:(run_id "missing-cash") ~scenario_sha256 ~config:(financing_config (policy ())) - ~initial_cash:[ ("USD", money "1000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "1000") ] ()) ~strategy_state:(empty_strategy ()) |> ok in @@ -213,8 +215,7 @@ let missing_data_policies_are_explicit () = |> ok in let borrow_state = - Runner.create_with_portfolio ~run_id:(run_id "missing-borrow") - ~scenario_sha256 + Runner.create ~run_id:(run_id "missing-borrow") ~scenario_sha256 ~config:(financing_config (policy ~cash_missing_data:T.Financing.Zero ())) ~initial_portfolio ~strategy_state:(empty_strategy ()) |> ok @@ -247,7 +248,7 @@ let reject_order_policy_uses_current_locate () = let state = Runner.create ~run_id:(run_id "reject-locate") ~scenario_sha256 ~config:(financing_config financing) - ~initial_cash:[ ("USD", money "1000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "1000") ] ()) ~strategy_state |> ok in @@ -294,8 +295,7 @@ let zero_missing_data_and_recall_retention () = ~recall_policy:T.Financing.Reject_new_shorts () in let state = - Runner.create_with_portfolio ~run_id:(run_id "retain-recall") - ~scenario_sha256 + Runner.create ~run_id:(run_id "retain-recall") ~scenario_sha256 ~config:(financing_config financing) ~initial_portfolio ~strategy_state:(empty_strategy ()) |> ok @@ -344,18 +344,19 @@ let availability_clips_and_recall_closes () = ] in let strategy_state = T.Scripted_strategy.create [ (1L, [ target ]) ] |> ok in - let configured_risk = risk ~short_borrow_bps:0 () in + let configured_risk = risk () in let financing = policy () in let config = - T.Engine.config_v10 ~contract_version:T.Contract.version - ~risk:configured_risk ~venue_calendars:[] + T.Engine.config ~contract_version:T.Contract.version ~risk:configured_risk + ~venue_calendars:[] ~execution_model:(T.Execution_model.find "completed_bar_v1" |> ok) - ~execution:(execution ()) ~financing ~max_internal_events:1000 + ~execution:(execution ()) ~financing ~settlement:(settlement_policy ()) + ~max_internal_events:1000 |> ok in let state = Runner.create ~run_id:(run_id "financing") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "1000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "1000") ] ()) ~strategy_state |> ok in diff --git a/test/test_order_lifetimes.ml b/test/test_order_lifetimes.ml index 2ba0f4c..a464ff5 100644 --- a/test/test_order_lifetimes.ml +++ b/test/test_order_lifetimes.ml @@ -9,8 +9,9 @@ let runner ?(initial_cash = "10000") ?(risk = risk ()) ?(venue_calendars = []) schedule = let strategy_state = T.Scripted_strategy.create schedule |> ok in Runner.create ~run_id:(run_id "lifetime-run") ~scenario_sha256 - ~config:(engine_config_v8 ~risk ~venue_calendars ()) - ~initial_cash:[ ("USD", money initial_cash) ] + ~config:(engine_config ~risk ~venue_calendars ()) + ~initial_portfolio: + (initial_portfolio ~cash:[ ("USD", money initial_cash) ] ()) ~strategy_state |> ok @@ -34,21 +35,11 @@ let calendar ?(venue = "XNAS") ?(covered_instrument = "test-equity") () = ~sessions:[ session ] |> ok -let compatibility_mapping () = - let market = request () in - let limit = request ~kind:(T.Order.Limit (price "100")) () in - Alcotest.(check string) - "legacy market is IOC" "ioc" - (T.Order.time_in_force_to_string market.time_in_force); - Alcotest.(check string) - "legacy limit is GTC" "gtc" - (T.Order.time_in_force_to_string limit.time_in_force) - let validates_stop_limit_and_gtd () = Alcotest.(check bool) "invalid buy stop-limit" true (Result.is_error - (T.Order.request_v8 + (T.Order.request ~instrument_id:(instrument_id "test-equity") ~side:T.Order.Buy ~quantity:(quantity "1") ~kind: @@ -56,9 +47,7 @@ let validates_stop_limit_and_gtd () = { trigger_price = price "100"; limit_price = price "99" }) ~time_in_force:T.Order.Gtc ~origin:T.Order.Direct)); let request = - request_v8 - ~time_in_force:(T.Order.Gtd (timestamp "2026-01-02T20:00:00Z")) - () + request ~time_in_force:(T.Order.Gtd (timestamp "2026-01-02T20:00:00Z")) () in Alcotest.(check bool) "expiry follows creation" true @@ -68,7 +57,7 @@ let validates_stop_limit_and_gtd () = ~created_at:(timestamp "2026-01-02T21:00:00Z") ~eligible_after_slice_sequence:1L request)) -let v8_intent_requires_explicit_companions () = +let intent_requires_explicit_companions () = let intent = `Assoc [ @@ -87,7 +76,7 @@ let v8_intent_requires_explicit_companions () = in Alcotest.(check bool) "explicit stop/GTD parses" true - (Result.is_ok (T.Scenario.intent_of_yojson ~contract_version:"8" intent)); + (Result.is_ok (T.Scenario.intent_of_yojson intent)); let missing_trigger = match intent with | `Assoc fields -> `Assoc (List.remove_assoc "trigger_price" fields) @@ -95,8 +84,7 @@ let v8_intent_requires_explicit_companions () = in Alcotest.(check bool) "missing companion is rejected" true - (Result.is_error - (T.Scenario.intent_of_yojson ~contract_version:"8" missing_trigger)); + (Result.is_error (T.Scenario.intent_of_yojson missing_trigger)); let submit kind trigger limit tif venue calendar expires = `Assoc [ @@ -125,34 +113,34 @@ let v8_intent_requires_explicit_companions () = List.iter (fun json -> Alcotest.(check bool) - "v8 order variant parses" true - (Result.is_ok (T.Scenario.intent_of_yojson ~contract_version:"8" json))) + "order variant parses" true + (Result.is_ok (T.Scenario.intent_of_yojson json))) valid; Alcotest.(check bool) "inconsistent TIF companions rejected" true (Result.is_error - (T.Scenario.intent_of_yojson ~contract_version:"8" + (T.Scenario.intent_of_yojson (submit "market" `Null `Null "gtc" (`String "XNAS") `Null `Null))) let order_validation_and_serialization_branches () = Alcotest.(check bool) "nonpositive quantity rejected" true (Result.is_error - (T.Order.request_v8 + (T.Order.request ~instrument_id:(instrument_id "test-equity") ~side:T.Order.Buy ~quantity:T.Scalar.Quantity.zero ~kind:T.Order.Market ~time_in_force:T.Order.Gtc ~origin:T.Order.Direct)); Alcotest.(check bool) "invalid sell stop-limit rejected" true (Result.is_error - (T.Order.request_v8 + (T.Order.request ~instrument_id:(instrument_id "test-equity") ~side:T.Order.Sell ~quantity:(quantity "1") ~kind: (T.Order.Stop_limit { trigger_price = price "100"; limit_price = price "101" }) ~time_in_force:T.Order.Gtc ~origin:T.Order.Direct)); - let ordinary = request_v8 () in + let ordinary = current_request () in Alcotest.(check bool) "negative accepted sequence rejected" true (Result.is_error @@ -198,7 +186,7 @@ let order_validation_and_serialization_branches () = in List.iteri (fun index (kind, time_in_force) -> - let request = request_v8 ~kind ~time_in_force () in + let request = current_request ~kind ~time_in_force () in ignore (T.Order.kind_to_string kind); ignore (T.Order.time_in_force_to_string time_in_force); let order = @@ -206,14 +194,14 @@ let order_validation_and_serialization_branches () = in ignore (T.Order.is_market order); ignore (T.Order.effective_kind order); - match T.Codec.order_to_yojson_v8 order with + match T.Codec.order_to_yojson order with | `Assoc fields -> Alcotest.(check bool) "TIF serialized" true (List.mem_assoc "time_in_force" fields) | _ -> Alcotest.fail "serialized order must be an object") cases; - let unconditional = accepted_order (request_v8 ()) in + let unconditional = accepted_order (current_request ()) in Alcotest.(check bool) "unconditional order cannot trigger" true (Result.is_error @@ -222,7 +210,7 @@ let order_validation_and_serialization_branches () = ~triggered_at:(timestamp "2026-01-03T20:00:00Z") ~triggered_slice_sequence:2L)); let conditional = - accepted_order (request_v8 ~kind:(T.Order.Stop (price "110")) ()) + accepted_order (current_request ~kind:(T.Order.Stop (price "110")) ()) in Alcotest.(check bool) "negative trigger sequence rejected" true @@ -237,7 +225,7 @@ let order_validation_and_serialization_branches () = ~triggered_slice_sequence:2L |> ok in - ignore (T.Codec.order_to_yojson_v8 triggered); + ignore (T.Codec.order_to_yojson triggered); Alcotest.(check bool) "duplicate trigger rejected" true (Result.is_error @@ -259,7 +247,9 @@ let order_validation_and_serialization_branches () = let trigger_then_execute_on_following_slice () = let request = - request_v8 ~kind:(T.Order.Stop (price "110")) ~time_in_force:T.Order.Gtc () + current_request + ~kind:(T.Order.Stop (price "110")) + ~time_in_force:T.Order.Gtc () in let oms, order = oms_with_order request in let trigger_slice = @@ -317,7 +307,7 @@ let trigger_then_execute_on_following_slice () = let stop_limit_uses_limit_after_trigger () = let request = - request_v8 + request ~kind: (T.Order.Stop_limit { trigger_price = price "110"; limit_price = price "111" }) @@ -363,7 +353,7 @@ let stop_limit_uses_limit_after_trigger () = let sell_stop_gap_and_partial_fill () = let request = - request_v8 ~side:T.Order.Sell ~quantity_value:"10" + current_request ~side:T.Order.Sell ~quantity_value:"10" ~kind:(T.Order.Stop (price "90")) () in @@ -412,7 +402,9 @@ let sell_stop_gap_and_partial_fill () = | _ -> Alcotest.fail "expected one partial sell-stop fill" let fok_is_all_or_cancel () = - let request = request_v8 ~quantity_value:"10" ~time_in_force:T.Order.Fok () in + let request = + current_request ~quantity_value:"10" ~time_in_force:T.Order.Fok () + in let oms, order = oms_with_order request in let matched = T.Execution.match_slice (execution ()) @@ -427,7 +419,7 @@ let fok_is_all_or_cancel () = let split_adjusts_stop_prices () = let request = - request_v8 ~quantity_value:"10" + current_request ~quantity_value:"10" ~kind: (T.Order.Stop_limit { trigger_price = price "110"; limit_price = price "112" }) @@ -450,7 +442,9 @@ let split_adjusts_stop_prices () = let engine_audits_trigger_and_defers_fill () = let request = - request_v8 ~kind:(T.Order.Stop (price "110")) ~time_in_force:T.Order.Gtc () + current_request + ~kind:(T.Order.Stop (price "110")) + ~time_in_force:T.Order.Gtc () in let state = runner [ (1L, [ T.Strategy.Submit_order request ]) ] in let state, _ = Runner.process_slice state (market_slice 1L) |> ok in @@ -482,7 +476,7 @@ let engine_audits_trigger_and_defers_fill () = let gtd_and_day_expire_deterministically () = let gtd = - request_v8 + request ~kind:(T.Order.Limit (price "90")) ~time_in_force:(T.Order.Gtd (timestamp "2026-01-03T20:00:00Z")) () @@ -509,7 +503,7 @@ let gtd_and_day_expire_deterministically () = (T.Audit.cancellation_reason_to_string reason); let calendar = calendar () in let day = - request_v8 + request ~kind:(T.Order.Stop (price "101")) ~time_in_force: (T.Order.Day @@ -555,7 +549,7 @@ let gtd_and_day_expire_deterministically () = (List.mem "fill_applied" (event_names expired)) let fok_rejects_risk_clipped_fill () = - let order = request_v8 ~time_in_force:T.Order.Fok () in + let order = current_request ~time_in_force:T.Order.Fok () in let state = runner ~initial_cash:"550" ~risk:(risk ~max_leverage:"1" ()) @@ -593,7 +587,7 @@ let fok_rejects_risk_clipped_fill () = let day_identity_is_validated () = let day venue = - request_v8 + request ~kind:(T.Order.Limit (price "90")) ~time_in_force: (T.Order.Day @@ -637,12 +631,10 @@ let day_identity_is_validated () = let tests = [ - Alcotest.test_case "legacy compatibility mapping" `Quick - compatibility_mapping; Alcotest.test_case "stop-limit and GTD validation" `Quick validates_stop_limit_and_gtd; - Alcotest.test_case "v8 intent companions" `Quick - v8_intent_requires_explicit_companions; + Alcotest.test_case "intent companions" `Quick + intent_requires_explicit_companions; Alcotest.test_case "order validation and serialization" `Quick order_validation_and_serialization_branches; Alcotest.test_case "stop triggers before later execution" `Quick diff --git a/test/test_reducer.ml b/test/test_reducer.ml index 46bbd74..06e9c1e 100644 --- a/test/test_reducer.ml +++ b/test/test_reducer.ml @@ -9,7 +9,8 @@ let runner ?contract_version ?(initial_cash = "10000") ?(risk = risk ()) engine_config ?contract_version ~risk ?execution_model ~execution () in Runner.create ~run_id:(run_id "test-run") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money initial_cash) ] + ~initial_portfolio: + (initial_portfolio ~cash:[ ("USD", money initial_cash) ] ()) ~strategy_state |> ok @@ -49,6 +50,8 @@ let market_order_retries_after_partial_fill () = "first audit order" [ "run_started"; + "initial_state"; + "valuation"; "market_slice_received"; "target_portfolio_requested"; "order_accepted"; @@ -74,6 +77,7 @@ let market_order_retries_after_partial_fill () = [ "market_slice_received"; "fill_applied"; + "settlement_instruction_created"; "order_cancelled"; "order_accepted"; "valuation"; @@ -186,112 +190,6 @@ let superseding_target_replaces_retry () = (event_names events))) | _ -> Alcotest.fail "expected one replacement order" -let fill_limit_clips_buy_to_lots ?(contract_version = T.Contract.version) () = - let constrained = risk ~max_leverage:"1" () in - let state = - runner ~contract_version ~initial_cash:"550" ~risk:constrained - ~execution:(execution ~fixed_fee:"10" ()) - [ (1L, [ target "10" ]) ] - in - let decision_bar = - bar ~open_price:"50" ~high_price:"50" ~low_price:"50" ~close_price:"50" 1L - in - let state, _ = - Runner.process_slice state (market_slice ~bars:[ decision_bar ] 1L) |> ok - in - let state, events = - Runner.process_slice state - (market_slice ~bars:[ bar ~open_price:"100" ~close_price:"100" 2L ] 2L) - |> ok - in - Alcotest.check quantity_testable "five risk-permitted shares" (quantity "5") - (T.Account.position_quantity (Runner.account state) - (instrument_id "test-equity")); - Alcotest.check money_testable "cash after clipped fill" (money "40") - (account_cash (Runner.account state)); - let limited = - List.find - (fun audit -> - String.equal (T.Audit.event_name audit.T.Audit.event) "fill_clipped") - events - in - Alcotest.(check string) - "fill-clipped contract version" contract_version limited.contract_version; - match limited.event with - | T.Audit.Fill_clipped - { - proposed_quantity; - permitted_quantity; - price = fill_price; - limit = T.Risk.Maximum_leverage threshold; - _; - } -> - Alcotest.check quantity_testable "ten proposed" (quantity "10") - proposed_quantity; - Alcotest.check quantity_testable "five permitted" (quantity "5") - permitted_quantity; - Alcotest.check price_testable "actual price" (price "100") fill_price; - Alcotest.(check string) - "leverage threshold" "1" - (T.Scalar.Ratio.to_decimal_string threshold) - | _ -> Alcotest.fail "expected leverage clipping audit" - -let v4_replays_keep_the_fill_clipped_record () = - fill_limit_clips_buy_to_lots ~contract_version:T.Contract.previous_version () - -let v3_replays_keep_the_legacy_clipping_record () = - let constrained = risk ~max_leverage:"1" () in - let state = - runner ~contract_version:T.Contract.legacy_journal_version - ~initial_cash:"550" ~risk:constrained - ~execution:(execution ~fixed_fee:"10" ()) - [ (1L, [ target "10" ]) ] - in - let decision_bar = - bar ~open_price:"50" ~high_price:"50" ~low_price:"50" ~close_price:"50" 1L - in - let state, _ = - Runner.process_slice state (market_slice ~bars:[ decision_bar ] 1L) |> ok - in - let _, events = - Runner.process_slice state - (market_slice ~bars:[ bar ~open_price:"100" ~close_price:"100" 2L ] 2L) - |> ok - in - let limited = - List.find - (fun audit -> - String.equal (T.Audit.event_name audit.T.Audit.event) "margin_limited") - events - in - Alcotest.(check string) - "legacy journal version" T.Contract.legacy_journal_version - limited.contract_version; - match limited.event with - | T.Audit.Margin_limited { requested_quantity; permitted_quantity; _ } -> - Alcotest.check quantity_testable "legacy requested" (quantity "10") - requested_quantity; - Alcotest.check quantity_testable "legacy permitted" (quantity "5") - permitted_quantity - | _ -> Alcotest.fail "expected legacy margin_limited audit" - -let invalid_fill_candidates_fail_instead_of_clipping () = - let constrained = risk ~max_leverage:"1" () in - let state = - runner ~initial_cash:"9223372036854.775807" ~risk:constrained - [ - ( 1L, - [ - T.Strategy.Submit_order - (request ~side:T.Order.Sell ~quantity_value:"1" ()); - ] ); - ] - in - let state, _ = Runner.process_slice state (market_slice 1L) |> ok in - Alcotest.(check string) - "account overflow is not a clipping policy" "int64 addition overflow" - (Runner.process_slice state (market_slice 2L) |> error) - let sells_precede_buys_in_the_same_slice () = let a = instrument ~id:"asset-a" ~symbol:"A" () in let b = instrument ~id:"asset-b" ~symbol:"B" () in @@ -311,6 +209,7 @@ let sells_precede_buys_in_the_same_slice () = in let state = runner ~initial_cash:"1000" ~risk:configured + ~execution:(execution ~instruments:[ a; b ] ()) [ (1L, [ portfolio "10" "0" ]); (2L, [ portfolio "0" "10" ]) ] in let state, _ = @@ -349,7 +248,7 @@ let interactive_market_slice_timeline_is_non_overlapping () = let initial = T.Engine.Interactive.create ~run_id:(run_id "timeline-test") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) |> ok in let rec finish progress = @@ -400,7 +299,7 @@ let internal_feedback_is_capped () = let config = engine_config ~max_internal_events:3 () in let state = Looping_runner.create ~run_id:(run_id "loop") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok in @@ -413,7 +312,7 @@ let exact_internal_event_limit_succeeds () = let config = engine_config ~max_internal_events:1 () in let state = Runner.create ~run_id:(run_id "one-event") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok in @@ -433,7 +332,7 @@ let reducer_feedback_queue_handles_large_batches () = let config = engine_config ~max_internal_events () in let state = Runner.create ~run_id:(run_id "large-feedback") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) ~strategy_state |> ok in @@ -448,7 +347,7 @@ let reducer_feedback_queue_handles_large_batches () = in Alcotest.(check int) "every intent rejected" batch_size rejection_count; Alcotest.(check int) - "batch completes at the exact feedback limit" (batch_size + 3) + "batch completes at the exact feedback limit" (batch_size + 5) (List.length events) let completed_run_is_terminal_and_hash_bound () = @@ -456,7 +355,7 @@ let completed_run_is_terminal_and_hash_bound () = let state, valuation, events = Runner.complete state |> ok in Alcotest.(check (list string)) "start and completion events" - [ "run_started"; "run_completed" ] + [ "run_started"; "initial_state"; "valuation"; "run_completed" ] (event_names events); Alcotest.check money_testable "initial equity" (money "10000") valuation.equity; @@ -476,18 +375,12 @@ let completed_run_is_terminal_and_hash_bound () = let invalid_initial_state_is_rejected () = let strategy_state = T.Scripted_strategy.create [] |> ok in let config = engine_config () in - Alcotest.(check bool) - "negative cash rejected" true - (Result.is_error - (Runner.create ~run_id:(run_id "bad-cash") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "-1") ] - ~strategy_state)); Alcotest.(check bool) "noncanonical hash rejected" true (Result.is_error (Runner.create ~run_id:(run_id "bad-hash") ~scenario_sha256:(String.make 64 'A') ~config - ~initial_cash:[ ("USD", money "1") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "1") ] ()) ~strategy_state)) let one_valuation_per_slice () = @@ -500,7 +393,7 @@ let one_valuation_per_slice () = (fun name -> String.equal name "valuation") (event_names events)) in - Alcotest.(check int) "first slice" 1 (count first); + Alcotest.(check int) "initial state and first slice" 2 (count first); Alcotest.(check int) "second slice" 1 (count second) module No_fill_execution = struct @@ -546,21 +439,19 @@ let execution_model_configuration_must_match () = |> ok in let configure contract_version execution_model execution = - T.Engine.config ~contract_version ~risk:(risk ()) ~execution_model - ~execution ~max_internal_events:1000 + T.Engine.config ~contract_version ~risk:(risk ()) ~venue_calendars:[] + ~execution_model ~execution ~financing:(financing_policy ()) + ~settlement:(settlement_policy ()) ~max_internal_events:1000 in Alcotest.(check bool) "conservative model requires pricing configuration" true - (Result.is_error (configure "13" next_open (execution ()))); + (Result.is_error (configure "1" next_open (execution ()))); Alcotest.(check bool) - "legacy model rejects conservative pricing" true - (Result.is_error (configure "13" completed conservative)); - Alcotest.(check bool) - "conservative model is v13-only" true - (Result.is_error (configure "12" next_open conservative)); + "completed-bar model rejects conservative pricing" true + (Result.is_error (configure "1" completed conservative)); Alcotest.(check bool) "matching conservative configuration accepted" true - (Result.is_ok (configure "13" next_open conservative)) + (Result.is_ok (configure "1" next_open conservative)) module Cancel_next_strategy = struct type state = { submitted : bool; cancelled : bool } @@ -592,8 +483,12 @@ module Cancel_next_runner = T.Engine.Make (Cancel_next_strategy) let callbacks_use_current_slice_and_apply_responses_before_matching () = let configured = instrument ~currency:"EUR" () in let configured_risk = risk ~instruments:[ configured ] () in - let config = engine_config ~risk:configured_risk () in - let initial_cash = [ ("USD", money "10000"); ("EUR", money "0") ] in + let config = + engine_config ~risk:configured_risk + ~execution:(execution ~instruments:[ configured ] ()) + () + in + let initial_cash = [ ("USD", money "0"); ("EUR", money "10000") ] in let first_slice = market_slice ~bars:[ bar ~close_price:"104" 1L ] @@ -616,7 +511,9 @@ let callbacks_use_current_slice_and_apply_responses_before_matching () = let scripted = Cancel_next_runner.create ~run_id:(run_id "callback-consistency") - ~scenario_sha256 ~config ~initial_cash ~strategy_state + ~scenario_sha256 ~config + ~initial_portfolio:(initial_portfolio ~cash:initial_cash ()) + ~strategy_state |> ok in let scripted, _ = @@ -628,7 +525,8 @@ let callbacks_use_current_slice_and_apply_responses_before_matching () = let interactive = T.Engine.Interactive.create ~run_id:(run_id "callback-consistency") - ~scenario_sha256 ~config ~initial_cash + ~scenario_sha256 ~config + ~initial_portfolio:(initial_portfolio ~cash:initial_cash ()) |> ok in let rec finish_first submitted progress = @@ -746,7 +644,7 @@ let interactive_reducer_matches_scripted_strategy () = let interactive = T.Engine.Interactive.create ~run_id:(run_id "test-run") ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money "10000") ] + ~initial_portfolio:(initial_portfolio ~cash:[ ("USD", money "10000") ] ()) |> ok in let progress = @@ -812,6 +710,7 @@ let explicit_phase_order_is_stable () = "market_slice_received"; "cash_dividend_applied"; "fill_applied"; + "settlement_instruction_created"; "metric_emitted"; "target_portfolio_requested"; "order_accepted"; @@ -830,14 +729,6 @@ let tests = bounded_target_orders_make_progress; Alcotest.test_case "superseding target replaces retry" `Quick superseding_target_replaces_retry; - Alcotest.test_case "fill clipping identifies leverage" `Quick - fill_limit_clips_buy_to_lots; - Alcotest.test_case "v4 keeps fill clipping records" `Quick - v4_replays_keep_the_fill_clipped_record; - Alcotest.test_case "v3 keeps legacy clipping records" `Quick - v3_replays_keep_the_legacy_clipping_record; - Alcotest.test_case "invalid fill candidates fail" `Quick - invalid_fill_candidates_fail_instead_of_clipping; Alcotest.test_case "same-slice sells precede buys" `Quick sells_precede_buys_in_the_same_slice; Alcotest.test_case "external ordering validation" `Quick diff --git a/test/test_reducer_properties.ml b/test/test_reducer_properties.ml index 9135a12..42edfd0 100644 --- a/test/test_reducer_properties.ml +++ b/test/test_reducer_properties.ml @@ -218,22 +218,17 @@ let gen_trace = (list_size (int_range 4 14) gen_step))) let make_risk trace = - T.Risk.create ~base_currency:"USD" ~instruments:[ primary; foreign ] - ~max_order_quantity:(quantity "50") ~max_long_position:(quantity "100") - ~max_short_position:(quantity "100") ~max_gross_exposure:(money "50000") - ~max_leverage: - (T.Scalar.Ratio.of_decimal_string - (decimal_of_scaled trace.leverage_tenths 10) - |> ok) + risk ~instruments:[ primary; foreign ] ~max_order:"50" ~max_long:"100" + ~max_short:"100" ~max_gross:"50000" + ~max_leverage:(decimal_of_scaled trace.leverage_tenths 10) ~initial_margin_bps:trace.initial_margin_bps - ~maintenance_margin_bps:trace.maintenance_margin_bps ~short_borrow_bps:250 - |> ok + ~maintenance_margin_bps:trace.maintenance_margin_bps () let make_config trace risk = engine_config ~risk ~execution: - (execution ~participation_bps:trace.participation_bps ~fixed_fee:"0.25" - ~fee_bps:5 ()) + (execution ~participation_bps:trace.participation_bps + ~instruments:[ primary; foreign ] ()) ~max_internal_events:5000 () let initial_cash = [ ("USD", money "10000"); ("EUR", money "5000") ] @@ -693,9 +688,10 @@ let slice_valuation audits = | T.Audit.Valuation value -> Some value | _ -> None) audits + |> List.rev |> function - | [ valuation ] -> Ok valuation - | _ -> Error "slice did not emit exactly one valuation" + | valuation :: _ -> Ok valuation + | [] -> Error "slice did not emit a valuation" let check_fill oms audit = match audit.T.Audit.event with @@ -743,7 +739,9 @@ let reducer_invariants_hold trace = let config = make_config trace risk in let state = Generated_runner.create ~run_id:(run_id "property-run") ~scenario_sha256 - ~config ~initial_cash ~strategy_state:(schedule trace) + ~config + ~initial_portfolio:(initial_portfolio ~cash:initial_cash ()) + ~strategy_state:(schedule trace) |> ok in let rec loop index history state = function @@ -841,13 +839,16 @@ let reducers_agree trace = let scripted = Generated_runner.create ~run_id:(run_id "property-equivalence") - ~scenario_sha256 ~config ~initial_cash ~strategy_state + ~scenario_sha256 ~config + ~initial_portfolio:(initial_portfolio ~cash:initial_cash ()) + ~strategy_state |> ok in let interactive = T.Engine.Interactive.create ~run_id:(run_id "property-equivalence") - ~scenario_sha256 ~config ~initial_cash + ~scenario_sha256 ~config + ~initial_portfolio:(initial_portfolio ~cash:initial_cash ()) |> ok in let compare_slice index scripted interactive audits scripted_audits = diff --git a/test/test_repository_metadata.py b/test/test_repository_metadata.py index 3b76053..7509720 100644 --- a/test/test_repository_metadata.py +++ b/test/test_repository_metadata.py @@ -19,8 +19,7 @@ def test_repository_profile_is_specific_and_bounded(self) -> None: self.assertEqual( profile["description"], - "Deterministic event-driven OCaml execution engine with versioned replay contracts " - "and causal audit journals", + "Deterministic OCaml trading replay engine", ) self.assertEqual(profile["homepage"], "https://fallblu.github.io/trading-engine/") self.assertEqual( @@ -75,13 +74,13 @@ def test_label_manifest_covers_stable_planning_dimensions(self) -> None: self.assertEqual(len(names), len(set(names))) self.assertEqual( categories, - {"component": 10, "priority": 4, "effort": 3, "contract": 7, "dependency": 3}, + {"component": 10, "priority": 4, "effort": 3, "contract": 2, "dependency": 3}, ) self.assertTrue(all(re.fullmatch(r"[0-9a-f]{6}", label["color"]) for label in labels)) self.assertTrue(all(label["description"].strip() for label in labels)) self.assertIn("dependency: persistra", names) - self.assertIn("contract: scenario-v4", names) - self.assertIn("contract: strategy-v3", names) + self.assertIn("contract: scenario-v1", names) + self.assertIn("contract: strategy-v1", names) def test_structured_forms_reference_defined_labels_and_require_evidence(self) -> None: template_directory = GITHUB / "ISSUE_TEMPLATE" @@ -120,7 +119,7 @@ def test_pull_request_and_support_templates_preserve_required_sections(self) -> def test_compatibility_gate_is_pinned_and_canary_is_optional(self) -> None: workflow = (GITHUB / "workflows/ci.yml").read_text(encoding="utf-8") - revision = "ade8c05e435c56d8df8eba88fed1284652fd731b" + revision = "6874e175098519eef9904edf0bb9f27b244982e4" self.assertIn(f"PERSISTRA_COMPAT_REVISION: {revision}", workflow) self.assertIn("ref: ${{ env.PERSISTRA_COMPAT_REVISION }}", workflow) @@ -142,9 +141,11 @@ def test_compatibility_gate_is_pinned_and_canary_is_optional(self) -> None: self.assertTrue(all(re.fullmatch(r"[0-9a-f]{40}", revision) for revision in revisions)) compatibility = (REPOSITORY_ROOT / "docs/persistra.md").read_text(encoding="utf-8") - for guarantee in ("Engine", "Scenario", "Journal", "Strategy", "Persistra"): - self.assertIn(f"**{guarantee}:**", compatibility) - self.assertIn("Neither repository silently advances", compatibility) + self.assertIn("versioned files and processes", compatibility) + self.assertIn("scenario contract v1", compatibility) + self.assertIn("explicit pair of repository commits", compatibility) + self.assertIn("Neither repository", compatibility) + self.assertIn("silently follows a moving branch", compatibility) if __name__ == "__main__": diff --git a/test/test_risk_groups.ml b/test/test_risk_groups.ml index 1269510..891d1cb 100644 --- a/test/test_risk_groups.ml +++ b/test/test_risk_groups.ml @@ -40,10 +40,9 @@ let setup ?(groups = []) ?(shorting_allowed = true) () = ] in let risk = - T.Risk.create_v7 ~base_currency:"USD" ~instruments:[ first; second ] + T.Risk.create ~base_currency:"USD" ~instruments:[ first; second ] ~instrument_policies:policies ~groups ~max_gross_exposure:(money "100000") ~max_leverage:(T.Scalar.Ratio.of_decimal_string "10" |> ok) - ~short_borrow_bps:0 |> ok in (first, second, risk) @@ -52,11 +51,10 @@ let exact_coverage_and_short_policy () = let first = instrument ~id:"first" ~symbol:"FIRST" () in let second = instrument ~id:"second" ~symbol:"SECOND" () in let result = - T.Risk.create_v7 ~base_currency:"USD" ~instruments:[ first; second ] + T.Risk.create ~base_currency:"USD" ~instruments:[ first; second ] ~instrument_policies:[ policy first () ] ~groups:[] ~max_gross_exposure:(money "100000") ~max_leverage:(T.Scalar.Ratio.of_decimal_string "10" |> ok) - ~short_borrow_bps:0 in Alcotest.(check string) "policy required for every instrument" @@ -141,7 +139,7 @@ let initialized_positions_use_instrument_margin_and_groups () = let second = instrument ~id:"second" ~symbol:"SECOND" () in let group_limit = limits ~gross:"150" () in let risk = - T.Risk.create_v7 ~base_currency:"USD" ~instruments:[ first; second ] + T.Risk.create ~base_currency:"USD" ~instruments:[ first; second ] ~instrument_policies: [ policy first ~initial_margin_bps:10_000 ~maintenance_margin_bps:5000 @@ -151,7 +149,6 @@ let initialized_positions_use_instrument_margin_and_groups () = ~groups:[ group "initial-group" [ first; second ] group_limit ] ~max_gross_exposure:(money "100000") ~max_leverage:(T.Scalar.Ratio.of_decimal_string "10" |> ok) - ~short_borrow_bps:0 |> ok in let account = test_account () in @@ -195,7 +192,7 @@ let reserved_result ?(side = T.Order.Buy) ?(initial_cash = "10000") group_limits) in let risk = - T.Risk.create_v7 ~base_currency:"USD" ~instruments:[ first; second ] + T.Risk.create ~base_currency:"USD" ~instruments:[ first; second ] ~instrument_policies: [ policy first ~max_long ~max_short ~max_notional ~shorting_allowed @@ -206,7 +203,6 @@ let reserved_result ?(side = T.Order.Buy) ?(initial_cash = "10000") ] ~groups ~max_gross_exposure:(money max_gross) ~max_leverage:(T.Scalar.Ratio.of_decimal_string max_leverage |> ok) - ~short_borrow_bps:0 |> ok in let account = test_account ~initial_cash:[ ("USD", money initial_cash) ] () in @@ -328,7 +324,7 @@ let constructors_reject_ambiguous_policies () = ~group_kind:T.Risk.Custom ~instrument_ids:[ first.id; first.id ] ~limits:valid_limits)) -let create_v7_rejects_inconsistent_configuration () = +let create_rejects_inconsistent_configuration () = let first = instrument ~id:"first" ~symbol:"FIRST" () in let second = instrument ~id:"second" ~symbol:"SECOND" () in let first_policy = policy first () in @@ -341,22 +337,19 @@ let create_v7_rejects_inconsistent_configuration () = in let create ?(base_currency = "USD") ?(instruments = [ first; second ]) ?(policies = [ first_policy; second_policy ]) ?(groups = [ valid_group ]) - ?(max_gross = "100000") ?(short_borrow_bps = 0) () = - T.Risk.create_v7 ~base_currency ~instruments ~instrument_policies:policies + ?(max_gross = "100000") () = + T.Risk.create ~base_currency ~instruments ~instrument_policies:policies ~groups ~max_gross_exposure:(money max_gross) ~max_leverage:(T.Scalar.Ratio.of_decimal_string "10" |> ok) - ~short_borrow_bps in List.iter (fun result -> Alcotest.(check bool) - "invalid v7 configuration" true (Result.is_error result)) + "invalid risk configuration" true (Result.is_error result)) [ create ~base_currency:"" (); create ~instruments:[] ~policies:[] ~groups:[] (); create ~max_gross:"0" (); - create ~short_borrow_bps:(-1) (); - create ~short_borrow_bps:10_001 (); create ~instruments:[ first; first ] (); create ~policies:[ first_policy; unknown_policy ] (); create ~policies:[ first_policy; first_policy ] (); @@ -379,7 +372,7 @@ let admission_result ?(side = T.Order.Buy) ?(initial_cash = "10000") group_limits) in let risk = - T.Risk.create_v7 ~base_currency:"USD" ~instruments:[ first; second ] + T.Risk.create ~base_currency:"USD" ~instruments:[ first; second ] ~instrument_policies: [ policy first ~max_order ~max_long ~max_short ~max_notional @@ -390,7 +383,6 @@ let admission_result ?(side = T.Order.Buy) ?(initial_cash = "10000") ] ~groups ~max_gross_exposure:(money max_gross) ~max_leverage:(T.Scalar.Ratio.of_decimal_string max_leverage |> ok) - ~short_borrow_bps:0 |> ok in T.Risk.check risk @@ -400,7 +392,7 @@ let admission_result ?(side = T.Order.Buy) ?(initial_cash = "10000") ~fx_rates:[ ("USD", price "1") ] (request ~instrument:first.id ~side ~quantity_value:"10" ()) -let admission_enforces_every_v7_limit () = +let admission_enforces_every_limit () = let check_error expected result = Alcotest.(check string) "admission error" expected (error result) in @@ -436,12 +428,11 @@ let group_exposures_include_short_and_zero_equity () = let first = instrument ~id:"first" ~symbol:"FIRST" () in let second = instrument ~id:"second" ~symbol:"SECOND" () in let risk = - T.Risk.create_v7 ~base_currency:"USD" ~instruments:[ first; second ] + T.Risk.create ~base_currency:"USD" ~instruments:[ first; second ] ~instrument_policies:[ policy first (); policy second () ] ~groups:[ group "group" [ first ] (limits ~gross:"100000" ()) ] ~max_gross_exposure:(money "100000") ~max_leverage:(T.Scalar.Ratio.of_decimal_string "10" |> ok) - ~short_borrow_bps:0 |> ok in let order = @@ -476,7 +467,7 @@ let initial_result ?(side = T.Order.Buy) ?(initial_cash = "10000") group_limits) in let risk = - T.Risk.create_v7 ~base_currency:"USD" ~instruments:[ first; second ] + T.Risk.create ~base_currency:"USD" ~instruments:[ first; second ] ~instrument_policies: [ policy first ~max_long ~max_short ~max_notional ~shorting_allowed @@ -487,7 +478,6 @@ let initial_result ?(side = T.Order.Buy) ?(initial_cash = "10000") ] ~groups ~max_gross_exposure:(money max_gross) ~max_leverage:(T.Scalar.Ratio.of_decimal_string max_leverage |> ok) - ~short_borrow_bps:0 |> ok in let order = @@ -504,7 +494,7 @@ let initial_result ?(side = T.Order.Buy) ?(initial_cash = "10000") in T.Risk.check_initial risk valuation -let initial_portfolio_enforces_every_v7_limit () = +let initial_portfolio_enforces_every_limit () = let check_error expected result = Alcotest.(check string) "initial portfolio error" expected (error result) in @@ -535,25 +525,35 @@ let initial_portfolio_enforces_every_v7_limit () = initial_result ~group_limits:(limits ~concentration:"0.05" ()) () |> check_error "initial portfolio exceeds group group-a maximum concentration" -let legacy_and_policy_boundaries_are_rejected () = +let risk_and_policy_boundaries_are_rejected () = let first = instrument ~id:"first" ~symbol:"FIRST" () in let large_lot = instrument ~id:"large" ~symbol:"LARGE" ~lot_size:"2" () in let ratio = T.Scalar.Ratio.of_decimal_string "10" |> ok in let create ?(base_currency = "USD") ?(instruments = [ first ]) ?(max_order = "10") ?(max_long = "10") ?(max_short = "10") - ?(max_gross = "1000") ?(initial = 5000) ?(maintenance = 2500) - ?(borrow = 0) () = - T.Risk.create ~base_currency ~instruments - ~max_order_quantity:(quantity max_order) - ~max_long_position:(quantity max_long) - ~max_short_position:(quantity max_short) - ~max_gross_exposure:(money max_gross) ~max_leverage:ratio - ~initial_margin_bps:initial ~maintenance_margin_bps:maintenance - ~short_borrow_bps:borrow + ?(max_gross = "1000") ?(initial = 5000) ?(maintenance = 2500) () = + let instrument_policies = + List.map + (fun instrument -> + T.Risk.create_instrument_policy ~instrument + ~max_order_quantity:(quantity max_order) + ~max_long_position:(quantity max_long) + ~max_short_position:(quantity max_short) ~max_notional_exposure:None + ~initial_margin_bps:initial ~maintenance_margin_bps:maintenance + ~shorting_allowed:true) + instruments + in + match List.find_opt Result.is_error instrument_policies with + | Some (Error message) -> Error message + | Some (Ok _) -> assert false + | None -> + T.Risk.create ~base_currency ~instruments + ~instrument_policies:(List.map Result.get_ok instrument_policies) + ~groups:[] ~max_gross_exposure:(money max_gross) ~max_leverage:ratio in List.iter (fun result -> - Alcotest.(check bool) "invalid legacy risk" true (Result.is_error result)) + Alcotest.(check bool) "invalid risk" true (Result.is_error result)) [ create ~base_currency:"" (); create ~max_order:"0" (); @@ -565,8 +565,6 @@ let legacy_and_policy_boundaries_are_rejected () = create ~initial:10_001 (); create ~maintenance:10_001 (); create ~initial:1000 ~maintenance:2000 (); - create ~borrow:(-1) (); - create ~borrow:10_001 (); create ~instruments:[] (); create ~instruments:[ large_lot ] ~max_order:"1" (); create ~instruments:[ large_lot ] ~max_long:"1" (); @@ -594,29 +592,30 @@ let legacy_and_policy_boundaries_are_rejected () = ] let public_checks_cover_success_and_diagnostics () = - let legacy = risk ~max_order:"7" ~max_long:"7" ~max_short:"7" () in + let configured = risk ~max_order:"7" ~max_long:"7" ~max_short:"7" () in Alcotest.(check bool) "position accepted" true - (Result.is_ok (T.Risk.check_position legacy (quantity "7"))); + (Result.is_ok (T.Risk.check_position configured (quantity "7"))); Alcotest.(check string) "long rejected" "position would exceed the maximum long position" - (T.Risk.check_position legacy (quantity "8") |> error); + (T.Risk.check_position configured (quantity "8") |> error); Alcotest.(check string) "short rejected" "position would exceed the maximum short position" - (T.Risk.check_position legacy (quantity "-8") |> error); + (T.Risk.check_position configured (quantity "-8") |> error); Alcotest.(check string) "unknown policy" "position refers to an unknown instrument risk policy" - (T.Risk.check_position_for legacy (instrument_id "unknown") (quantity "1") + (T.Risk.check_position_for configured (instrument_id "unknown") + (quantity "1") |> error); let unknown_request = request ~instrument:(instrument_id "unknown") () in Alcotest.(check string) "unknown instrument" "order refers to an unknown instrument" - (T.Risk.check legacy ~account:(test_account ()) ~oms:T.Oms.empty ~marks:[] - ~fx_rates:[] unknown_request + (T.Risk.check configured ~account:(test_account ()) ~oms:T.Oms.empty + ~marks:[] ~fx_rates:[] unknown_request |> error); Alcotest.(check string) - "legacy order limit" "order exceeds the maximum order quantity" - (risk_check legacy ~account:(test_account ()) ~oms:T.Oms.empty + "order limit" "order exceeds the instrument maximum order quantity" + (risk_check configured ~account:(test_account ()) ~oms:T.Oms.empty (request ~quantity_value:"8" ()) |> error); (match reserved_result ~include_mark:false () with @@ -641,7 +640,7 @@ let public_checks_cover_success_and_diagnostics () = (Result.is_ok (admission_result ~group_limits:(limits ~gross:"10000" ()) ())) -let legacy_post_fill_covers_gross_and_reduction () = +let post_fill_covers_gross_and_reduction () = let first = instrument () in let before_account = test_account () in let before = @@ -660,7 +659,7 @@ let legacy_post_fill_covers_gross_and_reduction () = ~after_position:(quantity "10") ~before ~after with | Error (T.Risk.Limit (T.Risk.Maximum_gross_exposure _)) -> () - | _ -> Alcotest.fail "expected legacy gross fill limit"); + | _ -> Alcotest.fail "expected gross fill limit"); Alcotest.(check bool) "gross-reducing fill accepted" true (Result.is_ok @@ -681,18 +680,18 @@ let tests = clipping_taxonomy_is_exact; Alcotest.test_case "constructors reject ambiguous policies" `Quick constructors_reject_ambiguous_policies; - Alcotest.test_case "v7 rejects inconsistent configuration" `Quick - create_v7_rejects_inconsistent_configuration; - Alcotest.test_case "admission enforces every v7 limit" `Quick - admission_enforces_every_v7_limit; + Alcotest.test_case "current constructor rejects inconsistent configuration" + `Quick create_rejects_inconsistent_configuration; + Alcotest.test_case "admission enforces every current limit" `Quick + admission_enforces_every_limit; Alcotest.test_case "group exposures include short and zero equity" `Quick group_exposures_include_short_and_zero_equity; - Alcotest.test_case "initial portfolio enforces every v7 limit" `Quick - initial_portfolio_enforces_every_v7_limit; - Alcotest.test_case "legacy and policy boundaries are rejected" `Quick - legacy_and_policy_boundaries_are_rejected; + Alcotest.test_case "initial portfolio enforces every current limit" `Quick + initial_portfolio_enforces_every_limit; + Alcotest.test_case "risk and policy boundaries are rejected" `Quick + risk_and_policy_boundaries_are_rejected; Alcotest.test_case "public checks cover success and diagnostics" `Quick public_checks_cover_success_and_diagnostics; - Alcotest.test_case "legacy post-fill covers gross and reduction" `Quick - legacy_post_fill_covers_gross_and_reduction; + Alcotest.test_case "post-fill covers gross and reduction" `Quick + post_fill_covers_gross_and_reduction; ] diff --git a/test/test_scenario.ml b/test/test_scenario.ml index eebadba..1cf7428 100644 --- a/test/test_scenario.ml +++ b/test/test_scenario.ml @@ -2,21 +2,21 @@ open Test_support module T = Trading_engine let demo_document () = - In_channel.with_open_bin "../contracts/v16/fixtures/demo.scenario.json" + In_channel.with_open_bin "../contracts/v1/fixtures/demo.scenario.json" In_channel.input_all let demo () = T.Scenario.of_string (demo_document ()) |> ok let demo_hash () = T.Sha256.digest_string (demo_document ()) -let stream_path = "../contracts/v16/fixtures/demo.scenario.jsonl" -let quote_trade_path = "../contracts/v16/fixtures/quote-trade.scenario.json" +let stream_path = "../contracts/v1/fixtures/demo.scenario.jsonl" +let quote_trade_path = "../contracts/v1/fixtures/quote-trade.scenario.json" let quote_trade_stream_path = - "../contracts/v16/fixtures/quote-trade.scenario.jsonl" + "../contracts/v1/fixtures/quote-trade.scenario.jsonl" -let order_book_path = "../contracts/v16/fixtures/order-book.scenario.json" +let order_book_path = "../contracts/v1/fixtures/order-book.scenario.json" let order_book_stream_path = - "../contracts/v16/fixtures/order-book.scenario.jsonl" + "../contracts/v1/fixtures/order-book.scenario.jsonl" let stream_document () = In_channel.with_open_bin stream_path In_channel.input_all @@ -84,8 +84,7 @@ let write_large_stream path slice_count = ~effective_at:start_at ~credit_rate_bps:0 ~debit_rate_bps:0 |> ok in - T.Market_slice.create_v15 ~slice_sequence:(Int64.of_int index) - ~start_at + T.Market_slice.create ~slice_sequence:(Int64.of_int index) ~start_at ~end_at:(add_seconds base (offset + 1)) ~available_at:(add_seconds base (offset + 2)) ~received_at:(add_seconds base (offset + 3)) @@ -104,7 +103,7 @@ let write_large_stream path slice_count = let payload = `Assoc [ - ("market_slice", T.Codec.market_slice_to_yojson_v16 market_slice); + ("market_slice", T.Codec.market_slice_to_yojson market_slice); ("intents", `List []); ] in @@ -149,9 +148,9 @@ let schema_artifacts_parse () = (List.mem_assoc "$defs" fields) | _ -> Alcotest.fail (path ^ " must contain a JSON object") in - check_schema "../contracts/v16/scenario.schema.json"; - check_schema "../contracts/v16/scenario-stream.schema.json"; - check_schema "../contracts/v16/journal.schema.json" + check_schema "../contracts/v1/scenario.schema.json"; + check_schema "../contracts/v1/scenario-stream.schema.json"; + check_schema "../contracts/v1/journal.schema.json" let timestamp_precision_is_bounded () = List.iter @@ -191,7 +190,7 @@ let map_root change = let replace_assoc name value fields = (name, value) :: List.remove_assoc name fields -let v12_distributions_and_lifecycle_parse () = +let distributions_and_lifecycle_parse () = let source = instrument_id "demo-equity-acme" in let child = instrument_id "demo-equity-child" in let action name distribution_type destination fractional_policy = @@ -212,7 +211,7 @@ let v12_distributions_and_lifecycle_parse () = |> ok in let market_slice = - T.Market_slice.create_v15 ~slice_sequence:1L + T.Market_slice.create ~slice_sequence:1L ~start_at:(timestamp "2026-01-02T14:30:00Z") ~end_at:(timestamp "2026-01-02T20:55:00Z") ~available_at:(timestamp "2026-01-02T21:00:00Z") @@ -351,7 +350,7 @@ let v12_distributions_and_lifecycle_parse () = | _ -> Alcotest.fail "demo slice must be an object" in `List - (T.Codec.market_slice_to_yojson_v16 market_slice + (T.Codec.market_slice_to_yojson market_slice :: List.map add_child_bar rest) | _ -> Alcotest.fail "demo slices must be nonempty" in @@ -441,8 +440,7 @@ let contract_version_is_required_and_supported () = let unsupported_diagnostic = T.Scenario.of_yojson unsupported |> error in Alcotest.(check string) "unsupported version diagnosed" - "unsupported scenario contract_version \"2\" (expected one of 16, 15, 14, \ - 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3)" + "unsupported scenario contract_version \"2\" (expected one of 1)" (T.Diagnostic.to_human unsupported_diagnostic); Alcotest.(check string) "unsupported version code" "scenario.unsupported_contract" @@ -592,7 +590,7 @@ let dense_schedule_document slice_count = ~effective_at:start_at ~credit_rate_bps:100 ~debit_rate_bps:200 |> ok in - T.Market_slice.create_v15 ~slice_sequence:(Int64.of_int index) ~start_at + T.Market_slice.create ~slice_sequence:(Int64.of_int index) ~start_at ~end_at:(add_seconds base (time_offset + 1)) ~available_at:(add_seconds base (time_offset + 2)) ~received_at:(add_seconds base (time_offset + 3)) @@ -607,7 +605,7 @@ let dense_schedule_document slice_count = ~cash_rate_observations:[ cash_rate_observation ] ~settlement_failures:[] ~lifecycle_events:[] ~market_events:[] ~order_book_events:[] - |> ok |> T.Codec.market_slice_to_yojson_v16) + |> ok |> T.Codec.market_slice_to_yojson) in let schedule = List.init slice_count (fun offset -> @@ -703,8 +701,10 @@ let configured_resources_are_bounded () = "reducer configuration limit" true (Result.is_error (T.Engine.config ~contract_version:T.Contract.version ~risk:(risk ()) + ~venue_calendars:[] ~execution_model:(T.Execution_model.find "completed_bar_v1" |> ok) - ~execution:(execution ()) + ~execution:(execution ()) ~financing:(financing_policy ()) + ~settlement:(settlement_policy ()) ~max_internal_events:(T.Resource_limits.internal_events + 1))) let scenario_with_second_slice_start start_at = @@ -1154,10 +1154,19 @@ let audit_ids_are_deterministic_and_causal () = "fill cites price selection" [ "demo-event-000000000012" ] (cause_strings (event 13L)); + let completion = List.hd (List.rev result.audits) in + let terminal_valuation = + result.audits + |> List.filter (fun audit -> + Int64.compare audit.T.Audit.engine_sequence completion.engine_sequence + < 0 + && String.equal (T.Audit.event_name audit.event) "valuation") + |> List.rev |> List.hd + in Alcotest.(check (list string)) "completion cites terminal valuation" - [ "demo-event-000000000028" ] - (cause_strings (event 29L)); + [ T.Id.Event.to_string terminal_valuation.event_id ] + (cause_strings completion); match (event 8L).event with | T.Audit.Order_accepted order -> Alcotest.(check string) @@ -1196,36 +1205,15 @@ let replay_matches_golden_file () = |> fun value -> value ^ "\n" in let expected = - In_channel.with_open_bin "../contracts/v16/fixtures/demo.journal.jsonl" + In_channel.with_open_bin "../contracts/v1/fixtures/demo.journal.jsonl" In_channel.input_all in Alcotest.(check string) "stable audit contract" expected actual -let v3_replay_matches_frozen_golden_file () = - let document = - In_channel.with_open_bin "../contracts/v3/fixtures/demo.scenario.json" - In_channel.input_all - in - let scenario = T.Scenario.of_string document |> ok in - let result = - T.Replay.run ~scenario_sha256:(T.Sha256.digest_string document) scenario - |> ok - in - let actual = - result.audits |> List.map T.Codec.audit_to_string |> String.concat "\n" - |> fun value -> value ^ "\n" - in - let expected = - In_channel.with_open_bin "../contracts/v3/fixtures/demo.journal.jsonl" - In_channel.input_all - in - Alcotest.(check string) "frozen v3 audit contract" expected actual - let fill_clipping_fixture_reconciles () = let document = In_channel.with_open_bin - "../contracts/v16/fixtures/fill-clipped.scenario.json" - In_channel.input_all + "../contracts/v1/fixtures/fill-clipped.scenario.json" In_channel.input_all in let scenario = T.Scenario.of_string document |> ok in let result = @@ -1238,8 +1226,7 @@ let fill_clipping_fixture_reconciles () = in let expected = In_channel.with_open_bin - "../contracts/v16/fixtures/fill-clipped.journal.jsonl" - In_channel.input_all + "../contracts/v1/fixtures/fill-clipped.journal.jsonl" In_channel.input_all in Alcotest.(check string) "fill clipping audit reconciliation" expected actual @@ -1258,7 +1245,7 @@ let quote_trade_replay_is_causal_and_stream_equivalent () = in let golden = In_channel.with_open_bin - "../contracts/v16/fixtures/quote-trade.journal.jsonl" In_channel.input_all + "../contracts/v1/fixtures/quote-trade.journal.jsonl" In_channel.input_all in Alcotest.(check string) "quote/trade golden journal" golden batch_journal; let fills = @@ -1315,8 +1302,8 @@ let order_book_replay_is_bounded_and_stream_equivalent () = |> fun value -> value ^ "\n" in let golden = - In_channel.with_open_bin - "../contracts/v16/fixtures/order-book.journal.jsonl" In_channel.input_all + In_channel.with_open_bin "../contracts/v1/fixtures/order-book.journal.jsonl" + In_channel.input_all in Alcotest.(check string) "order-book golden journal" golden actual; let fills = @@ -1435,9 +1422,11 @@ let journal_matches_in_memory_events () = let streamed_replay_matches_batch_semantics () = let scenario_sha256 = T.Sha256.digest_file stream_path |> ok in + let expected_result = T.Replay.run ~scenario_sha256 (demo ()) |> ok in let expected = - T.Replay.run ~scenario_sha256 (demo ()) |> ok |> fun result -> - result.audits |> List.map T.Codec.audit_to_string |> String.concat "\n" + expected_result.audits + |> List.map T.Codec.audit_to_string + |> String.concat "\n" |> fun value -> value ^ "\n" in let journal = Filename.temp_file "trading-engine-stream" ".jsonl" in @@ -1454,7 +1443,10 @@ let streamed_replay_matches_batch_semantics () = Alcotest.(check int64) "four streamed slices" 4L result.slice_count; Alcotest.(check int64) "two schedule batches" 2L result.schedule_count; Alcotest.(check int) "one instrument" 1 result.instrument_count; - Alcotest.(check int64) "twenty-nine audits" 29L result.audit_count; + Alcotest.(check int64) + "same audit count" + (Int64.of_int (List.length expected_result.audits)) + result.audit_count; Alcotest.check money_testable "same equity" (money "10111.979929") result.valuation.equity; Alcotest.(check string) @@ -1657,8 +1649,8 @@ let large_stream_replay_does_not_retain_audit_history () = let tests = [ Alcotest.test_case "demo contract parses" `Quick demo_contract_parses; - Alcotest.test_case "v12 distributions and lifecycle parse" `Quick - v12_distributions_and_lifecycle_parse; + Alcotest.test_case "distributions and lifecycle parse" `Quick + distributions_and_lifecycle_parse; Alcotest.test_case "schema artifacts parse" `Quick schema_artifacts_parse; Alcotest.test_case "timestamp precision is bounded" `Quick timestamp_precision_is_bounded; @@ -1697,8 +1689,6 @@ let tests = replay_ends_with_completion_summary; Alcotest.test_case "replay matches golden file" `Quick replay_matches_golden_file; - Alcotest.test_case "v3 replay matches frozen golden file" `Quick - v3_replay_matches_frozen_golden_file; Alcotest.test_case "fill clipping fixture reconciles" `Quick fill_clipping_fixture_reconciles; Alcotest.test_case "quote/trade replay is causal and stream equivalent" diff --git a/test/test_settlement.ml b/test/test_settlement.ml index eb7fe85..3b3b4c1 100644 --- a/test/test_settlement.ml +++ b/test/test_settlement.ml @@ -60,7 +60,7 @@ let calendar_and_trade_date_accounting () = let slice ?(settlement_failures = []) sequence = let date = match sequence with 1L -> "02" | 2L -> "03" | _ -> "04" in - T.Market_slice.create_v11 ~slice_sequence:sequence + T.Market_slice.create ~slice_sequence:sequence ~start_at:(timestamp ("2026-01-" ^ date ^ "T14:30:00Z")) ~end_at:(timestamp ("2026-01-" ^ date ^ "T21:00:00Z")) ~available_at:(timestamp ("2026-01-" ^ date ^ "T21:00:01Z")) @@ -68,15 +68,15 @@ let slice ?(settlement_failures = []) sequence = ~bars:[ bar sequence ] ~fx_rates:[ fx_mark () ] ~corporate_actions:[] ~borrow_observations:[] ~cash_rate_observations:[] - ~settlement_failures + ~settlement_failures ~lifecycle_events:[] ~market_events:[] + ~order_book_events:[] |> ok let runner ?(initial_cash = "1000") ?schedule policy run = let config = - T.Engine.config_v11 ~contract_version:"11" ~risk:(risk ()) - ~venue_calendars:[] + T.Engine.config ~contract_version:"1" ~risk:(risk ()) ~venue_calendars:[] ~execution_model:(T.Execution_model.find "completed_bar_v1" |> ok) - ~execution:(execution ()) ~financing:T.Financing.legacy_policy + ~execution:(execution ()) ~financing:(financing_policy ()) ~settlement:policy ~max_internal_events:1000 |> ok in @@ -98,7 +98,8 @@ let runner ?(initial_cash = "1000") ?schedule policy run = in let strategy_state = T.Scripted_strategy.create schedule |> ok in Runner.create ~run_id:(run_id run) ~scenario_sha256 ~config - ~initial_cash:[ ("USD", money initial_cash) ] + ~initial_portfolio: + (initial_portfolio ~cash:[ ("USD", money initial_cash) ] ()) ~strategy_state |> ok diff --git a/test/test_strategy_protocol.ml b/test/test_strategy_protocol.ml index bec7710..903bdec 100644 --- a/test/test_strategy_protocol.ml +++ b/test/test_strategy_protocol.ml @@ -22,18 +22,17 @@ let initialization () = metadata = `Assoc [ ("experiment", `String "demo") ]; run_id = run_id "test-run"; base_currency = "USD"; - initial_cash = [ ("USD", money "10000") ]; - initial_portfolio = None; + initial_portfolio = initial_portfolio (); instruments = [ instrument ]; venue_calendars = []; risk = risk ~instruments:[ instrument ] (); execution_model = T.Execution_model.find "completed_bar_v1" |> ok; execution = - T.Execution.create_v2 ~participation_bps:10_000 + T.Execution.create ~participation_bps:10_000 ~fee_schedules:[ fee_schedule ] |> ok; - financing = Some T.Financing.legacy_policy; - settlement = None; + financing = financing_policy (); + settlement = settlement_policy (); } let field name = function @@ -45,7 +44,7 @@ let initialize_message_is_complete () = T.Strategy_protocol.initialize_message ~sequence:1L (initialization ()) in Alcotest.(check string) - "protocol version" "14" + "protocol version" "1" (match field "strategy_protocol_version" message with | `String value -> value | _ -> Alcotest.fail "expected version string"); @@ -148,36 +147,6 @@ let conservative_initialize_message_encodes_cost_models () = check "completed_bar_next_open_v1" T.Execution.Reject_missing_volume "reject"; check "completed_bar_adverse_touch_v1" T.Execution.Zero_impact "zero_impact" -let legacy_initialize_message_remains_frozen () = - let initialization = - { - (initialization ()) with - scenario_contract_version = T.Contract.legacy_journal_version; - } - in - let message = - T.Strategy_protocol.initialize_message ~sequence:1L initialization - in - Alcotest.(check string) - "legacy protocol version" "3" - (match field "strategy_protocol_version" message with - | `String value -> value - | _ -> Alcotest.fail "expected version string"); - let payload = field "payload" message in - Alcotest.(check bool) - "no v4 initial portfolio" false - (match payload with - | `Assoc fields -> List.mem_assoc "initial_portfolio" fields - | _ -> Alcotest.fail "expected payload object"); - let execution = field "execution" payload in - Alcotest.(check bool) - "flat v3 execution" true - (match execution with - | `Assoc fields -> - List.mem_assoc "participation_bps" fields - && not (List.mem_assoc "configuration" fields) - | _ -> Alcotest.fail "expected execution object") - let event_message_contains_complete_context () = let account = test_account () in let slice = market_slice 1L in @@ -265,7 +234,7 @@ let nonpositive_equity_omits_weights () = let response message_type payload = `Assoc [ - ("strategy_protocol_version", `String "14"); + ("strategy_protocol_version", `String "1"); ("strategy_sequence", `String "3"); ("message_type", `String message_type); ("payload", payload); @@ -365,8 +334,8 @@ let responses_are_strict_and_typed () = let duplicate = `Assoc [ - ("strategy_protocol_version", `String "7"); - ("strategy_protocol_version", `String "7"); + ("strategy_protocol_version", `String "1"); + ("strategy_protocol_version", `String "1"); ("strategy_sequence", `String "3"); ("message_type", `String "stopped"); ("payload", `Assoc []); @@ -380,20 +349,21 @@ let responses_are_strict_and_typed () = let wrong_version = `Assoc [ - ("strategy_protocol_version", `String "1"); + ("strategy_protocol_version", `String "unsupported"); ("strategy_sequence", `String "3"); ("message_type", `String "stopped"); ("payload", `Assoc []); ] in Alcotest.(check string) - "wrong version rejected" "unsupported strategy protocol version: 1" + "wrong version rejected" + "unsupported strategy protocol version: unsupported" (T.Strategy_protocol.response_of_yojson ~expected_sequence:3L wrong_version |> diagnostic_message); let unknown_field = `Assoc [ - ("strategy_protocol_version", `String "7"); + ("strategy_protocol_version", `String "unsupported"); ("strategy_sequence", `String "3"); ("message_type", `String "stopped"); ("payload", `Assoc []); @@ -581,8 +551,6 @@ let tests = initialize_message_includes_calendars; Alcotest.test_case "conservative initialization encodes costs" `Quick conservative_initialize_message_encodes_cost_models; - Alcotest.test_case "legacy initialize message remains frozen" `Quick - legacy_initialize_message_remains_frozen; Alcotest.test_case "event context is complete" `Quick event_message_contains_complete_context; Alcotest.test_case "nonpositive equity omits weights" `Quick diff --git a/test/test_support.ml b/test/test_support.ml index 93402b4..21aaaef 100644 --- a/test/test_support.ml +++ b/test/test_support.ml @@ -54,6 +54,10 @@ let test_account ?(base_currency = "USD") ?initial_cash () = in T.Account.create ~base_currency ~initial_cash |> ok +let initial_portfolio ?(base_currency = "USD") ?cash () = + let cash = Option.value cash ~default:[ (base_currency, money "10000") ] in + T.Initial_portfolio.cash_only ~base_currency ~cash |> ok + let account_cash ?(currency = "USD") account = T.Account.cash account currency |> Option.get @@ -61,8 +65,11 @@ let account_value ?(instruments = [ instrument () ]) ?(fx_rates = [ ("USD", price "1") ]) account ~marks = T.Account.value account ~instruments ~marks ~fx_rates |> ok -let market_slice ?bars ?fx_rates ?(corporate_actions = []) ?start_at ?end_at - ?available_at ?received_at sequence = +let market_slice ?bars ?fx_rates ?(corporate_actions = []) + ?(borrow_observations = []) ?(cash_rate_observations = []) + ?(settlement_failures = []) ?(lifecycle_events = []) ?(market_events = []) + ?(order_book_events = []) ?start_at ?end_at ?available_at ?received_at + sequence = let day = day sequence in let start_at = Option.value start_at @@ -83,20 +90,25 @@ let market_slice ?bars ?fx_rates ?(corporate_actions = []) ?start_at ?end_at let bars = Option.value bars ~default:[ bar sequence ] in let fx_rates = Option.value fx_rates ~default:[ fx_mark () ] in T.Market_slice.create ~slice_sequence:sequence ~start_at ~end_at ~available_at - ~received_at ~bars ~fx_rates ~corporate_actions + ~received_at ~bars ~fx_rates ~corporate_actions ~borrow_observations + ~cash_rate_observations ~settlement_failures ~lifecycle_events + ~market_events ~order_book_events |> ok let request ?(instrument = instrument_id "test-equity") ?(side = T.Order.Buy) ?(quantity_value = "10") ?(kind = T.Order.Market) ?(origin = T.Order.Direct) - () = + ?time_in_force () = + let time_in_force = + Option.value time_in_force ~default:(T.Order.default_time_in_force kind) + in T.Order.request ~instrument_id:instrument ~side - ~quantity:(quantity quantity_value) ~kind ~origin + ~quantity:(quantity quantity_value) ~kind ~time_in_force ~origin |> ok -let request_v8 ?(instrument = instrument_id "test-equity") ?(side = T.Order.Buy) - ?(quantity_value = "10") ?(kind = T.Order.Market) +let current_request ?(instrument = instrument_id "test-equity") + ?(side = T.Order.Buy) ?(quantity_value = "10") ?(kind = T.Order.Market) ?(time_in_force = T.Order.Gtc) ?(origin = T.Order.Direct) () = - T.Order.request_v8 ~instrument_id:instrument ~side + T.Order.request ~instrument_id:instrument ~side ~quantity:(quantity quantity_value) ~kind ~time_in_force ~origin |> ok @@ -122,48 +134,94 @@ let fill ?(id = "fill-1") ?(price_value = "100") ?(quantity_value = "1") T.Fill.create ~id:(fill_id id) ~order_id:order.T.Order.id ~instrument_id:order.request.instrument_id ~side:order.request.side ~quote_currency:"USD" ~quantity:(quantity quantity_value) - ~price:(price price_value) ~fee:(money fee_value) ~executed_at - ~slice_sequence + ~price:(price price_value) ~fee:(money fee_value) ~fee_components:[] + ~executed_at ~slice_sequence |> ok -let execution ?(participation_bps = 10_000) ?(fixed_fee = "0") ?(fee_bps = 0) () - = - T.Execution.create ~participation_bps ~fixed_fee:(money fixed_fee) ~fee_bps +let zero_fee_schedule instrument = + let component = + T.Fee_schedule.create_component ~name:"zero" + ~currency:instrument.T.Instrument.quote_currency + ~basis:(T.Fee_schedule.Fixed T.Scalar.Money.zero) + ~rounding:T.Fee_schedule.Up ~applicability:T.Fee_schedule.Any + |> ok + in + T.Fee_schedule.create + ~schedule_id:(T.Id.Instrument.to_string instrument.id ^ "-fees-v1") + ~instrument_id:instrument.id ~settlement_currency:instrument.quote_currency + ~minimum:None ~maximum:None ~components:[ component ] |> ok +let execution ?(participation_bps = 10_000) ?fee_schedules + ?(instruments = [ instrument () ]) () = + let fee_schedules = + Option.value fee_schedules ~default:(List.map zero_fee_schedule instruments) + in + T.Execution.create ~participation_bps ~fee_schedules |> ok + let risk ?(base_currency = "USD") ?(instruments = [ instrument () ]) ?(max_order = "1000") ?(max_long = "1000") ?(max_short = "1000") ?(max_gross = "1000000000") ?(max_leverage = "2") - ?(initial_margin_bps = 5000) ?(maintenance_margin_bps = 2500) - ?(short_borrow_bps = 100) () = - T.Risk.create ~base_currency ~instruments - ~max_order_quantity:(quantity max_order) - ~max_long_position:(quantity max_long) - ~max_short_position:(quantity max_short) + ?(initial_margin_bps = 5000) ?(maintenance_margin_bps = 2500) () = + let instrument_policies = + List.map + (fun instrument -> + T.Risk.create_instrument_policy ~instrument + ~max_order_quantity:(quantity max_order) + ~max_long_position:(quantity max_long) + ~max_short_position:(quantity max_short) ~max_notional_exposure:None + ~initial_margin_bps ~maintenance_margin_bps ~shorting_allowed:true + |> ok) + instruments + in + T.Risk.create ~base_currency ~instruments ~instrument_policies ~groups:[] ~max_gross_exposure:(money max_gross) ~max_leverage:(T.Scalar.Ratio.of_decimal_string max_leverage |> ok) - ~initial_margin_bps ~maintenance_margin_bps ~short_borrow_bps |> ok -let engine_config ?(contract_version = T.Contract.version) ?(risk = risk ()) - ?execution_model ?(execution = execution ()) ?(max_internal_events = 1000) - () = - let execution_model = - Option.value execution_model - ~default:(T.Execution_model.find "completed_bar_v1" |> ok) +let financing_policy () = + T.Financing.policy ~day_count:T.Financing.Actual_365 + ~compounding:T.Financing.Simple ~borrow_missing_data:T.Financing.Zero + ~cash_missing_data:T.Financing.Zero ~locate_policy:T.Financing.Clip_fill + ~recall_policy:T.Financing.Reject_new_shorts + +let settlement_policy ?(instruments = [ instrument () ]) () = + let dates month count = + List.init count (fun index -> + Printf.sprintf "2026-%02d-%02d" month (index + 1)) in - T.Engine.config ~contract_version ~risk ~execution_model ~execution - ~max_internal_events + let calendar = + T.Settlement.calendar ~calendar_id:"test-settlement" ~version:"1" + ~business_dates:(dates 1 31 @ dates 2 28 @ dates 3 31) + |> ok + in + let rules = + List.map + (fun instrument -> + T.Settlement.rule ~instrument_id:instrument.T.Instrument.id + ~calendar_id:"test-settlement" ~lag_business_days:1 + |> ok) + instruments + in + T.Settlement.policy ~cash_buying_power:T.Settlement.Total_cash + ~position_availability:T.Settlement.Total_positions ~calendars:[ calendar ] + ~rules |> ok -let engine_config_v8 ?(risk = risk ()) ?(venue_calendars = []) ?execution_model - ?(execution = execution ()) ?(max_internal_events = 1000) () = +let engine_config ?(contract_version = T.Contract.version) ?(risk = risk ()) + ?(venue_calendars = []) ?execution_model ?(execution = execution ()) + ?(financing = financing_policy ()) ?settlement ?(max_internal_events = 1000) + () = let execution_model = Option.value execution_model ~default:(T.Execution_model.find "completed_bar_v1" |> ok) in - T.Engine.config_v8 ~contract_version:"8" ~risk ~venue_calendars - ~execution_model ~execution ~max_internal_events + let settlement = + Option.value settlement + ~default:(settlement_policy ~instruments:(T.Risk.instruments risk) ()) + in + T.Engine.config ~contract_version ~risk ~venue_calendars ~execution_model + ~execution ~financing ~settlement ~max_internal_events |> ok let risk_check risk ~account ~oms request = diff --git a/test/test_venue_calendar.ml b/test/test_venue_calendar.ml index 2b8b03b..8d028a6 100644 --- a/test/test_venue_calendar.ml +++ b/test/test_venue_calendar.ml @@ -95,7 +95,7 @@ let ambiguous_phase_policies_are_rejected () = let scenario_contract_requires_calendar_coverage () = let document = - Yojson.Safe.from_file "../contracts/v5/fixtures/demo.scenario.json" + Yojson.Safe.from_file "../contracts/v1/fixtures/demo.scenario.json" in let scenario = T.Scenario.of_yojson document |> ok in Alcotest.(check int) @@ -144,15 +144,6 @@ let scenario_contract_requires_calendar_coverage () = Alcotest.(check (option string)) "coverage path" (Some "$.venue_calendars") uncovered.context.json_path -let v4_remains_a_calendar_free_compatibility_contract () = - let scenario = - T.Scenario.read_file "../contracts/v4/fixtures/demo.scenario.json" |> ok - in - Alcotest.(check string) "v4 retained" "4" scenario.contract_version; - Alcotest.(check int) - "no inferred calendars" 0 - (List.length scenario.venue_calendars) - let tests = [ Alcotest.test_case "explicit policies and missing dates" `Quick @@ -161,6 +152,4 @@ let tests = ambiguous_phase_policies_are_rejected; Alcotest.test_case "scenario calendar coverage" `Quick scenario_contract_requires_calendar_coverage; - Alcotest.test_case "v4 compatibility does not infer calendars" `Quick - v4_remains_a_calendar_free_compatibility_contract; ] diff --git a/test/validate_contract_conformance.py b/test/validate_contract_conformance.py index 3aa3047..f2d1bf7 100644 --- a/test/validate_contract_conformance.py +++ b/test/validate_contract_conformance.py @@ -4,7 +4,6 @@ from __future__ import annotations import copy -import hashlib import json from pathlib import Path from typing import Any @@ -394,54 +393,11 @@ def verify_top_level_branches( ) -def verify_frozen_integrity() -> None: - ledger_path = CONFORMANCE / "frozen.sha256" - expected: dict[str, str] = {} - for line_number, line in enumerate( - ledger_path.read_text(encoding="utf-8").splitlines(), start=1 - ): - try: - digest, relative = line.split(" ", maxsplit=1) - except ValueError as error: - raise AssertionError( - f"{ledger_path.relative_to(ROOT)}:{line_number} is malformed" - ) from error - if relative in expected: - raise AssertionError(f"duplicate frozen artifact {relative}") - expected[relative] = digest - frozen_roots = [ - CONTRACTS / "v1", - CONTRACTS / "v2", - CONTRACTS / "strategy" / "v1", - CONTRACTS / "strategy" / "v2", - ] - discovered = { - str(path.relative_to(ROOT)) - for root in frozen_roots - for path in root.rglob("*") - if path.is_file() - and (path.name.endswith(".schema.json") or "fixtures" in path.parts) - } - if set(expected) != discovered: - raise AssertionError( - "frozen integrity ledger differs from archived artifacts: " - f"ledger={sorted(expected)} archived={sorted(discovered)}" - ) - for relative, digest in expected.items(): - actual = hashlib.sha256((ROOT / relative).read_bytes()).hexdigest() - if actual != digest: - raise AssertionError( - f"frozen artifact changed: {relative}; " - "update frozen.sha256 only for an intentional contract revision" - ) - - def main() -> None: schemas, registry = schema_registry() artifacts, _ = verify_manifest(schemas, registry) accepted_cases = verify_cases(artifacts, schemas, registry) verify_top_level_branches(artifacts, schemas, registry, accepted_cases) - verify_frozen_integrity() if __name__ == "__main__": diff --git a/test/validate_schemas.py b/test/validate_schemas.py index 827d76e..34e115a 100644 --- a/test/validate_schemas.py +++ b/test/validate_schemas.py @@ -78,7 +78,6 @@ def main() -> None: ) scenario = load(scenario_path) - contract_version = scenario["contract_version"] unsupported_version = "unsupported" scenario_validator.validate(scenario) stream_records = [ @@ -116,31 +115,25 @@ def main() -> None: unsupported_execution_model = copy.deepcopy(scenario) unsupported_execution_model["execution"]["model"] = "future_model" expect_invalid(scenario_validator, unsupported_execution_model) - if contract_version in {"5", "6"}: - missing_configuration_version = copy.deepcopy(scenario) - del missing_configuration_version["execution"]["configuration"][ - "version" - ] - expect_invalid(scenario_validator, missing_configuration_version) - unsupported_configuration_version = copy.deepcopy(scenario) - unsupported_configuration_version["execution"]["configuration"][ - "version" - ] = "2" - expect_invalid(scenario_validator, unsupported_configuration_version) - unknown_configuration_field = copy.deepcopy(scenario) - unknown_configuration_field["execution"]["configuration"]["future"] = True - expect_invalid(scenario_validator, unknown_configuration_field) - if contract_version in {"3", "4", "5", "6"}: - excessive_feedback_cap = copy.deepcopy(scenario) - excessive_feedback_cap["max_internal_events"] = 100001 - expect_invalid(scenario_validator, excessive_feedback_cap) - excessive_catalog = copy.deepcopy(scenario) - excessive_catalog["instruments"] = [scenario["instruments"][0]] * 4097 - expect_invalid(scenario_validator, excessive_catalog) - excessive_intents = copy.deepcopy(scenario) - intent = scenario["schedule"][0]["intents"][0] - excessive_intents["schedule"][0]["intents"] = [intent] * 4097 - expect_invalid(scenario_validator, excessive_intents) + missing_configuration_version = copy.deepcopy(scenario) + del missing_configuration_version["execution"]["configuration"]["version"] + expect_invalid(scenario_validator, missing_configuration_version) + unsupported_configuration_version = copy.deepcopy(scenario) + unsupported_configuration_version["execution"]["configuration"]["version"] = "2" + expect_invalid(scenario_validator, unsupported_configuration_version) + unknown_configuration_field = copy.deepcopy(scenario) + unknown_configuration_field["execution"]["configuration"]["future"] = True + expect_invalid(scenario_validator, unknown_configuration_field) + excessive_feedback_cap = copy.deepcopy(scenario) + excessive_feedback_cap["max_internal_events"] = 100001 + expect_invalid(scenario_validator, excessive_feedback_cap) + excessive_catalog = copy.deepcopy(scenario) + excessive_catalog["instruments"] = [scenario["instruments"][0]] * 4097 + expect_invalid(scenario_validator, excessive_catalog) + excessive_intents = copy.deepcopy(scenario) + intent = scenario["schedule"][0]["intents"][0] + excessive_intents["schedule"][0]["intents"] = [intent] * 4097 + expect_invalid(scenario_validator, excessive_intents) unversioned_stream_record = copy.deepcopy(stream_records[0]) del unversioned_stream_record["contract_version"] expect_invalid(stream_validator, unversioned_stream_record) @@ -150,23 +143,17 @@ def main() -> None: malformed_stream_slice = copy.deepcopy(stream_records[1]) malformed_stream_slice["payload"]["market_slice"]["unexpected"] = True expect_invalid(stream_validator, malformed_stream_slice) - if contract_version in {"3", "4", "5", "6"}: - excessive_stream_catalog = copy.deepcopy(stream_records[0]) - excessive_stream_catalog["payload"]["instruments"] = ( - [stream_records[0]["payload"]["instruments"][0]] * 4097 - ) - expect_invalid(stream_validator, excessive_stream_catalog) - excessive_stream_intents = copy.deepcopy(stream_records[1]) - intent = scenario["schedule"][0]["intents"][0] - excessive_stream_intents["payload"]["intents"] = [intent] * 4097 - expect_invalid(stream_validator, excessive_stream_intents) + excessive_stream_catalog = copy.deepcopy(stream_records[0]) + excessive_stream_catalog["payload"]["instruments"] = ( + [stream_records[0]["payload"]["instruments"][0]] * 4097 + ) + expect_invalid(stream_validator, excessive_stream_catalog) + excessive_stream_intents = copy.deepcopy(stream_records[1]) + intent = scenario["schedule"][0]["intents"][0] + excessive_stream_intents["payload"]["intents"] = [intent] * 4097 + expect_invalid(stream_validator, excessive_stream_intents) noncanonical = copy.deepcopy(scenario) - if contract_version in {"3", "4"}: - noncanonical["initial_cash"][0]["amount"] = "10000.0" - elif contract_version == "6": - noncanonical["initial_portfolio"]["cash"][0]["amount"] = "10000.0" - else: - noncanonical["initial_cash"] = "10000.0" + noncanonical["initial_portfolio"]["cash"][0]["amount"] = "10000.0" expect_invalid(scenario_validator, noncanonical) first_journal_record = json.loads( journal_path.read_text(encoding="utf-8").splitlines()[0] @@ -187,31 +174,30 @@ def main() -> None: json.loads(line) for line in journal_path.read_text(encoding="utf-8").splitlines() ] - if contract_version == "4": - fill_clipped = copy.deepcopy(first_journal_record) - fill_clipped["event_type"] = "fill_clipped" - fill_clipped["payload"] = { - "reason": { - "version": "1", - "policy": "max_leverage", - "threshold": {"unit": "ratio", "value": "2"}, - }, - "order_id": "fixture-order", - "instrument_id": "fixture-instrument", - "proposed_quantity": "10", - "permitted_quantity": "5", - "price": "100", - } - journal_validator.validate(fill_clipped) - mismatched_threshold = copy.deepcopy(fill_clipped) - mismatched_threshold["payload"]["reason"]["threshold"] = { - "unit": "money", - "value": "2", - } - expect_invalid(journal_validator, mismatched_threshold) - unknown_policy = copy.deepcopy(fill_clipped) - unknown_policy["payload"]["reason"]["policy"] = "future_policy" - expect_invalid(journal_validator, unknown_policy) + fill_clipped = copy.deepcopy(first_journal_record) + fill_clipped["event_type"] = "fill_clipped" + fill_clipped["payload"] = { + "reason": { + "version": "1", + "policy": "max_leverage", + "threshold": {"unit": "ratio", "value": "2"}, + }, + "order_id": "fixture-order", + "instrument_id": "fixture-instrument", + "proposed_quantity": "10", + "permitted_quantity": "5", + "price": "100", + } + journal_validator.validate(fill_clipped) + mismatched_threshold = copy.deepcopy(fill_clipped) + mismatched_threshold["payload"]["reason"]["threshold"] = { + "unit": "money", + "value": "2", + } + expect_invalid(journal_validator, mismatched_threshold) + unknown_policy = copy.deepcopy(fill_clipped) + unknown_policy["payload"]["reason"]["policy"] = "future_policy" + expect_invalid(journal_validator, unknown_policy) order_record = next( record for record in journal_records if record["event_type"] == "order_accepted" ) diff --git a/test/validate_strategy_schema.py b/test/validate_strategy_schema.py index f419b22..2df99de 100644 --- a/test/validate_strategy_schema.py +++ b/test/validate_strategy_schema.py @@ -93,7 +93,7 @@ def main() -> None: extra_field["unexpected"] = True expect_invalid(message_validator, extra_field) unsupported_version = copy.deepcopy(records[1]["message"]) - unsupported_version["strategy_protocol_version"] = "1" + unsupported_version["strategy_protocol_version"] = "2" expect_invalid(message_validator, unsupported_version) malformed_sequence = copy.deepcopy(records[1]["message"]) malformed_sequence["strategy_sequence"] = "01"