PINK: TUI Hz fix + DC gate + ACB boost + 10 new tests (104/104 green)
TUI Hz fix: - hazelcast_projection.py: write_engine_snapshot now writes all NAUTILUS-era field aliases (trades_executed, current_leverage, open_positions as list, last_scan_number, last_vel_div, vol_ok, open_notional) so gear_rows/capital panel work with no TUI changes. - dolphin_status_pink.py: _normalize_eng_for_tui() safety-net translation added; render() uses it on every Hz read. DC gate (SYSTEM BIBLE §4.2, champion config): - pink_direct.py: _dc_contradicts() — 7-tick lookback, 0.75 bps threshold. Rising price (chg > 0.75 bps) blocks ENTER via dataclasses.replace(HOLD, DC_CONTRADICT). Price history deque initialized in connect(); dc_skip_contradicts=True enforced. ACB boost (SYSTEM BIBLE §10): - hazelcast_feed.py: fix wrong key "latest_acb" → "acb_boost" (DOLPHIN_FEATURES key written by acb_processor_service.py). - pink_direct.py: _last_acb_boost read from scan_payload["acb_boost"] first (scan bridge may embed it), then Hz direct fallback. Applied to intent.leverage via dataclasses.replace() after IntentEngine.plan(), capped at 3x. - _last_scan_number, _last_vel_div, _last_vol_ok tracked from scan_payload. OBF gate: NOT implemented. OBF shards (DOLPHIN_FEATURES_SHARD_*) require new Hz map connections + symbol routing. Gap documented; requires separate decision. Tests: TestDCGate (5) + TestNormalizeEngForTui (5) — 10 new, 104 total, all green. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1607,13 +1607,46 @@ def gear_rows(eng, safe, acb, exf, hb, obf_universe=None):
|
||||
return sig_row, trade_row, fill
|
||||
|
||||
|
||||
def _normalize_eng_for_tui(eng: dict) -> dict:
|
||||
"""Translate DITAv2 Hz engine_snapshot fields to TUI-expected NAUTILUS-era names.
|
||||
|
||||
PinkHzStateWriter already writes the TUI-compatible aliases; this function is a
|
||||
defensive fallback in case any older or partial snapshot lands in Hz.
|
||||
"""
|
||||
if not eng:
|
||||
return {}
|
||||
# If it already has the NAUTILUS-era field, it's either the new DITAv2 format
|
||||
# (which writes both) or old NAUTILUS format — either way, return as-is.
|
||||
if "trades_executed" in eng:
|
||||
return eng
|
||||
# Minimal translation for any snapshot that only has DITAv2 fields
|
||||
out = dict(eng)
|
||||
slot = eng.get("slot") or {}
|
||||
size = float(slot.get("size") or 0.0)
|
||||
ep = float(slot.get("entry_price") or 0.0)
|
||||
out.setdefault("trades_executed", eng.get("trade_seq", 0))
|
||||
out.setdefault("current_leverage", eng.get("our_leverage", 0.0))
|
||||
out.setdefault("leverage_abs_cap", 3.0)
|
||||
out.setdefault("open_notional", size * ep)
|
||||
out.setdefault("last_scan_number", eng.get("scan_number", 0))
|
||||
out.setdefault("scans_processed", eng.get("scan_number", 0))
|
||||
out.setdefault("last_vel_div", 0.0)
|
||||
out.setdefault("vol_ok", True)
|
||||
out.setdefault("bar_idx", 0)
|
||||
# open_positions: TUI expects a list (len() is called on it)
|
||||
open_int = int(eng.get("open_positions", 0))
|
||||
if not isinstance(eng.get("open_positions"), list):
|
||||
out["open_positions"] = [slot] if open_int > 0 and slot else []
|
||||
return out
|
||||
|
||||
|
||||
def render(hz):
|
||||
global START_CAP, CAP_PEAK
|
||||
|
||||
# ── DITAv2 kernel + BingX account (reads kernel snapshot file, not Hz) ──
|
||||
ditav2_section = _render_ditav2_section()
|
||||
|
||||
eng = _get(hz, PINK_STATE_MAP, "engine_snapshot")
|
||||
eng = _normalize_eng_for_tui(_get(hz, PINK_STATE_MAP, "engine_snapshot"))
|
||||
cap = _get(hz, PINK_STATE_MAP, "capital_checkpoint")
|
||||
safe = _get(hz, PINK_SAFETY_MAP, "latest")
|
||||
hb = _get(hz, PINK_HEARTBEAT_MAP, PINK_HEARTBEAT_KEY)
|
||||
|
||||
Reference in New Issue
Block a user