design(C10): reframe strategy output to intent/exposure stream; position table becomes a derived layer

The DAG expresses exactly one state at time t and a node emits at most one record
per eval (C8), so 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 buy/sell/close
events are its first difference, a derived consequence.

C10 is reframed accordingly: the strategy's primary, backtestable output is an
intent/exposure stream (one signed, bounded f64 in [-1,+1] per cycle). Signal
quality is measured by the sim-optimal broker integrating exposure*return into a
synthetic pip-equity curve. The broker-independent position-event table survives
as a decoupled, derivable, downstream position-management layer (computed table,
not a per-eval output) feeding realistic broker nodes for viability/deploy — no
longer the DAG output nor the signal-quality measure.

Touches the ledger contract (INDEX.md C10 + provenance/milestone/C20 ancillary),
the always-loaded summary (CLAUDE.md invariant #7), the glossary (broker, equity
stream, position table, realistic broker, signal, sim-optimal broker, strategy
reframed + new exposure-stream entry), and the north-star layout doc. Sealed
specs/plans (0001-0006) left as historical record.

refs #4 #5

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 17:02:33 +02:00
parent f000373507
commit 0d7deb3a91
4 changed files with 107 additions and 71 deletions
+15 -11
View File
@@ -72,17 +72,21 @@ 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 result is a broker-independent position table.** A strategy
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 **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.
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.
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).