"""V2b: ExecDeadlineDriver — TTL resolution semantics over fake-kernel ports. The real ExecutionRouter and the real DeadlineScheduler are used; only the kernel/venue side is faked so each path (skip, retry, exhaust, market, exit escalation, fill races, rejected-instant, fail-safe gate) can be forced deterministically. Kernel-integration runs live in V2c. """ from __future__ import annotations import asyncio import sys sys.path.insert(0, "/mnt/dolphinng5_predict") import pytest from prod.clean_arch.dita_v2.exec_router import ExecConfig, ExecutionRouter from prod.clean_arch.violet.clock import DeadlineScheduler, LatencyHistogram from prod.clean_arch.violet.exec_driver import ( ExecDeadlineDriver, ExecDriverPorts, ) from prod.clean_arch.violet.domain import ExecDriverSettings from prod.clean_arch.violet.test_violet_scripted_venue import _intent TTL_MS = 30.0 class _FakeRuntime: """slot_view + submit + pump fakes the driver ports plug into.""" def __init__(self): self.slot = ("", "IDLE", 0.0) self.submitted = [] # KernelIntents the driver sent self.pump_hook = None # optional callable run on each pump self.flat = True self.last_fill_ns = 0 async def submit_intent(self, intent): self.submitted.append(intent) return None async def pump_events(self): if self.pump_hook is not None: self.pump_hook() return 0 def ports(self, router): return ExecDriverPorts( router=router, submit_intent=self.submit_intent, pump_events=self.pump_events, slot_view=lambda: self.slot, venue_flat=lambda: self.flat, last_own_fill_mono_ns=lambda: self.last_fill_ns, reference_price=lambda asset: 100.0, ) def _setup(style="maker_both", miss="skip", retries=1, exhaust="skip"): rt = _FakeRuntime() router = ExecutionRouter(ExecConfig( style=style, entry_miss=miss, entry_retries=retries, retry_exhaust=exhaust)) sched = DeadlineScheduler(jitter_hist=LatencyHistogram("jit")) driver = ExecDeadlineDriver( rt.ports(router), sched, settings=ExecDriverSettings(ttl_override_ms=TTL_MS)) return rt, router, sched, driver def _enter_plan(router, tid, px=100.0): return router.plan_entry(trade_id=tid, asset="BTCUSDT", position_side="SHORT", reference_price=px) def _exit_plan(router, tid, px=100.0): return router.plan_exit(trade_id=tid, asset="BTCUSDT", position_side="SHORT", reference_price=px, reason="TAKE_PROFIT") async def _drive(driver, sched, body): sched.start() try: await body() assert await driver.drain(2.0), driver.snapshot() finally: await sched.stop() @pytest.mark.asyncio async def test_expire_skip_cancels_then_clears(): rt, router, sched, driver = _setup(miss="skip") async def body(): plan = _enter_plan(router, "E1") driver.on_submit(plan, _intent("E1", limit_price=plan.limit_price)) assert router.working("E1") is not None await asyncio.sleep(TTL_MS / 1000 + 0.1) await _drive(driver, sched, body) cancels = [i for i in rt.submitted if i.intent_id == "E1-ttlcxl"] assert len(cancels) == 1 and cancels[0].action.value == "CANCEL" assert router.working_orders() == [] assert driver.counters["entry_skips"] == 1 assert driver.ttl_resolution_hist.count == 1 @pytest.mark.asyncio async def test_retry_chain_then_exhaust_skip(): rt, router, sched, driver = _setup(miss="retry", retries=1, exhaust="skip") async def body(): plan = _enter_plan(router, "E2") driver.on_submit(plan, _intent("E2", limit_price=plan.limit_price)) await asyncio.sleep(2 * (TTL_MS / 1000) + 0.3) # two expiries await _drive(driver, sched, body) tids = [i.trade_id for i in rt.submitted if i.action.value == "ENTER"] assert tids == ["E2-r1"] # exactly one retry r1 = next(i for i in rt.submitted if i.trade_id == "E2-r1") assert r1.order_type == "LIMIT" assert r1.metadata["_time_in_force"] == "PostOnly" assert driver.counters["entry_retries"] == 1 assert driver.counters["entry_skips"] == 1 # the exhaust assert router.working_orders() == [] @pytest.mark.asyncio async def test_exhaust_market_submits_market_enter(): rt, router, sched, driver = _setup(miss="retry", retries=0, exhaust="market") async def body(): plan = _enter_plan(router, "E3") driver.on_submit(plan, _intent("E3", limit_price=plan.limit_price)) await asyncio.sleep(TTL_MS / 1000 + 0.15) await _drive(driver, sched, body) markets = [i for i in rt.submitted if i.trade_id == "E3-m"] assert len(markets) == 1 assert markets[0].order_type == "MARKET" assert driver.counters["entry_markets"] == 1 @pytest.mark.asyncio async def test_exit_expiry_escalates_market_same_trade_id(): rt, router, sched, driver = _setup() rt.slot = ("X1", "POSITION_OPEN", 1.0) # position held by X1 async def body(): plan = _exit_plan(router, "X1") assert plan.is_maker driver.on_submit(plan, _intent("X1", limit_price=plan.limit_price)) await asyncio.sleep(TTL_MS / 1000 + 0.15) await _drive(driver, sched, body) mkt = [i for i in rt.submitted if i.intent_id == "X1-mkt"] assert len(mkt) == 1 assert mkt[0].trade_id == "X1" # R1: SAME trade lifecycle assert mkt[0].order_type == "MARKET" assert mkt[0].metadata["_time_in_force"] == "GTC" assert driver.counters["exit_market_fallbacks"] == 1 @pytest.mark.asyncio async def test_fill_racing_cancel_is_noted_not_retried(): rt, router, sched, driver = _setup(miss="retry", retries=3) fired = {"n": 0} def pump_hook(): # The SECOND pump (after the cancel) reveals the fill won the race. fired["n"] += 1 if fired["n"] >= 2: rt.slot = ("E4", "POSITION_OPEN", 1.0) rt.pump_hook = pump_hook async def body(): plan = _enter_plan(router, "E4") driver.on_submit(plan, _intent("E4", limit_price=plan.limit_price)) await asyncio.sleep(TTL_MS / 1000 + 0.15) await _drive(driver, sched, body) assert driver.counters["fills_after_ttl"] == 1 assert driver.counters["entry_retries"] == 0 # no re-quote after a fill assert [i.trade_id for i in rt.submitted if i.action.value == "ENTER"] == [] @pytest.mark.asyncio async def test_on_fill_cancels_deadline_before_expiry(): rt, router, sched, driver = _setup() async def body(): plan = _enter_plan(router, "E5") driver.on_submit(plan, _intent("E5", limit_price=plan.limit_price)) driver.on_fill("E5") # WS fill notification await asyncio.sleep(TTL_MS / 1000 + 0.1) await _drive(driver, sched, body) assert rt.submitted == [] # no cancel ever sent assert driver.counters["deadline_fires"] == 0 assert router.working_orders() == [] @pytest.mark.asyncio async def test_post_only_reject_resolves_instantly(): rt, router, sched, driver = _setup(miss="skip") rt.slot = ("E6", "ORDER_REJECTED", 0.0) async def body(): plan = _enter_plan(router, "E6") driver.on_submit(plan, _intent("E6", limit_price=plan.limit_price)) await asyncio.sleep(0.05) # far below TTL await _drive(driver, sched, body) assert driver.counters["deadline_fires"] == 1 # schedule_in(0) fired now assert any(i.intent_id == "E6-ttlcxl" for i in rt.submitted) assert router.working_orders() == [] @pytest.mark.asyncio async def test_requote_gate_fails_safe_on_probe_error(): rt, router, sched, driver = _setup(miss="retry", retries=2) def boom(): raise RuntimeError("venue probe down") driver.ports.venue_flat = boom async def body(): plan = _enter_plan(router, "E7") driver.on_submit(plan, _intent("E7", limit_price=plan.limit_price)) await asyncio.sleep(TTL_MS / 1000 + 0.15) await _drive(driver, sched, body) assert driver.counters["requote_blocked"] == 1 assert driver.counters["entry_retries"] == 0 # ambiguity ⇒ skip, never quote assert router.working_orders() == [] @pytest.mark.asyncio async def test_immediate_fill_never_registers(): rt, router, sched, driver = _setup() rt.slot = ("E8", "POSITION_OPENED", 1.0) async def body(): plan = _enter_plan(router, "E8") driver.on_submit(plan, _intent("E8", limit_price=plan.limit_price)) await _drive(driver, sched, body) assert driver.counters["immediate_fills"] == 1 assert router.working_orders() == [] assert driver.snapshot()["pending_deadlines"] == 0 if __name__ == "__main__": raise SystemExit(pytest.main([__file__, "-v"]))