design(c10): reframe to a bias stream + R-unit signal quality

Adopt the R-reframe ratified in #117: the strategy's native unit is risk
(R), not pips/dollars, and its primary output is a directional bias.

- exposure -> bias: the primary output is an UNSIZED direction + conviction
  `f64 in [-1,+1]`; sizing and the protective stop leave the strategy.
- Signal quality is measured in R (Stage 1): an R-evaluator integrates the
  per-trade R-outcomes of a flat-1R RiskExecutor into R-expectancy. R is
  defined by the stop, account-/instrument-agnostic; pips retired as the unit.
  Flat-1R needs no equity, so Stage 1 is feed-forward (no cycle).
- Risk-based execution is a decoupled layer: a RiskExecutor composite
  (stop-rule -> Sizer -> Veto -> position-management) per symbol, nested in a
  Broker/Account composite; account mode (netting/hedging) = composition
  constraint. "Sizer" is not "risk-manager" (that names the Veto layer).
- Currency P&L is Stage 2 (fixed-fractional, compounding). The only feedback
  (equity -> Sizer) is cut by a z^-1 register on the fill edge (mark-to-market
  stays a same-cycle price read), encapsulated in the executor; flat-1R vs
  compounding is a structural axis (the explicit register is mandatory because
  C23 reorders the flat graph).
- Position-event table stays the decoupled Stage-2 audit layer = first
  difference of the book (deal = target - book - in_flight); the flawed 0064
  exposure-integral derive is abandoned.

Touches: ledger C10 + CLAUDE.md domain invariant #7 + glossary (adds bias, R,
R-evaluator, RiskExecutor, Sizer, veto, Stage 1/2; revises broker, exposure
stream, position table, sim-optimal broker, strategy, ...). Also fixes
cross-file drift surfaced by adversarial review (C20 guarantee + front-matter
provenance still claimed "exposure stream"; cross-refs corrected to
C9/C19/C20/C23). Industry-grounded against LEAN / nautilus_trader / backtrader
/ QSTrader / vectorbt / zipline.

refs #117
This commit is contained in:
2026-06-23 13:14:31 +02:00
parent 2e0500dedd
commit f040b66f30
3 changed files with 175 additions and 87 deletions
+25 -15
View File
@@ -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).