VIOLET V3.4c: make boost/beta, signal-gen, OB bit-identical to BLUE (+ exhaustive tests)

Operator directive: VIOLET must do IDENTICALLY what BLUE does for the three parity
flags — approximation cannot guarantee bit-for-bit functioning. Reworked
live_blue_source.py to call BLUE's OWN code paths, not reconstruct/substitute them.

boost/beta — was reading the published DOLPHIN_FEATURES.acb_boost scalar
(acb_processor_service's daily value). BLUE's trader does NOT use that for sizing; it
recomputes live via acb.get_dynamic_boost_from_hz(exf_latest, w750_velocity, direction)
with a bare AdaptiveCircuitBreaker() and NO ob_engine (nautilus_event_trader.py
on_exf_update:4769 / rollover prewarm:2710). New _source_boost_beta replicates that call
exactly (reads exf_latest + latest_eigen_scan.w750_velocity; 0.0→None like BLUE; on stale
exf ValueError → neutral, mirroring BLUE's "ACB Stale Data Fallback"). The published
acb_boost is never read. Test pins bit-identity against the real ACB.

signal-gen (dc_status) — was AlphaSignalGenerator() bare defaults; coincidentally equal to
BLUE today, but BLUE builds it from ENGINE_KWARGS (trader:128-133, threaded at
esf_alpha_orchestrator.py:180-191), so a champion retune would silently diverge. Now
constructed with BLUE_SIGNAL_GEN_KWARGS (vel_div_* imported from the kernel constants).
Test parses ENGINE_KWARGS from the trader source and asserts each param matches — drift
becomes a red test, not a silent miss.

OB — was a reinvented HazelcastOBProvider reading asset_*_ob with custom parsing. Now uses
BLUE's OWN HZOBProvider + OBFeatureEngine, wired exactly as _wire_obf
(nautilus_event_trader.py:4967-4980): step_live(assets, bar_idx) then get_market. Engine
is injectable + persistent so OB accumulation matches BLUE across scans (caller owns it).

Deleted: HazelcastOBProvider, _extract_acb, the status-label mc path. mc_scale fix
(begin_day cat/env thresholds) retained. Module docstring + structural-divergence doc
updated: all three flags FIXED; only _derive_mc_scale remains hand-replicated (pinned by
formula test). OPEN follow-up: launcher shadow_decision_step should pass a persistent
ob_engine + bar_idx for cross-scan OB history.

34 tests (33 + live-HZ smoke deselected): boost/beta-vs-ACB bit-identity (incl. w750=0→None,
no-exf, stale ValueError, ignores acb_boost), signal-gen ENGINE_KWARGS pin (parametrized),
OB wiring (step_live call, HZ coords, neutral paths), mc_scale formula, sequence dc/selector
parity, anomaly handling. violet-only; no shared-file edits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-06-16 17:33:01 +02:00
parent 1415a65670
commit fac287d678
3 changed files with 470 additions and 455 deletions

View File

@@ -46,16 +46,22 @@ not mechanical; it requires a human to know which VIOLET fragment mirrors which
| `strength_cubic` | `esf_alpha_orchestrator.py:872-885` | `sizing.VioletSizer.strength_cubic` | same gate | LOW-MED |
| `market_ob_mult` consensus | `esf_alpha_orchestrator.py:587-595` | `sizing.VioletSizer.market_ob_mult` | same gate | MED |
| `dc_lev_mult` | `esf_alpha_orchestrator.py:575-577` | `sizing.VioletSizer.dc_lev_mult` | unit only | MED (but ≡1.0 while dc_leverage_boost=1.0) |
| **`mc_scale`** | `esf_alpha_orchestrator.py:956-962` (`begin_day`) | `live_blue_source._derive_mc_scale` | **unit only — NO pin to BLUE's fn** | **HIGH** |
| `boost`/`beta` source | trader recompute `acb.get_dynamic_boost_from_hz(exf_latest)` | reads published `DOLPHIN_FEATURES.acb_boost` (acb_processor_service) | none | MED (two surfaces may differ on dynamic-β / OB Sub-4) |
| `dc_status` config | `signal_gen` built with threaded params `:180-191` | `AlphaSignalGenerator()` **bare defaults** | none | MED (cosmetic while dc_lev_mult≡1.0) |
| OB feed shape | live OB accumulation | single-snapshot `HazelcastOBProvider` + `bar_idx=0` | none | MED |
| **`mc_scale`** | `esf_alpha_orchestrator.py:956-962` (`begin_day`) | `live_blue_source._derive_mc_scale` | parametrized formula test (8 cases inc. divergences) | LOW-MED (only remaining hand-replica) |
| `boost`/`beta` source | trader recompute `acb.get_dynamic_boost_from_hz(exf_latest)` | **FIXED 2026-06-16**: `_source_boost_beta` calls the SAME `get_dynamic_boost_from_hz` over exf_latest+w750 (bare `AdaptiveCircuitBreaker()`, no ob_engine) | bit-identity test vs the real ACB | LOW |
| `dc_status` config | `signal_gen` built with ENGINE_KWARGS `:180-191` | **FIXED**: `AlphaSignalGenerator(**BLUE_SIGNAL_GEN_KWARGS)` | param test parses ENGINE_KWARGS from trader source | LOW |
| OB feed | live OB accumulation via `HZOBProvider` | **FIXED**: BLUE's own `HZOBProvider` + `OBFeatureEngine` + `step_live`/`get_market` (persistent engine + bar_idx) | wiring test (HZ coords, step_live call) | LOW (caller must pass persistent engine) |
The worst link is **`mc_scale`**: pure duplication of `begin_day`'s thresholds with no
test that pins it to BLUE's actual function (BLUE computes it inline inside `begin_day`,
which is not callable in isolation). The V3.4c bug fixed on 2026-06-16 (the adapter keyed
off the MC service's `status` label instead of BLUE's `cat`/`env` thresholds) is exactly
the failure mode this structure invites.
**Update 2026-06-16:** the three MED-risk flags above were brought to bit-identity per
operator directive ("VIOLET should do *identically* what BLUE does"). boost/beta now call
the SAME `get_dynamic_boost_from_hz` BLUE's trader calls (the published `acb_boost` is NOT
used); dc_status uses `AlphaSignalGenerator` pinned to BLUE's ENGINE_KWARGS; OB uses BLUE's
`HZOBProvider`. The reinvented `HazelcastOBProvider` and the `_extract_acb`/`status`-label
paths were deleted. The ONLY remaining hand-replicated arithmetic is `_derive_mc_scale`
(begin_day computes it inline inside an un-callable method), pinned by a formula test.
OPEN follow-up: the launcher (`shadow_decision_step`) must pass a PERSISTENT `ob_engine` +
per-scan-incrementing `bar_idx` into `source_live_blue_sizing_factors` so OB accumulation
matches BLUE across scans; today it single-shots, which is wired-correctly but historyless.
## Why we accept it (for now)