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,579 @@
from __future__ import annotations
from datetime import datetime, timezone
import random
from typing import Any
import pytest
from prod.clean_arch.dita_v2 import (
AccountProjection,
BingxVenueAdapter,
BackendMode,
ControlUpdate,
ExecutionKernel,
InMemoryControlPlane,
InMemoryZincPlane,
KernelCommandType,
KernelControlSnapshot,
KernelDiagnosticCode,
KernelEventKind,
KernelIntent,
KernelMode,
KernelOutcome,
KernelSeverity,
KernelVerbosity,
MemoryKernelJournal,
MockVenueAdapter,
MockVenueScenario,
TradeSide,
TradeSlot,
TradeStage,
VenueEvent,
VenueEventStatus,
VenueOrder,
VenueOrderStatus,
)
def mk_intent(
*,
action: KernelCommandType = KernelCommandType.ENTER,
slot_id: int = 0,
trade_id: str = "trade-1",
asset: str = "BTCUSDT",
side: TradeSide = TradeSide.SHORT,
target_size: float = 1.0,
leverage: float = 2.0,
reference_price: float = 100.0,
exit_leg_ratios=(1.0,),
reason: str = "TEST",
) -> KernelIntent:
return KernelIntent(
timestamp=datetime.now(timezone.utc),
intent_id=f"intent-{trade_id}-{action.value}",
trade_id=trade_id,
slot_id=slot_id,
asset=asset,
side=side,
action=action,
reference_price=reference_price,
target_size=target_size,
leverage=leverage,
exit_leg_ratios=tuple(exit_leg_ratios),
reason=reason,
)
def mk_event(
*,
kind: KernelEventKind,
status: VenueEventStatus,
trade_id: str = "trade-1",
slot_id: int = 0,
venue_order_id: str = "V-00000001",
venue_client_id: str = "trade-1:intent-1",
side: TradeSide = TradeSide.SHORT,
asset: str = "BTCUSDT",
price: float = 100.0,
size: float = 1.0,
filled_size: float = 1.0,
remaining_size: float = 0.0,
reason: str = "",
) -> VenueEvent:
return VenueEvent(
timestamp=datetime.now(timezone.utc),
event_id=f"evt-{kind.value.lower()}",
trade_id=trade_id,
slot_id=slot_id,
kind=kind,
status=status,
venue_order_id=venue_order_id,
venue_client_id=venue_client_id,
side=side,
asset=asset,
price=price,
size=size,
filled_size=filled_size,
remaining_size=remaining_size,
reason=reason,
raw_payload={"status": status.value},
)
def mk_kernel(
*,
max_slots: int = 3,
venue: Any | None = None,
control_mode: KernelMode = KernelMode.DEBUG,
verbosity: KernelVerbosity = KernelVerbosity.TRACE,
) -> ExecutionKernel:
return ExecutionKernel(
max_slots=max_slots,
control_plane=InMemoryControlPlane(
KernelControlSnapshot(mode=control_mode, verbosity=verbosity, backend_mode=BackendMode.MOCK)
),
venue=venue or MockVenueAdapter(),
journal=MemoryKernelJournal(),
zinc_plane=InMemoryZincPlane(),
account=AccountProjection(),
)
def _seed_open_slot(slot: TradeSlot, *, trade_id: str = "trade-1", asset: str = "BTCUSDT") -> None:
slot.trade_id = trade_id
slot.asset = asset
slot.side = TradeSide.SHORT
slot.entry_price = 100.0
slot.size = 1.0
slot.initial_size = 1.0
slot.leverage = 2.0
slot.fsm_state = TradeStage.POSITION_OPEN
slot.active_entry_order = VenueOrder(
internal_trade_id=trade_id,
venue_order_id="V-00000001",
venue_client_id=f"{trade_id}:entry",
side=TradeSide.SHORT,
intended_size=1.0,
status=VenueOrderStatus.FILLED,
metadata={"slot_id": slot.slot_id, "asset": asset},
)
def _seed_entry_order(slot: TradeSlot, *, trade_id: str = "trade-1", asset: str = "BTCUSDT", status: VenueOrderStatus = VenueOrderStatus.NEW) -> None:
slot.active_entry_order = VenueOrder(
internal_trade_id=trade_id,
venue_order_id="V-00000001",
venue_client_id=f"{trade_id}:entry",
side=TradeSide.SHORT,
intended_size=1.0,
status=status,
metadata={"slot_id": slot.slot_id, "asset": asset},
)
def _seed_exit_order(slot: TradeSlot, *, trade_id: str = "trade-1", asset: str = "BTCUSDT", intended_size: float = 0.5) -> None:
slot.active_exit_order = VenueOrder(
internal_trade_id=trade_id,
venue_order_id="V-00000002",
venue_client_id=f"{trade_id}:exit",
side=TradeSide.SHORT,
intended_size=intended_size,
status=VenueOrderStatus.NEW,
metadata={"slot_id": slot.slot_id, "asset": asset},
)
def _configure_slot_state(slot: TradeSlot, state: TradeStage, *, trade_id: str = "trade-1", asset: str = "BTCUSDT") -> None:
slot.trade_id = trade_id if state not in {TradeStage.IDLE, TradeStage.CLOSED} else ""
slot.asset = asset if state not in {TradeStage.IDLE, TradeStage.CLOSED} else ""
slot.side = TradeSide.SHORT if state not in {TradeStage.IDLE, TradeStage.CLOSED} else TradeSide.FLAT
slot.entry_price = 100.0 if state not in {TradeStage.IDLE, TradeStage.CLOSED} else 0.0
slot.size = 1.0 if state in {TradeStage.POSITION_OPEN, TradeStage.EXIT_WORKING, TradeStage.EXIT_REQUESTED, TradeStage.EXIT_SENT, TradeStage.ENTRY_WORKING, TradeStage.ORDER_REQUESTED, TradeStage.ORDER_SENT} else 0.0
slot.initial_size = slot.size
slot.leverage = 2.0 if state not in {TradeStage.IDLE, TradeStage.CLOSED} else 0.0
slot.fsm_state = state
slot.closed = state == TradeStage.CLOSED
slot.active_entry_order = None
slot.active_exit_order = None
if state in {TradeStage.ORDER_REQUESTED, TradeStage.ORDER_SENT, TradeStage.ENTRY_WORKING, TradeStage.POSITION_OPEN, TradeStage.POSITION_OPENED}:
slot.active_entry_order = VenueOrder(
internal_trade_id=trade_id,
venue_order_id="V-00000001",
venue_client_id=f"{trade_id}:entry",
side=TradeSide.SHORT,
intended_size=1.0,
status=VenueOrderStatus.NEW if state in {TradeStage.ORDER_REQUESTED, TradeStage.ORDER_SENT, TradeStage.ENTRY_WORKING} else VenueOrderStatus.FILLED,
metadata={"slot_id": slot.slot_id, "asset": asset},
)
if state in {TradeStage.EXIT_REQUESTED, TradeStage.EXIT_SENT, TradeStage.EXIT_WORKING}:
slot.active_exit_order = VenueOrder(
internal_trade_id=trade_id,
venue_order_id="V-00000002",
venue_client_id=f"{trade_id}:exit",
side=TradeSide.SHORT,
intended_size=0.5,
status=VenueOrderStatus.NEW,
metadata={"slot_id": slot.slot_id, "asset": asset},
)
# 18 invalid-intent slot tests
@pytest.mark.parametrize(
"slot_id,action,expected",
[
(-1, KernelCommandType.ENTER, KernelDiagnosticCode.INVALID_SLOT_ID),
(-1, KernelCommandType.EXIT, KernelDiagnosticCode.INVALID_SLOT_ID),
(-1, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.INVALID_SLOT_ID),
(-1, KernelCommandType.RECONCILE, KernelDiagnosticCode.INVALID_SLOT_ID),
(-1, KernelCommandType.CANCEL, KernelDiagnosticCode.INVALID_SLOT_ID),
(3, KernelCommandType.ENTER, KernelDiagnosticCode.INVALID_SLOT_ID),
(3, KernelCommandType.EXIT, KernelDiagnosticCode.INVALID_SLOT_ID),
(3, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.INVALID_SLOT_ID),
(3, KernelCommandType.RECONCILE, KernelDiagnosticCode.INVALID_SLOT_ID),
(3, KernelCommandType.CANCEL, KernelDiagnosticCode.INVALID_SLOT_ID),
(99, KernelCommandType.ENTER, KernelDiagnosticCode.INVALID_SLOT_ID),
(99, KernelCommandType.EXIT, KernelDiagnosticCode.INVALID_SLOT_ID),
(99, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.INVALID_SLOT_ID),
(99, KernelCommandType.RECONCILE, KernelDiagnosticCode.INVALID_SLOT_ID),
(99, KernelCommandType.CANCEL, KernelDiagnosticCode.INVALID_SLOT_ID),
(7, KernelCommandType.ENTER, KernelDiagnosticCode.INVALID_SLOT_ID),
(7, KernelCommandType.EXIT, KernelDiagnosticCode.INVALID_SLOT_ID),
(7, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.INVALID_SLOT_ID),
],
)
def test_kernel_rejects_invalid_slot_ids_with_codes(slot_id: int, action: KernelCommandType, expected: KernelDiagnosticCode) -> None:
kernel = mk_kernel(max_slots=3)
outcome = kernel.process_intent(mk_intent(slot_id=slot_id, action=action))
assert outcome.accepted is False
assert outcome.diagnostic_code == expected
assert outcome.details["reason"] == "INVALID_SLOT_ID"
# 20 entry-path tests
@pytest.mark.parametrize(
"scenario,expected_state,expected_code,expected_size",
[
(MockVenueScenario(emit_fill_on_submit=True, partial_fill_ratio=1.0), TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK, 1.0),
(MockVenueScenario(emit_fill_on_submit=True, partial_fill_ratio=0.5), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.5),
(MockVenueScenario(emit_fill_on_submit=False, partial_fill_ratio=0.5), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.5),
(MockVenueScenario(reject_entries=True), TradeStage.IDLE, KernelDiagnosticCode.OK, 0.0),
(MockVenueScenario(emit_fill_on_submit=True, partial_fill_ratio=0.25), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.25),
(MockVenueScenario(emit_fill_on_submit=True, partial_fill_ratio=0.75), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.75),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=False, partial_fill_ratio=0.0), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.0),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=True, partial_fill_ratio=1.0), TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK, 1.0),
(MockVenueScenario(emit_ack_before_fill=False, emit_fill_on_submit=True, partial_fill_ratio=1.0), TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK, 1.0),
(MockVenueScenario(emit_ack_before_fill=False, emit_fill_on_submit=True, partial_fill_ratio=0.5), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.5),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=True, partial_fill_ratio=0.9), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.9),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=True, partial_fill_ratio=0.1), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.1),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=True, partial_fill_ratio=1.0, reject_entries=False), TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK, 1.0),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=False, partial_fill_ratio=1.0), TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK, 1.0),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=False, partial_fill_ratio=0.2), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.2),
(MockVenueScenario(emit_ack_before_fill=False, emit_fill_on_submit=False, partial_fill_ratio=0.3), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.3),
(MockVenueScenario(emit_ack_before_fill=False, emit_fill_on_submit=False, partial_fill_ratio=1.0), TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK, 1.0),
(MockVenueScenario(emit_ack_before_fill=False, emit_fill_on_submit=False, partial_fill_ratio=0.0), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.0),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=True, partial_fill_ratio=0.6), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.6),
(MockVenueScenario(emit_ack_before_fill=True, emit_fill_on_submit=True, partial_fill_ratio=0.4), TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK, 0.4),
],
)
def test_kernel_entry_path_matrix(
scenario: MockVenueScenario,
expected_state: TradeStage,
expected_code: KernelDiagnosticCode,
expected_size: float,
) -> None:
kernel = mk_kernel(venue=MockVenueAdapter(scenario))
outcome = kernel.process_intent(mk_intent())
assert outcome.accepted is True
assert outcome.diagnostic_code == expected_code
assert kernel.slot(0).fsm_state == expected_state
assert kernel.slot(0).size == pytest.approx(expected_size, abs=1e-6)
# 20 exit-path tests
@pytest.mark.parametrize(
"initial_state,event_kind,event_status,expected_state,expected_code",
[
(TradeStage.POSITION_OPEN, KernelEventKind.PARTIAL_FILL, VenueEventStatus.PARTIALLY_FILLED, TradeStage.EXIT_WORKING, KernelDiagnosticCode.OK),
(TradeStage.POSITION_OPEN, KernelEventKind.FULL_FILL, VenueEventStatus.FILLED, TradeStage.CLOSED, KernelDiagnosticCode.OK),
(TradeStage.EXIT_REQUESTED, KernelEventKind.PARTIAL_FILL, VenueEventStatus.PARTIALLY_FILLED, TradeStage.EXIT_WORKING, KernelDiagnosticCode.OK),
(TradeStage.EXIT_REQUESTED, KernelEventKind.FULL_FILL, VenueEventStatus.FILLED, TradeStage.CLOSED, KernelDiagnosticCode.OK),
(TradeStage.EXIT_SENT, KernelEventKind.PARTIAL_FILL, VenueEventStatus.PARTIALLY_FILLED, TradeStage.EXIT_WORKING, KernelDiagnosticCode.OK),
(TradeStage.EXIT_SENT, KernelEventKind.FULL_FILL, VenueEventStatus.FILLED, TradeStage.CLOSED, KernelDiagnosticCode.OK),
(TradeStage.EXIT_WORKING, KernelEventKind.PARTIAL_FILL, VenueEventStatus.PARTIALLY_FILLED, TradeStage.EXIT_WORKING, KernelDiagnosticCode.OK),
(TradeStage.EXIT_WORKING, KernelEventKind.FULL_FILL, VenueEventStatus.FILLED, TradeStage.CLOSED, KernelDiagnosticCode.OK),
(TradeStage.EXIT_WORKING, KernelEventKind.CANCEL_ACK, VenueEventStatus.CANCELED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(TradeStage.EXIT_WORKING, KernelEventKind.CANCEL_REJECT, VenueEventStatus.CANCELED_REJECTED, TradeStage.EXIT_WORKING, KernelDiagnosticCode.CANCEL_REJECTED),
(TradeStage.POSITION_OPEN, KernelEventKind.CANCEL_ACK, VenueEventStatus.CANCELED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(TradeStage.POSITION_OPEN, KernelEventKind.CANCEL_REJECT, VenueEventStatus.CANCELED_REJECTED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.CANCEL_REJECTED),
(TradeStage.EXIT_REQUESTED, KernelEventKind.CANCEL_ACK, VenueEventStatus.CANCELED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(TradeStage.EXIT_SENT, KernelEventKind.CANCEL_ACK, VenueEventStatus.CANCELED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(TradeStage.EXIT_REQUESTED, KernelEventKind.CANCEL_REJECT, VenueEventStatus.CANCELED_REJECTED, TradeStage.EXIT_REQUESTED, KernelDiagnosticCode.CANCEL_REJECTED),
(TradeStage.EXIT_SENT, KernelEventKind.CANCEL_REJECT, VenueEventStatus.CANCELED_REJECTED, TradeStage.EXIT_SENT, KernelDiagnosticCode.CANCEL_REJECTED),
(TradeStage.POSITION_OPEN, KernelEventKind.ORDER_REJECT, VenueEventStatus.REJECTED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.EXIT_ORDER_REJECTED),
(TradeStage.EXIT_WORKING, KernelEventKind.ORDER_REJECT, VenueEventStatus.REJECTED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.EXIT_ORDER_REJECTED),
(TradeStage.EXIT_REQUESTED, KernelEventKind.ORDER_REJECT, VenueEventStatus.REJECTED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.EXIT_ORDER_REJECTED),
(TradeStage.EXIT_SENT, KernelEventKind.ORDER_REJECT, VenueEventStatus.REJECTED, TradeStage.POSITION_OPEN, KernelDiagnosticCode.EXIT_ORDER_REJECTED),
],
)
def test_kernel_exit_path_matrix(
initial_state: TradeStage,
event_kind: KernelEventKind,
event_status: VenueEventStatus,
expected_state: TradeStage,
expected_code: KernelDiagnosticCode,
) -> None:
kernel = mk_kernel()
slot = kernel.slot(0)
_configure_slot_state(slot, initial_state)
if event_kind in {KernelEventKind.ORDER_REJECT, KernelEventKind.PARTIAL_FILL, KernelEventKind.FULL_FILL}:
_seed_exit_order(slot, trade_id=slot.trade_id or "trade-1", asset="BTCUSDT", intended_size=slot.size or 0.5)
if initial_state in {TradeStage.EXIT_REQUESTED, TradeStage.EXIT_SENT, TradeStage.EXIT_WORKING} and event_kind in {
KernelEventKind.CANCEL_ACK,
KernelEventKind.CANCEL_REJECT,
KernelEventKind.ORDER_ACK,
}:
_seed_exit_order(slot, trade_id=slot.trade_id or "trade-1", asset="BTCUSDT", intended_size=slot.size or 0.5)
outcome = kernel.on_venue_event(
mk_event(
kind=event_kind,
status=event_status,
trade_id=slot.trade_id or "trade-1",
venue_order_id=slot.active_exit_order.venue_order_id if slot.active_exit_order else "V-00000002",
venue_client_id=slot.active_exit_order.venue_client_id if slot.active_exit_order else "trade-1:exit",
side=TradeSide.SHORT,
asset="BTCUSDT",
size=float(slot.size or 0.5),
filled_size=float(slot.size or 0.5) if event_kind == KernelEventKind.FULL_FILL else float((slot.size or 0.5) / 2.0),
remaining_size=0.0,
)
)
assert outcome.diagnostic_code == expected_code
assert kernel.slot(0).fsm_state == expected_state
# 18 event-resolution tests
@pytest.mark.parametrize(
"event,initial_state,expected_state,expected_code",
[
(mk_event(kind=KernelEventKind.ORDER_ACK, status=VenueEventStatus.ACKED), TradeStage.IDLE, TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.ORDER_ACK, status=VenueEventStatus.ACKED), TradeStage.EXIT_REQUESTED, TradeStage.EXIT_WORKING, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.ORDER_REJECT, status=VenueEventStatus.REJECTED), TradeStage.ENTRY_WORKING, TradeStage.IDLE, KernelDiagnosticCode.ENTRY_ORDER_REJECTED),
(mk_event(kind=KernelEventKind.ORDER_REJECT, status=VenueEventStatus.REJECTED), TradeStage.EXIT_WORKING, TradeStage.POSITION_OPEN, KernelDiagnosticCode.EXIT_ORDER_REJECTED),
(mk_event(kind=KernelEventKind.ORDER_REJECT, status=VenueEventStatus.REJECTED), TradeStage.IDLE, TradeStage.IDLE, KernelDiagnosticCode.ORDER_REJECTED),
(mk_event(kind=KernelEventKind.PARTIAL_FILL, status=VenueEventStatus.PARTIALLY_FILLED), TradeStage.ENTRY_WORKING, TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.FULL_FILL, status=VenueEventStatus.FILLED), TradeStage.ENTRY_WORKING, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.PARTIAL_FILL, status=VenueEventStatus.PARTIALLY_FILLED), TradeStage.EXIT_WORKING, TradeStage.EXIT_WORKING, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.FULL_FILL, status=VenueEventStatus.FILLED), TradeStage.EXIT_WORKING, TradeStage.CLOSED, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.CANCEL_ACK, status=VenueEventStatus.CANCELED), TradeStage.EXIT_WORKING, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.CANCEL_REJECT, status=VenueEventStatus.CANCELED_REJECTED), TradeStage.EXIT_WORKING, TradeStage.EXIT_WORKING, KernelDiagnosticCode.CANCEL_REJECTED),
(mk_event(kind=KernelEventKind.MARK_PRICE, status=VenueEventStatus.ACKED), TradeStage.POSITION_OPEN, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.RECONCILE, status=VenueEventStatus.ACKED), TradeStage.POSITION_OPEN, TradeStage.STALE_STATE_RECONCILING, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.ORDER_ACK, status=VenueEventStatus.ACKED, venue_order_id="V-2"), TradeStage.POSITION_OPEN, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.ORDER_ACK, status=VenueEventStatus.ACKED, venue_order_id="V-3"), TradeStage.ENTRY_WORKING, TradeStage.ENTRY_WORKING, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.FULL_FILL, status=VenueEventStatus.FILLED, venue_order_id="V-4"), TradeStage.EXIT_WORKING, TradeStage.CLOSED, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.CANCEL_ACK, status=VenueEventStatus.CANCELED, venue_order_id="V-5"), TradeStage.POSITION_OPEN, TradeStage.POSITION_OPEN, KernelDiagnosticCode.OK),
(mk_event(kind=KernelEventKind.CANCEL_REJECT, status=VenueEventStatus.CANCELED_REJECTED, venue_order_id="V-6"), TradeStage.POSITION_OPEN, TradeStage.POSITION_OPEN, KernelDiagnosticCode.CANCEL_REJECTED),
],
)
def test_kernel_event_matrix(event: VenueEvent, initial_state: TradeStage, expected_state: TradeStage, expected_code: KernelDiagnosticCode) -> None:
kernel = mk_kernel()
slot = kernel.slot(0)
_configure_slot_state(slot, initial_state)
entry_states = {TradeStage.IDLE, TradeStage.ORDER_REQUESTED, TradeStage.ORDER_SENT, TradeStage.ENTRY_WORKING}
exit_states = {TradeStage.POSITION_OPEN, TradeStage.EXIT_REQUESTED, TradeStage.EXIT_SENT, TradeStage.EXIT_WORKING}
if initial_state in entry_states and event.kind in {KernelEventKind.ORDER_ACK, KernelEventKind.PARTIAL_FILL, KernelEventKind.FULL_FILL}:
_seed_entry_order(slot, trade_id="trade-1", asset="BTCUSDT")
elif initial_state == TradeStage.ENTRY_WORKING and event.kind == KernelEventKind.ORDER_REJECT:
_seed_entry_order(slot, trade_id="trade-1", asset="BTCUSDT")
if initial_state in exit_states:
if event.kind == KernelEventKind.ORDER_REJECT:
_seed_exit_order(slot, trade_id="trade-1", asset="BTCUSDT", intended_size=1.0)
elif event.kind in {KernelEventKind.PARTIAL_FILL, KernelEventKind.FULL_FILL}:
_seed_exit_order(slot, trade_id="trade-1", asset="BTCUSDT", intended_size=1.0)
elif initial_state in {TradeStage.EXIT_REQUESTED, TradeStage.EXIT_SENT, TradeStage.EXIT_WORKING} and event.kind in {
KernelEventKind.ORDER_ACK,
KernelEventKind.CANCEL_ACK,
KernelEventKind.CANCEL_REJECT,
}:
_seed_exit_order(slot, trade_id="trade-1", asset="BTCUSDT", intended_size=1.0)
if initial_state == TradeStage.POSITION_OPEN and event.kind == KernelEventKind.ORDER_ACK:
slot.active_entry_order = None
fill_size = 1.0 if event.kind == KernelEventKind.FULL_FILL else 0.5 if event.kind == KernelEventKind.PARTIAL_FILL else 0.0
resolved_event = mk_event(
kind=event.kind,
status=event.status,
trade_id=event.trade_id,
slot_id=event.slot_id,
venue_order_id=slot.active_entry_order.venue_order_id if slot.active_entry_order else slot.active_exit_order.venue_order_id if slot.active_exit_order else event.venue_order_id,
venue_client_id=slot.active_entry_order.venue_client_id if slot.active_entry_order else slot.active_exit_order.venue_client_id if slot.active_exit_order else event.venue_client_id,
side=event.side,
asset=event.asset,
price=event.price,
size=1.0,
filled_size=fill_size,
remaining_size=max(0.0, 1.0 - fill_size),
reason=event.reason,
)
outcome = kernel.on_venue_event(resolved_event)
assert outcome.state == expected_state
assert outcome.diagnostic_code == expected_code
def test_kernel_rate_limited_event_is_characterized_without_state_drift() -> None:
kernel = mk_kernel()
slot = kernel.slot(0)
_configure_slot_state(slot, TradeStage.ENTRY_WORKING)
_seed_entry_order(slot, trade_id="trade-rate-limit", asset="BTCUSDT")
before = slot.to_dict()
outcome = kernel.on_venue_event(
mk_event(
kind=KernelEventKind.RATE_LIMITED,
status=VenueEventStatus.RATE_LIMITED,
trade_id="trade-rate-limit",
venue_order_id="V-RATE-LIMITED",
venue_client_id="trade-rate-limit:entry",
reason="code:100410 endpoint is in disabled/frequency-limited period",
size=1.0,
filled_size=0.0,
remaining_size=1.0,
)
)
after = kernel.slot(0).to_dict()
assert outcome.accepted is False
assert outcome.diagnostic_code == KernelDiagnosticCode.RATE_LIMITED
assert outcome.severity == KernelSeverity.WARNING
assert outcome.details["venue_event_kind"] == KernelEventKind.RATE_LIMITED.value
assert outcome.details["severity"] == KernelSeverity.WARNING.value
assert outcome.details["release_eta"] == "few minutes"
assert outcome.details["retryable"] is True
assert after["fsm_state"] == before["fsm_state"]
assert after["trade_id"] == before["trade_id"]
assert after["size"] == before["size"]
# 24 fuzz cases
@pytest.mark.parametrize("seed", list(range(24)))
def test_kernel_fuzz_event_sequences(seed: int) -> None:
rng = random.Random(seed)
kernel = mk_kernel(max_slots=4)
current_trade_id = f"trade-{seed}"
# Seed one slot open for exit/reconcile fuzzing.
seed_slot = kernel.slot(0)
_seed_open_slot(seed_slot, trade_id=current_trade_id)
seed_slot.exit_leg_ratios = (0.25, 0.25, 0.5)
kinds = [
KernelEventKind.ORDER_ACK,
KernelEventKind.ORDER_REJECT,
KernelEventKind.PARTIAL_FILL,
KernelEventKind.FULL_FILL,
KernelEventKind.CANCEL_ACK,
KernelEventKind.CANCEL_REJECT,
KernelEventKind.MARK_PRICE,
KernelEventKind.RECONCILE,
]
for idx in range(12):
kind = rng.choice(kinds)
if kind in {KernelEventKind.ORDER_ACK, KernelEventKind.ORDER_REJECT}:
seed_slot.active_entry_order = VenueOrder(
internal_trade_id=current_trade_id,
venue_order_id=f"V-{seed:04d}-{idx:02d}",
venue_client_id=f"{current_trade_id}:entry-{idx}",
side=TradeSide.SHORT,
intended_size=1.0,
status=VenueOrderStatus.NEW,
metadata={"slot_id": 0, "asset": "BTCUSDT"},
)
if kind in {KernelEventKind.CANCEL_ACK, KernelEventKind.CANCEL_REJECT, KernelEventKind.PARTIAL_FILL, KernelEventKind.FULL_FILL}:
seed_slot.active_exit_order = VenueOrder(
internal_trade_id=current_trade_id,
venue_order_id=f"V-{seed:04d}-{idx:02d}",
venue_client_id=f"{current_trade_id}:exit-{idx}",
side=TradeSide.SHORT,
intended_size=0.5,
filled_size=0.0,
status=VenueOrderStatus.NEW,
metadata={"slot_id": 0, "asset": "BTCUSDT"},
)
event = mk_event(kind=kind, status=_status_for_kind(kind), trade_id=current_trade_id, venue_order_id=f"V-{seed:04d}-{idx:02d}", venue_client_id=f"{current_trade_id}:{idx}")
outcome = kernel.on_venue_event(event)
assert isinstance(outcome, KernelOutcome)
assert outcome.diagnostic_code in set(KernelDiagnosticCode)
assert kernel.slot(0).fsm_state in set(TradeStage)
def _status_for_kind(kind: KernelEventKind) -> VenueEventStatus:
return {
KernelEventKind.ORDER_ACK: VenueEventStatus.ACKED,
KernelEventKind.ORDER_REJECT: VenueEventStatus.REJECTED,
KernelEventKind.PARTIAL_FILL: VenueEventStatus.PARTIALLY_FILLED,
KernelEventKind.FULL_FILL: VenueEventStatus.FILLED,
KernelEventKind.CANCEL_ACK: VenueEventStatus.CANCELED,
KernelEventKind.CANCEL_REJECT: VenueEventStatus.CANCELED_REJECTED,
KernelEventKind.MARK_PRICE: VenueEventStatus.ACKED,
KernelEventKind.RECONCILE: VenueEventStatus.ACKED,
}[kind]
# 22 explicit edge-condition tests
@pytest.mark.parametrize(
"slot_state,action,expected_code",
[
(TradeStage.IDLE, KernelCommandType.EXIT, KernelDiagnosticCode.NO_OPEN_POSITION),
(TradeStage.CLOSED, KernelCommandType.EXIT, KernelDiagnosticCode.NO_OPEN_POSITION),
(TradeStage.POSITION_OPEN, KernelCommandType.CANCEL, KernelDiagnosticCode.NO_ACTIVE_EXIT_ORDER),
(TradeStage.IDLE, KernelCommandType.CANCEL, KernelDiagnosticCode.NO_ACTIVE_EXIT_ORDER),
(TradeStage.IDLE, KernelCommandType.RECONCILE, KernelDiagnosticCode.STALE_STATE_RECONCILE),
(TradeStage.POSITION_OPEN, KernelCommandType.RECONCILE, KernelDiagnosticCode.STALE_STATE_RECONCILE),
(TradeStage.POSITION_OPEN, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.EXIT_WORKING, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.ENTRY_WORKING, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.ORDER_REQUESTED, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.ORDER_SENT, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.EXIT_REQUESTED, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.EXIT_SENT, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.STALE_STATE_RECONCILING, KernelCommandType.MARK_PRICE, KernelDiagnosticCode.OK),
(TradeStage.POSITION_OPEN, KernelCommandType.ENTER, KernelDiagnosticCode.SLOT_BUSY),
(TradeStage.EXIT_WORKING, KernelCommandType.ENTER, KernelDiagnosticCode.SLOT_BUSY),
(TradeStage.ORDER_REQUESTED, KernelCommandType.ENTER, KernelDiagnosticCode.SLOT_BUSY),
(TradeStage.ORDER_SENT, KernelCommandType.ENTER, KernelDiagnosticCode.SLOT_BUSY),
(TradeStage.POSITION_OPEN, KernelCommandType.EXIT, KernelDiagnosticCode.OK),
(TradeStage.EXIT_WORKING, KernelCommandType.EXIT, KernelDiagnosticCode.OK),
(TradeStage.POSITION_OPEN, KernelCommandType.CANCEL, KernelDiagnosticCode.OK),
(TradeStage.EXIT_WORKING, KernelCommandType.CANCEL, KernelDiagnosticCode.OK),
],
)
def test_kernel_action_edge_conditions(slot_state: TradeStage, action: KernelCommandType, expected_code: KernelDiagnosticCode) -> None:
kernel = mk_kernel(venue=MockVenueAdapter(MockVenueScenario(emit_fill_on_submit=True, partial_fill_ratio=1.0)))
slot = kernel.slot(0)
_configure_slot_state(slot, slot_state)
if action == KernelCommandType.ENTER and expected_code == KernelDiagnosticCode.SLOT_BUSY:
slot.trade_id = f"occupied-{slot_state.value.lower()}"
if action == KernelCommandType.CANCEL and expected_code == KernelDiagnosticCode.OK:
_seed_exit_order(slot, trade_id=slot.trade_id or "trade-1", asset=slot.asset or "BTCUSDT", intended_size=0.5)
outcome = kernel.process_intent(mk_intent(action=action, target_size=0.5, exit_leg_ratios=(0.25, 0.25, 0.5)))
assert outcome.diagnostic_code == expected_code
# 20 transition-detail tests
@pytest.mark.parametrize("mode", [KernelMode.NORMAL, KernelMode.DEBUG])
@pytest.mark.parametrize("verbosity", [KernelVerbosity.QUIET, KernelVerbosity.TRACE])
@pytest.mark.parametrize("control_enabled", [True, False])
@pytest.mark.parametrize("closed", [True, False])
@pytest.mark.parametrize("state", [TradeStage.IDLE, TradeStage.POSITION_OPEN])
def test_transition_details_and_control_modes_are_captured(
mode: KernelMode,
verbosity: KernelVerbosity,
control_enabled: bool,
closed: bool,
state: TradeStage,
) -> None:
kernel = mk_kernel()
if control_enabled:
kernel.update_control(
ControlUpdate(
mode=mode,
verbosity=verbosity,
trace_transitions=True,
)
)
slot = kernel.slot(0)
_seed_open_slot(slot)
slot.fsm_state = state
slot.closed = closed
event = mk_event(kind=KernelEventKind.MARK_PRICE, status=VenueEventStatus.ACKED)
outcome = kernel.on_venue_event(event)
assert outcome.transitions
transition = outcome.transitions[0]
assert transition.control_mode in {KernelMode.NORMAL.value, KernelMode.DEBUG.value}
assert transition.control_verbosity in {KernelVerbosity.QUIET.value, KernelVerbosity.TRACE.value}
assert "asset" in transition.details
assert "side" in transition.details