diff --git a/crates/aura-engine/src/report.rs b/crates/aura-engine/src/report.rs index eb523e7..8d94a09 100644 --- a/crates/aura-engine/src/report.rs +++ b/crates/aura-engine/src/report.rs @@ -54,8 +54,10 @@ pub struct RMetrics { } // Dense `PositionManagement` record column indices — the lockstep contract with -// aura-std's FIELD_NAMES/RECORD_KINDS (aura-std is only a dev-dependency here, so the -// layout is shared by convention; `stage1_r_e2e.rs` guards that it matches). +// aura-std's FIELD_NAMES/RECORD_KINDS. The record crosses the crate boundary as a +// type-erased `Scalar` vector (C4 SoA), so it is read positionally, not by importing +// the producer's types; the layout is shared by convention and `stage1_r_e2e.rs` +// guards that it matches. mod r_col { pub const CLOSED: usize = 0; pub const REALIZED_R: usize = 1; diff --git a/crates/aura-std/src/position_management.rs b/crates/aura-std/src/position_management.rs index 597dab2..206a542 100644 --- a/crates/aura-std/src/position_management.rs +++ b/crates/aura-std/src/position_management.rs @@ -11,8 +11,8 @@ use aura_core::{ }; /// Why a trade closed. i64-encoded into the dense record (column 2). `summarize_r` -/// matches the raw i64 (it lives across a crate boundary — aura-std is only a -/// dev-dependency of aura-engine), so the encoding is the load-bearing contract. +/// matches the raw i64 across the crate boundary (the record streams as type-erased +/// `Scalar`s, C4 SoA, not as this enum), so the encoding is the load-bearing contract. #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[repr(i64)] pub enum ExitReason { diff --git a/docs/design/INDEX.md b/docs/design/INDEX.md index b436104..17f1ccc 100644 --- a/docs/design/INDEX.md +++ b/docs/design/INDEX.md @@ -558,8 +558,8 @@ 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 +rename, the RiskExecutor / Sizer / Veto nodes, and the R-evaluator **landed in +cycle 0065** (Stage-1; see the realization note below); 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 / @@ -604,6 +604,43 @@ construction rather than by researcher discipline. Threaded through the CLI `aura run --real` path; the manifest broker label records the looked-up pip. The runnable GER40 examples (already at the correct `1.0`) are routed through the same lookup separately (#98). +**Realization (cycle 0065 — Stage-1 R signal quality, #119/#126/#127/#128/#129).** +The Stage-1 chain above is now built. `Exposure → Bias` renames the unsized strategy +output (the node + its output field); the persisted `exposure_sign_flips` metric key, +the `SimBroker` `exposure` input slot, and the `exposure_scale` manifest param keep +the old name as **serde-stable residue** — a deferred rename tail. A **stop-rule** +defines 1R: `FixedStop` (a triggered-constant primitive) and a `vol_stop(length, k)` +**composition** `k·√EMA(Δ²)` (the originally-fused node was corrected to a composition +of new `Mul`/`Sqrt` primitives — a node is a primitive only if not DAG-expressible +from others). **`PositionManagement`** (`aura-std`) is the stateful heart: it latches +the entry-cycle stop distance as the immutable R-denominator, marks against the +one-cycle-lagged fill (no look-ahead, C2), and emits a **dense 14-column per-cycle +R-record** (one row per eval, C8; the trade ledger is the `closed_this_cycle` subset, +the R-equity is `cum_realized_r + unrealized_r`, the window-end open trade is the last +`open=true` row). The **`Sizer`** (`size = risk_budget / stop_distance`, flat-1R) is +the feed-forward sizing seam, and **R is size-invariant** — scaling `risk_budget` +leaves every `realized_r` unchanged (pinned by a RED test). **`summarize_r`** is a +post-run fold (sibling of `summarize`, **not** an in-graph node) → `RMetrics` (E[R], +SQN, win-rate, profit-factor, max-R-drawdown, conviction terciles, net-of-cost). The +**RiskExecutor** ships as a public `aura-engine` composite-builder +(`risk_executor(StopRule, risk_budget)` — bias+price roles embedding +`stop-rule → Sizer → PositionManagement`, beside `vol_stop`) with a `StopRule{Fixed,Vol}` +**structural axis** (C11); the **Veto** stays a documented seam, not a runtime node (a +pass-through identity is exactly what C19/C23 DCE deletes). The layer is **operable +from the CLI**: `aura run --harness ` — a **compile-time** selector +over Rust-authored harnesses (C9/C17: the CLI *runs*, it does not wire) — folds +`summarize_r` into `RunMetrics.r` (additive; `skip_serializing_if` keeps pip-only and +legacy `runs.jsonl` JSON byte-unchanged), the `stage1-r` harness fanning one bias into +both `SimBroker` (pip) and the RiskExecutor (R) for an honest dual yardstick; an +`r_equity` tap charts the by-trade R-equity through the existing `aura chart --tap`. +The R-record redundancy `debug_assert` uses a **scale-robust relative tolerance** (an +absolute `1e-9` panicked on tiny-pip FX where the `entry − stop` denominator +reconstruction loses precision; the stored `realized_r` is exact). Composites live in +`aura-engine` (the engine's convenience layer over the standard nodes, sibling of +`summarize_r`), making `aura-engine → aura-std` a normal dependency — the graph stays +acyclic. **Stage 2** (currency P&L, fixed-fractional compounding through the z⁻¹ +fill-edge register, realistic brokers consuming the position-event table) remains the +deferred downstream layer, entered only after `E[R] > 0`. ### C11 — Generalized sources; record-then-replay determinism boundary **Guarantee.** A source is anything that produces timestamped scalar streams —