diff --git a/CLAUDE.md b/CLAUDE.md index bf225f5..a7c5054 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -84,21 +84,31 @@ design decision, not a refactor, and belongs in the ledger. makes a live external call mid-replay. (See `~/.claude/CLAUDE.md` for the IONOS consent rule: external LLM calls happen at the recording/live-source edge, with explicit per-session consent, never inside a backtest.) -7. **Strategy output is an intent/exposure stream; position management is a - decoupled derived layer.** The DAG expresses one state at t (C8: ≤1 record per - `eval`), so a strategy's primary, backtestable output is a signed, bounded - **exposure** `f64 ∈ [-1,+1]` per cycle, not an equity curve. **Signal quality** - is measured by the **sim-optimal broker** — a downstream consumer node that - integrates `exposure·return` into a deterministic, frictionless synthetic - equity stream in **pips**. The broker-independent **position-event table** - (`event_ts, action[buy/sell/close], position_id, instrument_id, volume`) is a - **decoupled, derivable** layer — the first difference of the exposure state, a - computed table (not a per-`eval` output, since one decision instant may yield - >1 event) — that feeds **realistic broker nodes** (currency equity, real - frictions) for viability and deploy. The two broker classes attach at two - points: sim-optimal on the exposure stream, realistic on the derived - position-event table; brokers are ordinary downstream nodes, never part of the - strategy. +7. **Strategy output is a directional bias stream; risk-based execution and + realistic brokers are decoupled downstream layers; signal quality is measured + in R.** The DAG expresses one state at t (C8: ≤1 record per `eval`), so a + strategy's primary, backtestable output is a signed, bounded **bias** `f64 ∈ + [-1,+1]` per cycle — direction (sign) + conviction (magnitude, optional), + **unsized** (not an equity curve, not a position, not a size). Sizing leaves the + strategy: a decoupled **risk-based execution** layer `bias → stop-rule → Sizer → + Veto → position-management` (the **RiskExecutor** composite, per symbol, nested + in a Broker/Account composite) turns bias + a protective **stop** into a sized + intent. The **stop defines the risk unit R** (1R = the loss if stopped). + **Signal quality is measured in R** (R-multiples / expectancy), the account- and + instrument-agnostic yardstick — **Stage 1**: flat-1R sizing, feed-forward, no + equity feedback, the primary research loop. **Currency P&L is Stage 2** (deploy + viability): fixed-fractional sizing reads equity (compounding) → realistic + brokers apply real frictions → currency equity, entered only after `E[R] > 0`. + The single feedback (equity → Sizer) is cut by a `z⁻¹` register on the **fill + edge** (mark-to-market stays a same-cycle price read), encapsulated in the + executor composite; flat-1R vs compounding is a **structural axis** (C11). The + broker-independent **position-event table** (`event_ts, action[buy/sell/close], + position_id, instrument_id, volume`) remains the **decoupled, derived** Stage-2 + audit layer — the first difference of the *book* (`deal = target − book − + in_flight`), a computed table (not a per-`eval` output, since one decision + instant may yield >1 event) — feeding realistic brokers. Brokers/executors are + ordinary downstream nodes, never part of the strategy; account mode + (netting/hedging) is a composition constraint. 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/docs/design/INDEX.md b/docs/design/INDEX.md index db49c57..b436104 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -8,8 +8,9 @@ its new rationale), never a silent refactor. Provenance: contracts C1–C18 were settled in the initial rough-sketch design interview (2026-06-03), walking the design tree root-to-leaf (C16–C18 and the C10 refinement to a broker-independent position table came in follow-up turns; -C10 was later reframed in cycle 0007 — the intent/exposure stream is the primary -output, the position table a derived layer — see C10). C19–C22 were added as the +C10 was reframed in cycle 0007 to an exposure stream, then again 2026-06-23 +(#117) to a **bias** stream with signal quality in **R**, the position table a +derived layer — see C10). C19–C22 were added as the construction / World / playground layer; C23 and the C9/C19 compilation refinements were settled 2026-06-05 for the **Construction-layer** milestone (the blueprint→flat-graph reading of composites and graph optimisation). @@ -20,8 +21,9 @@ rationale. Vocabulary: a *contract* is one ledger entry. A *cycle* is one pipeline round; a *milestone* is a tracker container spanning many cycles (the first milestone is -the **walking skeleton**: ingest → one signal → exposure/intent → sim-optimal -broker → synthetic pip-equity signal-quality metric). +the **walking skeleton**: ingest → one signal → exposure → sim-optimal broker → +synthetic pip-equity signal-quality metric — the *pre-reframe* substrate, now +reframed to bias → R-evaluator → R-expectancy, see C10). --- @@ -401,7 +403,7 @@ cycle 0005). This is the **same arity** C8 already grants a leaf (OHLCV = one po 5 columns): a multi-line indicator (MACD = macd/signal/histogram) is **one** record of K fields, **one** port, **one** row per `eval` — C8/C7/C4 untouched, a boundary completion, not a contract change. A strategy composite is simply the K=1 case -(one exposure field, C10). The re-export **names** are **non-load-bearing** (C23): +(one bias field, C10). The re-export **names** are **non-load-bearing** (C23): they live at the blueprint boundary and in render (cycle 0022/#46 folds each onto its producing node as a `name := …` binding; originally `[out:]` markers, #13) but are dropped at lowering — `ItemLowering::Composite.output` is `Vec<(usize, @@ -447,74 +449,122 @@ distinguishability check, if ever wanted (e.g. for the WASM graph view's #21 thread), is decoupled from param-space injectivity. Construction-phase only; the flat graph stays name-free (C23). -### C10 — Strategy output is an intent/exposure stream; position management is a decoupled derived layer; brokers are downstream nodes +### C10 — Strategy output is a bias stream; signal quality is measured in R; risk-based execution and realistic brokers are decoupled downstream layers **Guarantee.** A strategy's primary, backtestable output is **not** an equity -curve, **nor a position-event table**, but an **intent / exposure stream**: the -DAG expresses exactly one *state* at time t (C8 — a node emits at most one record -per `eval`), so a strategy emits one **signed, bounded exposure** `f64 ∈ -[-1, +1]` per cycle (per instrument; the portfolio is multi-instrument). Exposure -is the desired fractional position; **position sizing and risk live in the -decision/sizing node** that shapes a raw signal score into exposure. The chain is -`signals (scores) → decision/sizing node → exposure stream`. +curve, **nor a position-event table**, **nor a position size**, but a **bias +stream**: the DAG expresses exactly one *state* at time t (C8 — a node emits at +most one record per `eval`), so a strategy emits one **signed, bounded bias** +`f64 ∈ [-1, +1]` per cycle (per instrument) — the **sign is direction, the +magnitude is conviction**, and conviction is optional (a bare ±1 / 0 is the modal +case). Bias is **unsized**: position sizing and the protective stop do **not** +live in the strategy. The chain is `signals (scores) → decision node → bias +stream`. -**Signal quality** is evaluated by the **(a) sim-optimal broker** — a downstream -consumer node (C8/C9) that consumes the **exposure stream** plus the relevant -price stream and integrates `exposure(t-1) · (price(t) − price(t-1))` into a -**synthetic equity stream in pips**: deterministic, frictionless, perfect-fill -(no currency, no real-broker constraints). The exposure held *into* a cycle -(decided at t-1) earns that cycle's return, so the integration is causal (C2 — no -look-ahead). Pip PnL uses per-instrument pip metadata (reference data beside the -hot path, C7/C15). This pip-equity curve measures the **signal's quality**, not -an execution-modelled P&L; it is the primary research loop — backtest one signal, -combine it with another, backtest the combination. +**Risk-based execution is a decoupled downstream layer.** Turning a bias into a +position is the job of a **risk-based execution** chain — `bias → stop-rule → +Sizer → Veto → position-management` — never the strategy's. The **stop-rule** sets +a protective stop, which **defines the risk unit R** (1R = the loss taken if +stopped). The **Sizer** sizes the trade in R; the **Veto** is a distinct +pre-trade gate (position / exposure caps), kept separate from sizing. These wire +into a **RiskExecutor** composite (per symbol); RiskExecutors nest inside a +**Broker / Account** composite that aggregates per-symbol P&L into account equity. +The account **mode is a composition constraint**: a *netting* account allows ≤1 +RiskExecutor per (strategy, symbol); a *hedging* account (the European CFD +default) allows many per symbol, even oppositely directed. -**Position management** — turning the exposure stream into a broker-independent, +**Signal quality is measured in R — Stage 1.** A downstream **R-evaluator** +consumes a RiskExecutor run under **flat-1R** sizing (every trade risks exactly +1R) and integrates the per-trade R-outcomes into an **R-expectancy** / R-curve: +the account- and instrument-agnostic yardstick for *"how much R out per 1R +risked?"*. Flat-1R needs no equity, so this stage is **feed-forward** (no +feedback, no cycle) — the primary research loop, maximally parallel and +deterministic (C1). R, not pips, is the unit: pips are not risk-normalized. + +**Currency P&L is Stage 2 — deploy viability.** Entered only once `E[R] > 0` is +established. Here sizing is **fixed-fractional** (size = risk-fraction · equity / +stop-distance), so it **reads account equity** and **compounds**; **realistic +broker** nodes apply real spread / commission / slippage / lot / margin and emit a +**currency** equity stream. This introduces the *only* feedback in the whole +design — equity → Sizer — cut by a **`z⁻¹` register on the fill edge** (the +realized/fill component is delayed one cycle; mark-to-market off the current price +stays a legal same-cycle read, C2), **encapsulated inside the executor +composite**. Whether that register is live is the **flat-1R vs compounding +structural axis** (instantiating a feedback edge is topology, fixed at bootstrap +(C19), hence a structural axis (C20), never a numeric sweep param): flat-1R DCEs +it away (Stage 1), compounding keeps it (Stage 2). The explicit register is +**mandatory** — C9's "only feedback is an explicit delay node" made concrete — +because the bootstrap's optimiser reorders the flat graph (C23 CSE/DCE): the +implicit read-before-fill ordering by which conventional sequential backtesters +cut this loop would not survive that reordering. + +**The position-event table** — turning the executed book into a broker-independent, time-ordered **table of position events** (pure scalar columns, C7: `event_ts: timestamp`, `action: i64` buy / sell / close, `position_id: i64`, `instrument_id: i64`, `volume: f64` unsigned — direction is the `action`; a position's open time is its opening event's `event_ts`, no separate `open_ts`; a `close` references a `position_id` and may be partial via its own `volume`) — is a -**decoupled, derivable, downstream** layer. The events are the **first difference -of the exposure state**, materialized as a *computed table* (where multiple -events may share one `event_ts` — e.g. a reversal's close + open), **never as a -per-`eval` node output** (which C8 caps at one record per cycle). This layer feeds -**(b) realistic broker nodes** (Pepperstone, …): downstream consumer nodes that -consume the position-event table plus prices, apply real spread / commission / -slippage / lot / margin, may reject or modify positions, and produce a -**currency** equity stream for viability and deployment. The position-event table -stays broker-independent — one table feeds many realistic brokers, giving +**decoupled, derived, downstream** Stage-2 layer. The events are the **first +difference of the book** under book-tracking (`deal = target − book − in_flight`; +a close sizes the actual book, never an exposure delta), materialized as a +*computed table* (multiple events may share one `event_ts` — e.g. a reversal's +close + open), **never as a per-`eval` node output** (C8 caps one record per +cycle). This table feeds the realistic broker nodes; one table feeds many, giving directly comparable currency curves. Live: a realistic broker node consumes the events in real time and routes orders as a side effect; reconciliation with the real account is an external adapter. -So **the two broker classes attach at two different points**: the sim-optimal -broker on the **exposure stream** (signal quality, pips, now), realistic brokers -on the **derived position-event table** (execution viability, currency, later). -Both are ordinary downstream nodes (C8/C9); several can attach at once for -directly comparable curves. -**Forbids.** Treating an equity curve as the strategy's output; making the -**position-event table the strategy's direct DAG output** (it is derived, not -emitted per `eval` — a decision instant may need >1 event, which C8 forbids) or -the measure of signal quality; baking a broker 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 in the event -table (use `action`); broker-specific assumptions leaking into the strategy logic. -**Why.** The DAG is a synchronous reactive graph: at time t it holds exactly one -state, and a node emits at most one record per `eval` (C8). A *sequence of -position events* — where one decision instant (a stop-and-reverse) needs a close -**and** an open at the same `event_ts` — cannot be the DAG's per-cycle output -without violating C8. The state the DAG *can* express faithfully is the **desired -exposure** (one value per cycle); the position events are its first difference, a -derived consequence. Decoupling them resolves the C8↔C10 impedance and matches -how signal research actually proceeds: you first measure a signal's *quality* -(does this exposure, held over time, make pips?) independently of any execution -model; only later do you model position management and real-broker frictions for -deployment. The sim-optimal pip curve is a level, currency-free playing field for -comparing and combining signals; the derived position-event table + realistic -broker nodes then test real-world viability. Modelling brokers as nodes (not a -bespoke subsystem) keeps them within the one Node/graph abstraction (C9). This -supersedes the earlier "the strategy's output is the position-event table" -framing (cycle 0007 reframe). +So the layers attach at distinct points: the **R-evaluator** on a flat-1R +RiskExecutor (signal quality, R, Stage 1); **realistic brokers** on the derived +position-event table (execution viability, currency, Stage 2). All are ordinary +downstream nodes (C8/C9); several can attach at once for directly comparable +curves. +**Forbids.** Putting **sizing or the stop in the strategy** (bias is unsized; the +Sizer and stop-rule own them); treating an equity curve as the strategy's output; +making the **position-event table the strategy's direct DAG output** (it is +derived, not emitted per `eval` — a decision instant may need >1 event, which C8 +forbids) or the measure of signal quality; **measuring signal quality in currency +before R is established** (Stage 2 before Stage 1); a **combinational equity → size +cycle** (the fill-edge register is mandatory — an implicit execution ordering does +not survive C23 reordering); **fusing the Sizer and the Veto** into one node (the +size / veto / fill roles stay distinct); baking a broker 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 in +the event table (use `action`); broker-specific assumptions leaking into the +strategy logic. +**Why.** A strategy's edge is a *procedure*, not a currency outcome ("focus on the +procedure, not the money"): the right primary question is *"how much R out per 1R +risked?"*, and R — defined by the stop — is the only account- and +instrument-agnostic, risk-normalized unit (pips are not). Separating **direction +(bias) from sizing (Sizer) from fill (broker)** is the decomposition every mature +system converges on (LEAN's Alpha → Portfolio-Construction → Execution is a near +isomorphism; backtrader, QSTrader, zipline all emit an unsized directional signal +sized downstream). The **Stage-1 / Stage-2 cleave** quarantines the *only* +feedback (equity → sizing) into Stage 2, leaving the signal-quality layer +feed-forward, parallel and deterministic (C1); its closest external precedent is +vectorbt's split of vectorized signal generation from sequential money-management +— it is aura's own synthesis, not an industry standard. The DAG holds exactly one +state at t and a node emits ≤1 record per `eval` (C8), so the faithful per-cycle +output is the **bias** (one value); position *events* are its book's first +difference, a derived consequence — decoupling them resolves the C8↔C10 impedance. +Modelling brokers and executors as nodes (not a bespoke subsystem) keeps them +within the one Node/graph abstraction (C9). This supersedes the **exposure** +framing (the strategy's output was a signed fractional *position*) of the +cycle-0007 reframe and its realization notes below; that in turn superseded the +still-earlier "the strategy's output is the position-event table" framing. +**Reframe (2026-06-23, #117 — exposure → bias, R as the signal-quality unit).** +The contract above is the R-reframe; the realization notes below describe the +**pre-reframe code** (`Exposure`, `SimBroker`, pip-equity) and are retained as +history and as the **Stage-1 ancestor**: `Exposure { scale }` is the ancestor of +the unsized `bias` node, and `SimBroker`'s pip integral is the ancestor of the +R-evaluator (which additionally requires a stop, since R is stop-defined, so it +consumes a flat-1R RiskExecutor rather than raw bias). The `exposure → bias` +rename, the RiskExecutor / Sizer / Veto nodes, and the R-evaluator are **pending +Stage-1 implementation**; the position-event schema (0063, #114) survives +unchanged as the Stage-2 audit layer, though its derivation is now the **book** +first-difference (`deal = target − book − in_flight`), not the flawed 0064 +exposure-integral derive (abandoned). Industry grounding for this reframe: LEAN / +nautilus_trader / backtrader / QSTrader / vectorbt / zipline (see #117 decision +log). **Realization (cycle 0007).** The signal-quality half of this contract is now realized at the substrate, as two `aura-std` nodes composed on the unchanged engine (the engine stays domain-free — it routes only `f64` records, never @@ -923,7 +973,7 @@ per-knob overlay, no registry (C9/C10 intact). ### C20 — Strategy ↔ harness; the harness is the root sim graph **Guarantee.** A **strategy** is a reusable composite-node blueprint (C9): broker-, data-, and viz-independent, with inputs declared as named **roles** -(symbol-agnostic where possible) and the intent/exposure stream (C10) as output. +(symbol-agnostic where possible) and the **bias** stream (C10) as output. A **harness** (the experimental setup) is the **root sim graph** — sources bound to the strategy's input roles + the strategy + attached broker node(s) + sinks — and is itself produced by the bootstrap (C19). A harness *instance* is C1's @@ -1131,7 +1181,7 @@ recorded data stays on disk (view-only), and the walk-forward null-fill page col for free. Deterministic (C1): pure bucketing over the sorted-deduped spine, no-op under budget. **Refinement (#111, 2957561):** the per-bucket reduction is **tap-aware** — an *envelope* series (equity) keeps min/max, but a *bounded level* series (the C10 -exposure, ∈[-1,+1]) reduces by per-bucket **mean** (a `ReduceKind` on each `Series`, +bias level — pre-reframe: exposure — ∈[-1,+1]) reduces by per-bucket **mean** (a `ReduceKind` on each `Series`, set by `reduce_for_tap`). Without it min/max made every multi-year exposure a solid -1..+1 band (each bucket straddles many sign flips), reading as per-point oscillation; the mean shows the net/duty-cycle level. Deferred refinements: rendering the min/max diff --git a/docs/glossary.md b/docs/glossary.md index 1015f2a..04ad192 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -23,6 +23,10 @@ The per-project declarative config holding only static context (data paths, inst **Avoid:** — A single deterministic, synchronous run of one harness over historical input — the historical-replay framing of an execution. The commodity substrate the World builds families of; distinct from `sim` (the executable unit) and `run` (its registry record). +### bias +**Avoid:** exposure, exposure stream, intent stream +A strategy's primary, backtestable DAG output: one signed, bounded `f64 ∈ [-1,+1]` per cycle whose **sign is direction and magnitude is conviction** (conviction optional). Bias is **unsized** — sizing and the protective stop live downstream in the risk-based execution layer (`Sizer`/`RiskExecutor`), never in the strategy; it reframes the pre-reframe `exposure stream` (a signed fractional *position*). + ### blueprint **Avoid:** — The param-generic, input-role-generic graph-as-data produced by running a Rust builder; it carries free numeric params and free input roles before bootstrap. Bootstrapped into a frozen instance by binding params + data + seed. @@ -37,7 +41,7 @@ A frozen artifact that is a deployed strategy + broker: the live trading program ### broker **Avoid:** — -A downstream consumer node that emits an equity stream, attaching at one of two points: the **sim-optimal broker** consumes the **exposure stream** (integrating `exposure·return` → synthetic pip equity = signal quality); **realistic brokers** consume the derived **position-event table** (real frictions → currency equity). Several can attach at once for directly comparable curves. Not part of the strategy. Two classes: the sim-optimal broker and realistic brokers. +A downstream consumer node that emits an equity stream, never part of the strategy. The signal-quality side is the **R-evaluator** (Stage 1: per-trade R-outcomes from a flat-1R `RiskExecutor` → R-expectancy); **realistic brokers** (Stage 2) consume the derived **position-event table** (real frictions → currency equity), and a **Broker/Account** composite aggregates per-symbol P&L into account equity. Several can attach at once for directly comparable curves. ### cdylib **Avoid:** — @@ -61,7 +65,7 @@ A directed wiring link in a harness that forwards **one field** (`from_field`) o ### equity stream **Avoid:** — -A broker node's output over time — synthetic pips for the sim-optimal broker (its `exposure·return` integral), currency for realistic brokers. An equity *curve* is explicitly not a strategy's output (the intent/exposure stream is). +A downstream node's output over time — an **R-curve** for the R-evaluator (Stage 1, its per-trade R integral), **currency** for realistic brokers (Stage 2). An equity *curve* is explicitly not a strategy's output (the `bias` stream is). ### experiment **Avoid:** — @@ -72,8 +76,8 @@ A Rust (builder-API) definition of anything beyond a single backtest — sweep, The set of harness instances produced by varying the structural axes (strategy × instrument × broker × window), expressed as plain Rust loops. The outer orchestration over the structural dimension; the tuning sweep is the inner loop. ### exposure stream -**Avoid:** intent stream -A strategy's primary, backtestable DAG output: one signed, bounded `f64 ∈ [-1,+1]` per cycle — the desired fractional position (intent). The DAG expresses one state at t (C8: ≤1 record per `eval`), so exposure, not a position-event sequence, is what it emits. The sim-optimal broker integrates `exposure·return` into pip equity to measure signal quality; the position table is its derived first difference. +**Avoid:** — (superseded) +**Superseded by `bias` (2026-06 R-reframe).** The pre-reframe primary output: a signed, bounded `f64 ∈ [-1,+1]` per cycle read as the desired fractional *position* (conflating direction + conviction + size). Reframed to `bias` (unsized direction + conviction), sizing moved downstream to the `Sizer`/`RiskExecutor`; the term and the `Exposure` node persist in pre-reframe code until the Stage-1 rename. ### firing policy **Avoid:** — @@ -121,11 +125,23 @@ The egui-native visual face (`aura play`) that plays any harness — program str ### position table **Avoid:** — -A broker-independent, time-ordered table of position events (scalar columns: `event_ts, action, position_id, instrument_id, volume`) — the **derived** first difference of a strategy's exposure stream, a **decoupled position-management layer** feeding realistic brokers / deploy. Computed, not emitted per `eval` (one decision instant may yield >1 event); **not** the strategy's direct DAG output (that is the intent/exposure stream). +A broker-independent, time-ordered table of position events (scalar columns: `event_ts, action, position_id, instrument_id, volume`) — the **derived** first difference of the executed **book** (book-tracking `deal = target − book − in_flight`; a close sizes the actual book), a **decoupled** Stage-2 position-management layer feeding realistic brokers / deploy. Computed, not emitted per `eval` (one decision instant may yield >1 event); **not** the strategy's direct DAG output (that is the `bias` stream). + +### R +**Avoid:** — +The native unit of strategy performance: 1R = the loss if the protective stop is hit, so a trade's outcome is a multiple of R (−1R stopped out, +2R, …) and the primary question is *"how much R out per 1R risked?"*. Risk-normalized and account-/instrument-agnostic — the Stage-1 yardstick replacing pips, defined by the stop (Van Tharp R-multiples). + +### R-evaluator +**Avoid:** — +The Stage-1 signal-quality node: integrates the per-trade R-outcomes of a flat-1R `RiskExecutor` into an R-expectancy / R-curve — the deterministic, account-/instrument-agnostic yardstick. The R-reframe successor of the `sim-optimal broker` (pip integral); unlike it the R-evaluator requires a stop, so it consumes a RiskExecutor, not raw bias. + +### RiskExecutor +**Avoid:** risk-manager +The per-symbol composite turning a bias into a managed position — `stop-rule → Sizer → Veto → position-management` — with the only feedback (equity → Sizer, Stage 2) cut by a `z⁻¹` register on the fill edge and encapsulated inside. RiskExecutors nest in a Broker/Account composite that aggregates per-symbol P&L into account equity; the account mode (netting/hedging) constrains how many exist per (strategy, symbol). ### realistic broker **Avoid:** — -A broker node that consumes the derived position-event table and applies real spread / commission / slippage / lot / margin (and may reject or modify positions), emitting a currency equity stream for viability and deploy. Contrasted with the sim-optimal broker (which consumes the exposure stream directly). +A Stage-2 broker node that consumes the derived position-event table and applies real spread / commission / slippage / lot / margin (and may reject or modify positions), emitting a currency equity stream for viability and deploy. Contrasted with the R-evaluator (Stage 1, which consumes a flat-1R RiskExecutor and measures signal quality in R). ### resampler **Avoid:** — @@ -153,7 +169,7 @@ A node that exposes session context as scalar streams (`bars_since_open`, `in_se ### signal **Avoid:** — -A node whose output is a score, feeding the `signals (scores) → decision/sizing node → exposure stream` chain. A specific node role — distinct from a general node and from a strategy. +A node whose output is a score, feeding the `signals (scores) → decision node → bias stream` chain. A specific node role — distinct from a general node and from a strategy. ### sim **Avoid:** — @@ -161,12 +177,16 @@ The disjoint, executable unit of one deterministic harness run; the unit of para ### sim-optimal broker **Avoid:** — -The deterministic, frictionless, perfect-fill broker that consumes the **exposure stream** + prices and integrates `exposure·return` into synthetic equity in pips — the neutral, currency-free yardstick that measures **signal quality**. Distinct from the Aura.toml "default broker" (a config role) and from realistic brokers (which consume the derived position-event table). +**Pre-reframe term, succeeded by the `R-evaluator`.** The deterministic, frictionless, perfect-fill broker (`SimBroker`) that consumes the **exposure stream** + prices and integrates `exposure·return` into synthetic pip equity to measure signal quality. The R-reframe replaces pips with R (the R-evaluator integrates per-trade R-outcomes from a flat-1R RiskExecutor); `SimBroker` persists in pre-reframe code until the Stage-1 rename. ### sink **Avoid:** — A node in its **recording role**: in `eval` it reads its inputs (and `ctx.now()`) and pushes the record to an out-of-graph destination it holds as a field (a channel, a chart handle, the run registry) — a role, not a type, so a node may be a pure consumer (no output) or record *and* forward an output in the same `eval` (the C8 "both" case). The sole recording and observability mechanism: displayable = exactly what a sink recorded. +### Sizer +**Avoid:** risk-manager +The node that sizes a trade from bias + the stop — in R (flat-1R, Stage 1) or in lots from account equity (fixed-fractional, Stage 2) — owning the size, not the direction (bias) or the gate (Veto). "risk-manager" is avoided: in LEAN/nautilus that names the Veto layer, not the sizer. + ### SoA **Avoid:** Structure-of-Arrays The columnar Structure-of-Arrays layout in which the four scalar base types are streamed on the hot path. Composite streams are bundles of base columns; the layout is what makes streaming cache- and SIMD-friendly. @@ -175,9 +195,13 @@ The columnar Structure-of-Arrays layout in which the four scalar base types are **Avoid:** — Anything that produces timestamped scalar streams — market data and non-financial feeds (e.g. a news-bias node) are treated identically; a pure producer node. `data-server` is aura's first source. +### Stage 1 / Stage 2 +**Avoid:** — +The two-stage cleave of evaluation: **Stage 1** (R / signal quality) is flat-1R, feed-forward (no equity feedback), measured by the R-evaluator in R-expectancy — the primary research loop; **Stage 2** (currency / deploy viability) is fixed-fractional sizing that reads equity and compounds, with realistic brokers and real frictions, entered only once `E[R] > 0`. The cleave quarantines the only feedback into Stage 2 (flat-1R vs compounding is a structural axis, C11); aura's own synthesis, closest precedent vectorbt's signal vs money-management split. + ### strategy **Avoid:** — -A reusable composite-node blueprint — broker-, data-, and viz-independent, inputs declared as named roles — whose output is the intent/exposure stream (not an equity curve; the position table is a derived downstream layer). Frozen with a broker into a bot for deploy. +A reusable composite-node blueprint — broker-, data-, and viz-independent, inputs declared as named roles — whose output is the **bias** stream (unsized direction + conviction; not an equity curve, not a size; sizing and the position table are derived downstream layers). Frozen with a broker into a bot for deploy. ### structural axes **Avoid:** — @@ -187,6 +211,10 @@ The harness's structural parameterization — which strategy, instrument(s), bro **Avoid:** param-sweep, parameter sweep An orchestration axis varying tuning params (grid or random) within a fixed structure. The inner, param-tuning loop, distinct from the structural experiment matrix. +### veto +**Avoid:** risk-manager +The distinct pre-trade gate in the execution chain (`… → Sizer → Veto → position-management`): position / exposure / notional caps that may reject or scale a sized intent before it reaches the broker. Kept separate from the Sizer — it is what LEAN calls "Risk Management" and nautilus the RiskEngine. + ### walk-forward **Avoid:** — An orchestration axis: rolling in-sample optimize + out-of-sample test across moving windows, stitched into one out-of-sample verdict plus parameter stability.