spec(crt): v3 architecture reset — collapse Phase A+B into CRT.1 unified controller

Empirical trigger: Phase A as designed in v2 failed Gate 1 catastrophically
on both smoke vjmwc (commit 3d8f12deb) and lkrdf (commit fe2498769 with
amplification clamp). Both produced ~155k trades (62× baseline), 9100%
max-drawdown (175× baseline), and Sharpe -15.7. The clamp had effectively
zero impact on the outcome, confirming the bug is structural not formulaic.

Architectural finding: the v2 phase split (A: continuous control / B:
signal-driven position management) is artificial. They are the same
mechanism. A scalar EMA on max(|p-0.5|) cannot smooth direction jitter
between horizons; only the multi-horizon ISV-weighted conviction formula
(v2 §4.4, deferred to Phase B in v2) is structurally coherent.

User-validated mental model: signal vector at any moment IS a forward
prediction of the trade trajectory; optimal position = inventory implied
by current beliefs; trade actions are sparse because most events
produce only fractional adjustments to a stable optimum. Continuous
evaluation, discrete action.

v3 phase structure (replaces v2 A/B/C/D):
  CRT.1  Unified Inventory Controller (was A+B merged)
  CRT.2  Adaptive Risk Envelope (was Layer C, unchanged)
  CRT.3  Online Weight Adaptation (was Layer D, unchanged)

CRT.1 components:
  - forward_step every event (already shipped: A0.5)
  - decision_stride deleted (already shipped: A1)
  - Multi-horizon ISV-weighted conviction (§4.4 promoted from Phase B)
  - Wiener-α EMA on multi-horizon conviction (§4.2 promoted)
  - target_lots = direction × |conviction_ema| × envelope_max
  - No-trade band in seed_inflight: skip if |delta| < delta_floor (NEW)
  - open_trade_state 24→64 expansion (§7 promoted from Phase B)
  - Conviction-degradation exit emergent from target→0; composite-signal
    safety layer (§4.3) preserved as circuit-breaker

What survives from v2 commits on the branch:
  a0e81fbdf forward_step incremental SSM (A0.5)
  92f8b10ed forward_step_into eliminates GPU↔CPU round-trip
  045850e8f delete decision_stride field (A1)
  3d8f12deb buffer-level seed bit-identity test

What gets superseded in CRT.1 implementation:
  1d889d2de A2 scalar conviction-EMA with aggregate rescale — replaced
            by multi-horizon §4.4 formula
  fe2498769 A2.1 clamp on broken rescale — same reason

The three conviction-EMA device slots (conviction_ema_d et al.) STAY
in LobSimCuda — the EMA mechanism is reused on the multi-horizon
conviction scalar. The `final_size *= scale` rescale step is deleted.

Gate restructure:
  v2 Gate 1 (Layer A standalone) — REMOVED
  v2 Gate 2 (Layer B) — PROMOTED as Gate CRT.1
  v2 Gate 3/4 — unchanged as CRT.2/CRT.3

Status: Design v3 — awaiting plan rewrite before implementation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-05-20 20:15:28 +02:00
parent fe24987690
commit 9ad76c4dfe

View File

@@ -1,9 +1,92 @@
# Continuous-Reasoning Trader — Architecture Design
**Date:** 2026-05-20
**Branch context:** `ml-alpha-phase-a` (S2 closed at `8828e8ab1`)
**Status:** Design v2 (amended from v1 after self-critical review — 12 issues addressed inline)
**Supersedes scope of:** `2026-05-19-isv-driven-stop-controller-design.md` (that spec ships clean stops; this spec replaces the rule-based policy that consumes those stops)
**Branch context:** `ml-alpha-phase-a` (S2 closed at `8828e8ab1`; Phase A attempt fe2498769 RED on Gate 1)
**Status:** Design v3 — phase split collapsed after empirical Gate 1 failure + architectural clarification
**Supersedes scope of:** `2026-05-19-isv-driven-stop-controller-design.md`
---
## v3 ARCHITECTURE RESET (the section that supersedes everything below)
**Date:** 2026-05-20 (same day as v2; cluster smoke evidence forced the reset)
**Empirical trigger.** Phase A as designed in v2 (continuous controller with scalar conviction-EMA on `max(|p0.5|)`, rescale on target magnitude) failed Gate 1 catastrophically. Smokes `vjmwc` (commit `3d8f12deb`) and `lkrdf` (commit `fe2498769` — with the amplification-clamp fix) both produced:
- 155k+ trades (62× baseline 2,511)
- max-drawdown 9,100% (175× baseline 53.5%)
- Sharpe-ann 15.7 (vs baseline 6.6)
- ~83% of realized loss = round-trip cost (155k × $12.50)
The clamp fix `min(scale, 1.0)` prevented the most pathological amplification but had effectively zero impact on the catastrophic outcome — confirming the bug is structural, not in the scalar EMA formula.
**Architectural finding.** The phase split v2 made (A: continuous control / B: signal-driven position management) is artificial. The two are the same mechanism. A scalar EMA on `max(|p0.5|)` cannot smooth a controller that's churning on direction flips between horizons; only the multi-horizon ISV-weighted conviction (was §4.4, deferred to Phase B in v2) is structurally coherent.
**The user-validated mental model.** The agent should reason like a discretionary trader: the multi-horizon signal vector at any moment IS a forward prediction of the trade trajectory; the optimal position is the inventory implied by current beliefs; trade actions are sparse because most events produce only fractional adjustments to a stable optimum. Continuous evaluation; discrete action.
### v3 phase structure (REPLACES v2's A/B/C/D)
```
CRT.1 Unified Inventory Controller (was Phase A + Phase B merged)
- forward_step every event (already shipped: A0.5 / commit a0e81fbdf, 92f8b10ed)
- decision_stride deleted (already shipped: A1 / commit 045850e8f)
- Multi-horizon ISV-weighted conviction (v2 §4.4 formula — promoted from Phase B)
- Wiener-α EMA on the multi-horizon conviction (v2 §4.2 — promoted)
- target_lots = round(direction × |conviction_ema| × envelope_max)
- No-trade band in seed_inflight: skip if |delta| < δ
- open_trade_state 24→64 byte expansion (v2 §7 — promoted from Phase B)
- Conviction-degradation exit (v2 §4.3): EMERGENT from target→0 when conviction collapses,
plus a composite-signal safety layer matching v2 §4.3
CRT.2 Adaptive Risk Envelope (was Layer C)
- ISV-derived max_lots, threshold, target_vol (unchanged from v2 §5)
CRT.3 Online Weight Adaptation (was Layer D)
- LoRA adapter + EWC++ + shadow eval (unchanged from v2 §6)
```
### Why the v2 phase split was wrong
1. **Direction jitter, not magnitude noise, is the dominant source of hyperactivity.** Scalar EMA on `max(|p 0.5|)` smooths magnitude only; doesn't smooth direction. The multi-horizon ISV-weighted conviction formula `weight_h × magnitude_h × direction_h` summed across horizons — particularly with ISV weights that down-weight low-SNR horizons — naturally smooths direction because disagreeing horizons partially cancel.
2. **A target-position controller without a no-trade band cannot work at event rate.** Even with perfect smoothing, target moves fractionally every event; with target-delta seed_inflight semantics, every fractional move generates an order. The no-trade band (skip seeding if |Δ| < δ) is structurally required; deferring it to "Phase B" left Phase A unrunnable.
3. **Conviction-degradation exit is not a separate exit policy — it emerges from `target_lots → 0` when conviction collapses.** Splitting "continuous control" from "signal-driven exit" doubly-implements what's actually one mechanism.
### Inheritance from v2
- §4.4 conviction formula (with ε-floor net_edge; not the v1 backwards-fallback): **promoted, unchanged.**
- §4.2 Wiener-α adaptive EMA: **promoted, applied to the multi-horizon conviction scalar instead of `max(|p0.5|)`.**
- §4.3 composite exit signal: **emergent + safety.** The unified target-→-zero path handles the common case; the v2 §4.3 composite formula remains as a safety layer for cases where target-derivation hits an edge (e.g., conviction stuck above zero but trade is deep in loss).
- §5 (CRT.2) and §6 (CRT.3): **unchanged.**
- §7 (open_trade_state 64-byte layout): **promoted to CRT.1.**
- §8 hardcoded-vs-adaptive boundary: **unchanged.**
### Gate restructure (v3)
| v2 Gate | v3 status |
|---|---|
| Gate 1 (Layer A continuous controller) | REMOVED — A and B are co-shipped as CRT.1 |
| Gate 2 (Layer B multi-horizon + exit + state expansion) | **REPROMOTED as Gate CRT.1**, with the v2 §9 Gate 2 tiered MUST/WIN criteria intact |
| Gate 3 (Layer C envelope) | unchanged → Gate CRT.2 |
| Gate 4 (Layer D online) | unchanged → Gate CRT.3 |
### What survives from v1/v2 commits
The following commits are load-bearing and STAY on the branch:
- `a0e81fbdf` — forward_step incremental SSM (A0.5)
- `92f8b10ed` — forward_step_into eliminates GPU↔CPU round-trip (A0.5 corrective)
- `045850e8f` — delete decision_stride field (A1; greenfields atomic)
- `3d8f12deb` — buffer-level seed bit-identity test (A0.5 polish)
What gets REPLACED in CRT.1 implementation:
- `1d889d2de` (A2 scalar conviction-EMA with aggregate rescale) — **superseded** by the multi-horizon §4.4 formula
- `fe2498769` (A2.1 clamp on the broken rescale) — **superseded** for the same reason
The amplification clamp in `fe2498769` and the scalar EMA infrastructure in `1d889d2de` are not load-bearing for CRT.1; the multi-horizon formula replaces the scalar approach end-to-end. Code-wise: the three conviction-EMA device slots (`conviction_ema_d`, `conviction_diff_var_ema_d`, `conviction_sample_var_ema_d`) STAY in `LobSimCuda` — the EMA mechanism is reused on the multi-horizon conviction scalar. What gets deleted: the `final_size *= scale` rescale step in both decision kernels.
---
## v2 changelog (retained for audit trail; superseded by v3 above)
**v2 changelog** (vs v1 commit `0f3484325`):
1. §4.4 conviction: removed backwards cold-start fallback; replaced with ε floor on net_edge for smooth bootstrap. No regime switch when model has zero edge.
@@ -36,41 +119,50 @@ This spec specifies the rebuild.
---
## 2. Architectural Vision
## 2. Architectural Vision (v3 — see "v3 ARCHITECTURE RESET" section above)
Four layers, sequenced. Each independently validatable. Each addresses a specific failure mode visible in the S2 baseline.
**Three phases, sequenced.** The original v2 four-layer split has been merged into three because the empirical Gate-1 evidence + user clarification showed that v2 Layer A (continuous control) and Layer B (signal-driven position management) are the same mechanism.
```
┌────────────────────────────────────────────────────────────────────┐
LAYER A: Continuous Control Loop
Controller runs every event. decision_stride deprecated.
Failure addressed: stale-state decisions.
CRT.1 Unified Inventory Controller
Continuous evaluation (every event), discrete action.
│ - forward_step every event (already shipped via A0.5) │
│ - Multi-horizon ISV-weighted conviction (§4.4) │
│ - target_lots = direction × |conviction_ema| × envelope_max │
│ - Wiener-α EMA on the multi-horizon conviction (§4.2) │
│ - No-trade band on |target current| in seed_inflight │
│ - open_trade_state 24→64 expansion for trajectory (§7) │
│ - Conviction-degradation exit emergent (target→0) + │
│ composite-signal safety circuit-breaker (§4.3) │
│ │
│ Addresses: stale-state decisions, magnitude noise, direction │
│ jitter, fixed-time exits, spread-cost death-spiral. │
├────────────────────────────────────────────────────────────────────┤
LAYER B: Signal-Driven Position Management
Multi-horizon action fusion (h100/h500/h1500/h6000).
Continuous sizing: target_lots = conviction × envelope.
Conviction-degradation exit: replaces max_hold.
│ open_trade_state expanded 24 → 128 bytes for trajectory. │
│ Failure addressed: cap-binding holds, no mid-trade adjustment. │
CRT.2 Adaptive Risk Envelope
ISV-derived max_lots / threshold / target_vol from rolling
Sharpe × drawdown × regime-vol.
Addresses: fixed risk in regime-varying market.
├────────────────────────────────────────────────────────────────────┤
LAYER C: Adaptive Risk Envelope
max_lots: ISV-derived from rolling Sharpe × drawdown × regime-vol.
threshold: conviction-percentile gate.
target_annual_vol: regime-vol-inverse.
│ Failure addressed: fixed risk in regime-varying market. │
├────────────────────────────────────────────────────────────────────┤
│ LAYER D: Online Weight Adaptation │
│ LoRA adapter on frozen base. Trajectory-batch offline updates. │
│ EWC++ regularizer. Shadow eval + circuit-breaker revert. │
│ Failure addressed: static model in non-stationary market. │
CRT.3 Online Weight Adaptation
LoRA + EWC++ + offline-batch trajectory updates + shadow
eval + circuit-breaker revert.
Addresses: static model in non-stationary market.
└────────────────────────────────────────────────────────────────────┘
```
Sequencing rationale: A unlocks event-rate consumption needed by B. B is where alpha lives. C amplifies B by shaping when and how much B trades. D amplifies whatever's working in B+C. Each gate's lift is conditional on the prior gate being green — [no-deferrals-for-complementary-fixes](../../../../home/jgrusewski/.claude/projects/-home-jgrusewski-Work-foxhunt/memory/feedback_no_deferrals_for_complementary_fixes.md) doesn't apply because the layers are amplifications of one another, not independent fixes for orthogonal mechanisms.
**Sequencing rationale (v3):** CRT.1 unifies the signal-to-action mechanism — without it, neither CRT.2 nor CRT.3 has a coherent base to amplify. The v2 phased validation gates collapse one tier: CRT.1's gate is what was Gate 2 (Layer B) in v2; Gate 1 (Layer A) is gone because A standalone is incoherent. The "every gate green before the next" discipline survives.
**The mental model.** Every event: the signal vector is a forward prediction; ISV state tells us how much to trust each horizon; the unified conviction is the weighted aggregate; the target is the optimal inventory given current beliefs. Most events: target moves fractionally from prior — the no-trade band absorbs the noise, no order seeded. When the signal genuinely shifts (or the trade thesis breaks): target moves enough to cross the band, an order seeds, the position adjusts. Continuous evaluation, discrete action. No fixed cadence — the signal IS the cadence.
The detailed sections below were authored in v2 and remain accurate for the mechanisms they describe; the only structural change is that v2 §3 (Layer A) is absorbed into CRT.1, v2 §4 (Layer B) is renamed CRT.1, v2 §5 → CRT.2, v2 §6 → CRT.3.
---
## 3. Layer A — Continuous Control Loop
## 3. Layer A — Continuous Control Loop (v2; ABSORBED INTO CRT.1 IN v3)
**v3 status:** the components of this layer are part of CRT.1. A0.5 (forward_step every event, commits `a0e81fbdf` + `92f8b10ed`) and A1 (decision_stride deletion, commit `045850e8f`) are load-bearing for CRT.1 and stay. The original "Gate 1" for Layer A alone is dropped; validation moves to Gate CRT.1.
### 3.1 Current state
@@ -112,9 +204,16 @@ At event-rate, consecutive decisions see nearly-identical state. If the state→
---
## 4. Layer B — Signal-Driven Position Management
## 4. CRT.1 — Unified Inventory Controller (was "Layer B" in v2)
This is the heart of the rebuild. Three sub-components.
This is the unified architecture in v3. Continuous evaluation, discrete action.
### 4.0 Required additions in v3 vs v2 §4
- **No-trade band**: `seed_inflight_limits_batched` must skip seeding when `|target_lots effective_position| < delta_floor`. `delta_floor` is small (1 lot default for the bootstrap; CRT.2 may make it ISV-derived later). Without this, every fractional target change generates a fill — the v2 Gate-1 empirical failure mode.
- **Multi-horizon conviction promoted from §4.4**: this is the ONLY conviction formula in v3. The scalar `max(|p0.5|)` approach used in v2's A2 commits is dead — it cannot smooth direction jitter and is structurally insufficient.
Everything else in v2 §4.1§4.5 below is retained.
### 4.1 Multi-horizon action fusion