From 1467fcd30fb891d080fcc188f893327a07fb37c1 Mon Sep 17 00:00:00 2001 From: Brummel Date: Wed, 3 Jun 2026 09:12:22 +0200 Subject: [PATCH] docs: brokers are consumer nodes (C10), several attachable for comparable curves Correct the broker mechanism: a broker is an ordinary downstream consumer node (C8/C9), not an external plugin/subsystem. It consumes the position-event stream + price streams and emits an equity stream; several brokers (e.g. sim-optimal pip + realistic currency) can be attached to the same position table at once, yielding directly comparable equity curves. Updates C10, CLAUDE.md invariant 7, aura-engine/aura-std crate docs, and the day-in-the-life doc. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 12 +++++---- crates/aura-engine/src/lib.rs | 5 ++-- crates/aura-std/src/lib.rs | 4 +-- docs/design/INDEX.md | 48 ++++++++++++++++++++--------------- docs/project-layout.md | 6 +++-- 5 files changed, 44 insertions(+), 31 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 1981631..c736094 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -76,11 +76,13 @@ design decision, not a refactor, and belongs in the ledger. outputs not an equity curve but a time-ordered table of position events (`event_ts, action[buy/sell/close], position_id, instrument_id, volume`; a position's open time is its opening event's `event_ts`); the set of open - positions at t is its state. Brokers are downstream, swappable plugins that - turn this table into an equity curve — never part of the strategy. Neutral - evaluation uses a deterministic, frictionless sim-optimal broker producing - synthetic equity in **pips**; realistic broker plugins add real - friction/constraints in currency for viability and deploy. + positions at t is its state. Brokers are downstream **consumer nodes** (not part + of the strategy) that consume the position-event stream (plus prices) and emit + an equity stream; several can be attached to the same position table at once, + giving directly comparable curves. Neutral evaluation uses a deterministic, + frictionless sim-optimal broker producing synthetic equity in **pips**; + realistic broker nodes add real friction/constraints in currency for viability + and deploy. 8. **Deploy artifacts are frozen.** Hot-reload (cdylib) is an authoring-loop tool only. The live bot is a statically-linked, versioned, frozen artifact — never hot-swapped (audit trail: this bot = this commit). diff --git a/crates/aura-engine/src/lib.rs b/crates/aura-engine/src/lib.rs index d254819..90ddd96 100644 --- a/crates/aura-engine/src/lib.rs +++ b/crates/aura-engine/src/lib.rs @@ -4,8 +4,9 @@ //! sources into one chronological cycle stream), the deterministic synchronous //! single-threaded sim loop (one unique state per input tick), freshness-gated //! recompute, the strategy's broker-independent position-event output and the -//! downstream broker plugins that project it into equity (sim-optimal pip / -//! realistic currency), and the atomic sim unit +//! downstream broker nodes that project it into equity (sim-optimal pip / +//! realistic currency; several attachable at once for comparable curves), and +//! the atomic sim unit //! `(topology + params + data-window + seed) -> metrics` that the sweep / //! optimize / walk-forward / Monte-Carlo axes orchestrate. //! diff --git a/crates/aura-std/src/lib.rs b/crates/aura-std/src/lib.rs index 5739963..035712d 100644 --- a/crates/aura-std/src/lib.rs +++ b/crates/aura-std/src/lib.rs @@ -2,8 +2,8 @@ //! //! The universal, batteries-included building blocks every project gets for //! free: common indicators (SMA, ATR, RSI, …), resamplers, the `SessionNode`, -//! standard combinators, and broker profiles. Depends only on `aura-core` (the -//! shared contract). +//! standard combinators, and broker nodes (the sim-optimal broker + realistic +//! broker profiles). Depends only on `aura-core` (the shared contract). //! //! This is the top tier of the three-tier node-reuse model (contract C16): //! diff --git a/docs/design/INDEX.md b/docs/design/INDEX.md index 9565332..9ae0c21 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -143,7 +143,7 @@ forcing feedback through a visible delay node keeps the per-cycle determinism intact and the one legitimate feedback path explicit. Graph-as-data enables visualization, freezing, and re-parameterization for sweeps. -### C10 — Strategy result is a broker-independent position table; brokers are downstream plugins +### C10 — Strategy result is a broker-independent position table; brokers are downstream nodes **Guarantee.** A strategy's result is **not** an equity curve but a **broker-independent, time-ordered table of position events**. The chain is `signals (scores) → decision/sizing node → position-event output`. An event is @@ -156,28 +156,36 @@ positions at time t** (opens minus closes with `event_ts ≤ t`) is the strategy *state* at t; the ordered sequence of these states is the result. Position sizing and risk live here (they set `volume`); the portfolio is multi-instrument. -A **broker is a downstream, swappable plugin** that consumes the position table -and produces an equity curve — never part of the strategy. Two classes: -**(a) the sim-optimal broker** — deterministic, frictionless, perfect-fill -execution producing a **synthetic equity curve in pips** (no real currency, no -real-broker constraints); the neutral yardstick for comparing and optimizing -strategy *logic*. **(b) realistic broker plugins** (Pepperstone, …) — apply real -spread / commission / slippage / lot / margin, may reject or modify positions, -and produce a currency equity curve for viability and deployment. Pip PnL uses -per-instrument pip metadata (reference data beside the hot path, C7). Live: a -realistic broker plugin consumes the position events in real time and routes -orders; reconciliation with the real account is an external adapter. +A **broker is a downstream consumer node** (C8 / C9): it consumes the strategy's +position-event stream — plus the relevant price streams, to mark open positions — +and emits an **equity stream** as its output. It is *not* part of the strategy. +Because it is an ordinary node, **several brokers can be attached to the same +position table at once**, each emitting its own equity stream, so the resulting +curves are directly comparable. Two classes: **(a) the sim-optimal broker** — +deterministic, frictionless, perfect-fill execution producing a **synthetic +equity stream in pips** (no real currency, no real-broker constraints); the +neutral yardstick for comparing and optimizing strategy *logic*. **(b) realistic +broker nodes** (Pepperstone, …) — apply real spread / commission / slippage / +lot / margin, may reject or modify positions, and produce a currency equity +stream for viability and deployment. Pip PnL uses per-instrument pip metadata +(reference data beside the hot path, C7). Live: a realistic broker node consumes +the position events in real time and routes orders as a side effect; +reconciliation with the real account is an external adapter. **Forbids.** Treating an equity curve as the strategy's output; baking a broker -into the strategy; storing `open_ts` (derive it from the opening event); a -signed-volume direction trick (use `action`); broker-specific assumptions -leaking into the strategy logic. +into the strategy; a special external broker subsystem (a broker is an ordinary +node); storing `open_ts` (derive it from the opening event); a signed-volume +direction trick (use `action`); broker-specific assumptions leaking into the +strategy logic. **Why.** A strategy can be judged neutrally only if its result is independent of any real broker's frictions. The position table is that broker-independent -invariant: one table feeds many brokers, each yielding its own equity — so "same -strategy, different broker" and "same decisions sim vs live" both fall out. The -sim-optimal pip curve is a level, currency-free playing field for comparison; -realistic plugins then test real-world viability. This supersedes the earlier -"broker is part of the strategy" framing. +invariant: one table feeds many broker nodes, each yielding its own equity — so +attaching a synthetic and a real broker side by side gives two comparable +curves, and "same strategy, different broker" and "same decisions sim vs live" +both fall out. The sim-optimal pip curve is a level, currency-free playing field +for comparison; realistic broker nodes then test real-world viability. Modelling +the broker as a node (not a bespoke subsystem) keeps it within the one Node/graph +abstraction (C9). This supersedes the earlier "broker is part of the strategy" +framing. ### C11 — Generalized sources; record-then-replay determinism boundary **Guarantee.** A source is anything that produces timestamped scalar streams — diff --git a/docs/project-layout.md b/docs/project-layout.md index 1ae948d..4ca9ee3 100644 --- a/docs/project-layout.md +++ b/docs/project-layout.md @@ -73,8 +73,10 @@ recorded before it enters a backtest, and only with your per-session consent. **position table** (open/close events); the default **sim-optimal broker** projects it into a synthetic **pip**-equity, yielding a metrics table (trades, hit-rate, pip-P&L, max-DD, Sharpe) + a run record (manifest + - metrics) under `runs/`. Add `--broker pepperstone` to project the same table - through a realistic broker (currency, friction) for viability. (Contract C10.) + metrics) under `runs/`. Brokers are consumer **nodes**, and several can be + attached at once: add `--broker pepperstone` to get a realistic currency + curve *alongside* the default sim-optimal pip curve — two comparable equity + curves from the same position table. (Contract C10.) 4. **Sweep + Monte-Carlo:** `aura sweep … --grid lookback=5..50,thresh=0.5..0.9 --mc-seeds 1000` → a distribution of metrics, best params, robustness bands. 5. **Compose:** "combine it with `momentum-filter` as a weighted sum" → Claude