Snapshot PINK DITAv2 system + Sprint 0 flaw-fix verification

First commit of the previously-untracked PINK-on-DITAv2 migration system
(execution moves to the Rust kernel; policy stays on legacy DITA, so Alpha
Engine algorithmic integrity is preserved). BLUE is untouched.

Sprint 0 (safety snapshot + flaw-fix verification, MARKET single-leg scope):
- Verified Rust FSM fixes (flaws 2,4,10,11,13) by source read of lib.rs.
- Hardened 5 vacuous/guarded assertions in test_flaws.py so each flaw test
  genuinely exercises its fix. Most important: Flaw 5 now asserts capital
  moves by EXACTLY realized PnL (was entering/exiting at the same price).
- Offline suites: 533 passed, 0 failed (35 flaws + 402 kernel/accounting/
  bridge + 96 runtime/persistence/multi-exit/restart/seams).
- GATE PASS: MARKET-path-critical flaws 1,2,5 confirmed fixed + green.
- Added SPRINT0_FLAW_VERIFICATION.md report and _rust_kernel/.gitignore
  (excludes Rust target/ build artifacts).

LIMIT/partial-fill remain explicitly out of scope (MARKET-only bring-up).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Codex
2026-05-30 18:26:43 +02:00
parent 34d01fe6a4
commit 3d7b00e28d
89 changed files with 32782 additions and 0 deletions

View File

@@ -0,0 +1,202 @@
from __future__ import annotations
import json
import random
import threading
from dataclasses import dataclass
import importlib.util
from pathlib import Path
import pytest
_MOD_PATH = Path("/mnt/dolphinng5_predict/prod/nautilus_event_trader.py")
_SPEC = importlib.util.spec_from_file_location("nautilus_event_trader_mod", _MOD_PATH)
assert _SPEC and _SPEC.loader
mod = importlib.util.module_from_spec(_SPEC)
_SPEC.loader.exec_module(mod) # type: ignore[arg-type]
@dataclass
class _Pos:
trade_id: str
asset: str
entry_price: float
notional: float
current_price: float = 0.0
pnl_pct: float = 0.0
class _ExitMgr:
def __init__(self):
self._positions: dict[str, dict] = {}
class _Eng:
def __init__(self, pos: _Pos | None):
self.position = pos
self.capital = 25_000.0
self.exit_manager = _ExitMgr()
if pos:
self.exit_manager._positions[pos.trade_id] = {"dummy": True}
class _Map:
def __init__(self):
self._d = {"blue_runtime_commands": "[]"}
self._lock = threading.Lock()
def blocking(self):
return self
def get(self, key):
with self._lock:
return self._d.get(key)
def put(self, key, val):
with self._lock:
self._d[key] = val
class _F:
def add_done_callback(self, _cb):
return None
return _F()
def _mk_trader():
t = object.__new__(mod.DolphinLiveTrader)
t.eng_lock = threading.Lock()
t.control_map = _Map()
t._processed_retract_commands = mod.deque(maxlen=5000)
t._processed_retract_set = set()
t._pending_entries = {}
t.current_day = "2026-05-12"
t.bar_idx = 100
return t
def _install_open_position(t, *, trade_id="T", asset="STXUSDT", entry_price=1.0, notional=1000.0):
p = _Pos(trade_id, asset, entry_price, notional, current_price=entry_price)
t.eng = _Eng(p)
t._pending_entries[trade_id] = {
"trade_id": trade_id,
"asset": asset,
"side": "SHORT",
"entry_price": entry_price,
"entry_bar": 90,
"entry_date": "2026-05-12",
"notional": notional,
"notional_entry": notional,
"retraction_legs": 0,
"realized_pnl_legs_total": 0.0,
}
t._pending_entries[trade_id].update(t._chain_state_for_pending(
trade_id,
t._pending_entries[trade_id],
chain_mode="LIVE",
chain_head_leg_id=f"{trade_id}:open",
chain_prev_leg_id="",
chain_seq=0,
))
def test_fuzz_retraction_invariants_hold_under_random_command_stream(monkeypatch):
monkeypatch.setattr(mod, "ch_put", lambda *_args, **_kwargs: None)
monkeypatch.setattr(mod, "_ch_ts_us", lambda: 123)
rng = random.Random(20260512)
t = _mk_trader()
_install_open_position(t, trade_id="T-FUZZ", asset="STXUSDT", entry_price=1.0, notional=10_000.0)
seen_ids: set[str] = set()
baseline_cap = t.eng.capital
for i in range(2500):
if t.eng.position is None:
break
px = max(0.00001, 1.0 + rng.uniform(-0.25, 0.25))
# Mix valid and invalid commands.
frac_choice = rng.choice([
rng.uniform(0.01, 1.0), # valid
0.0, # invalid
-0.1, # invalid
1.2, # invalid
])
# inject duplicate ids often
if i > 0 and rng.random() < 0.2:
cid = rng.choice(tuple(seen_ids)) if seen_ids else f"c-{i}"
else:
cid = f"c-{i}-{rng.randint(0, 999)}"
seen_ids.add(cid)
# wrong trade ids sometimes
tid = "T-FUZZ" if rng.random() < 0.8 else f"OTHER-{i}"
pending = t._pending_entries["T-FUZZ"]
cmd = {
"command_id": cid,
"trade_id": tid,
"action": "RETRACT",
"fraction": frac_choice,
"reason": "HOTKEY_RETRACT",
"source": "fuzz",
"chain_root_trade_id": pending["chain_root_trade_id"],
"chain_head_leg_id": pending["chain_head_leg_id"],
"chain_prev_leg_id": pending["chain_prev_leg_id"],
"chain_seq": pending["chain_seq"],
"chain_token": pending["chain_token"],
}
t.control_map.put("blue_runtime_commands", json.dumps([cmd]))
t._process_runtime_commands({"STXUSDT": px})
if t.eng.position is not None:
n = float(t.eng.position.notional)
assert n >= -1e-8
# never exceed original notional
assert n <= 10_000.0 + 1e-8
p = t._pending_entries["T-FUZZ"]
assert int(p.get("retraction_legs", 0) or 0) >= 0
# Capital must stay finite and deterministic.
assert t.eng.capital == pytest.approx(float(t.eng.capital))
assert abs(t.eng.capital - baseline_cap) < 1e7
def test_fuzz_concurrent_queue_submission_and_drain(monkeypatch):
monkeypatch.setattr(mod, "ch_put", lambda *_args, **_kwargs: None)
monkeypatch.setattr(mod, "_ch_ts_us", lambda: 123)
rng = random.Random(777)
t = _mk_trader()
_install_open_position(t, trade_id="T-RACE", asset="DASHUSDT", entry_price=10.0, notional=5000.0)
def producer(start: int, count: int):
for i in range(start, start + count):
with t.control_map._lock:
raw = t.control_map._d.get("blue_runtime_commands", "[]")
q = json.loads(raw) if raw else []
q.append({
"command_id": f"p-{i}",
"trade_id": "T-RACE" if rng.random() < 0.9 else "OTHER",
"action": "RETRACT",
"fraction": rng.uniform(0.01, 1.0),
"reason": "HOTKEY_RETRACT",
"source": "race",
"chain_root_trade_id": t._pending_entries["T-RACE"]["chain_root_trade_id"],
"chain_head_leg_id": t._pending_entries["T-RACE"]["chain_head_leg_id"],
"chain_prev_leg_id": t._pending_entries["T-RACE"]["chain_prev_leg_id"],
"chain_seq": t._pending_entries["T-RACE"]["chain_seq"],
"chain_token": t._pending_entries["T-RACE"]["chain_token"],
})
t.control_map._d["blue_runtime_commands"] = json.dumps(q[-200:])
threads = [threading.Thread(target=producer, args=(k * 120, 120)) for k in range(4)]
for th in threads:
th.start()
for th in threads:
th.join()
# Drain repeatedly; must not throw and must preserve invariants.
for _ in range(50):
if t.eng.position is None:
break
t._process_runtime_commands({"DASHUSDT": rng.uniform(8.0, 12.0)})
if t.eng.position is not None:
assert t.eng.position.notional >= -1e-8
assert t.eng.position.notional <= 5000.0 + 1e-8