The aborted hard cutover crash-looped with "Rust kernel returned null string" from process_intent on the first live trading step. Root cause (reproduced): a non-finite (inf/NaN) numeric field reaching the kernel — Python json.dumps emits the Infinity/NaN token, serde_json rejects it at parse, and the FFI returned null. Magnitude is fine; only finiteness was the problem. Defense in depth, kernel catches it: - Rust FFI (lib.rs): dita_kernel_process_intent_json / _on_venue_event_json now return a clean INVALID_INTENT KernelResult on parse failure (incl. Infinity/NaN tokens) AND on serialize failure (a non-finite produced internally) — never a null string. - Python bridge (rust_backend.py): ExecutionKernel.process_intent validates intent finiteness/bounds (target_size, reference_price, limit_price, leverage, exit_leg_ratios; size>=0) BEFORE the FFI and rejects INVALID_INTENT, naming the offending field+value. - contracts.py: add KernelDiagnosticCode.INVALID_INTENT. - pink_direct.py: on INVALID_INTENT, log full upstream provenance (snapshot.price, capital, leverage, sizes) so the numerical SOURCE can be located on the next live run. - on_venue_event bridge tolerates the fallback's null slot (uses the live slot). Verified: kernel recompiled; offline 65 + 7 new guard tests green (no regression); direct-FFI inf payload -> INVALID_INTENT (no null crash). NOTE: this turns the cutover crash into a clean rejection — the upstream source of the non-finite (the live run's inf) still needs locating, now aided by the provenance log. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
331 lines
10 KiB
Python
331 lines
10 KiB
Python
"""Canonical v2 contracts for the DITAv2 execution kernel."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import Any, Dict, Mapping, Optional, Sequence, Tuple
|
|
|
|
|
|
class TradeSide(str, Enum):
|
|
"""Trade side."""
|
|
|
|
LONG = "LONG"
|
|
SHORT = "SHORT"
|
|
FLAT = "FLAT"
|
|
|
|
|
|
class TradeStage(str, Enum):
|
|
"""Execution stage for a trade slot."""
|
|
|
|
IDLE = "IDLE"
|
|
DECISION_CREATED = "DECISION_CREATED"
|
|
INTENT_CREATED = "INTENT_CREATED"
|
|
ORDER_REQUESTED = "ORDER_REQUESTED"
|
|
ORDER_SENT = "ORDER_SENT"
|
|
ORDER_ACKED = "ORDER_ACKED"
|
|
ORDER_REJECTED = "ORDER_REJECTED"
|
|
ENTRY_WORKING = "ENTRY_WORKING"
|
|
PARTIAL_FILL = "PARTIAL_FILL"
|
|
POSITION_OPENED = "POSITION_OPENED"
|
|
POSITION_OPEN = "POSITION_OPEN"
|
|
EXIT_REQUESTED = "EXIT_REQUESTED"
|
|
EXIT_SENT = "EXIT_SENT"
|
|
EXIT_ACKED = "EXIT_ACKED"
|
|
EXIT_REJECTED = "EXIT_REJECTED"
|
|
EXIT_WORKING = "EXIT_WORKING"
|
|
POSITION_PARTIALLY_CLOSED = "POSITION_PARTIALLY_CLOSED"
|
|
POSITION_CLOSED = "POSITION_CLOSED"
|
|
CLOSED = "CLOSED"
|
|
TRADE_TERMINAL_WRITTEN = "TRADE_TERMINAL_WRITTEN"
|
|
STALE_STATE_RECONCILING = "STALE_STATE_RECONCILING"
|
|
|
|
|
|
class KernelCommandType(str, Enum):
|
|
"""Kernel command types."""
|
|
|
|
ENTER = "ENTER"
|
|
EXIT = "EXIT"
|
|
MARK_PRICE = "MARK_PRICE"
|
|
RECONCILE = "RECONCILE"
|
|
CONTROL = "CONTROL"
|
|
CANCEL = "CANCEL"
|
|
|
|
|
|
class KernelEventKind(str, Enum):
|
|
"""Normalized venue event kinds."""
|
|
|
|
ORDER_ACK = "ORDER_ACK"
|
|
ORDER_REJECT = "ORDER_REJECT"
|
|
RATE_LIMITED = "RATE_LIMITED"
|
|
PARTIAL_FILL = "PARTIAL_FILL"
|
|
FULL_FILL = "FULL_FILL"
|
|
CANCEL_ACK = "CANCEL_ACK"
|
|
CANCEL_REJECT = "CANCEL_REJECT"
|
|
MARK_PRICE = "MARK_PRICE"
|
|
RECONCILE = "RECONCILE"
|
|
CONTROL = "CONTROL"
|
|
|
|
|
|
class KernelDiagnosticCode(str, Enum):
|
|
"""Structured diagnostic codes emitted by the kernel."""
|
|
|
|
OK = "OK"
|
|
RATE_LIMITED = "RATE_LIMITED"
|
|
INVALID_SLOT_ID = "INVALID_SLOT_ID"
|
|
INVALID_INTENT = "INVALID_INTENT"
|
|
UNSUPPORTED_INTENT = "UNSUPPORTED_INTENT"
|
|
SLOT_BUSY = "SLOT_BUSY"
|
|
NO_OPEN_POSITION = "NO_OPEN_POSITION"
|
|
NO_ACTIVE_EXIT_ORDER = "NO_ACTIVE_EXIT_ORDER"
|
|
UNKNOWN_EVENT_KIND = "UNKNOWN_EVENT_KIND"
|
|
ORDER_REJECTED = "ORDER_REJECTED"
|
|
ENTRY_ORDER_REJECTED = "ENTRY_ORDER_REJECTED"
|
|
EXIT_ORDER_REJECTED = "EXIT_ORDER_REJECTED"
|
|
CANCEL_REJECTED = "CANCEL_REJECTED"
|
|
STALE_STATE_RECONCILE = "STALE_STATE_RECONCILE"
|
|
RECONCILED = "RECONCILED"
|
|
DUPLICATE_EVENT = "DUPLICATE_EVENT"
|
|
UNRESOLVED_SLOT = "UNRESOLVED_SLOT"
|
|
INVALID_TRANSITION = "INVALID_TRANSITION"
|
|
TERMINAL_STATE = "TERMINAL_STATE"
|
|
|
|
|
|
class KernelSeverity(str, Enum):
|
|
"""Severity classification for kernel outcomes."""
|
|
|
|
INFO = "INFO"
|
|
WARNING = "WARNING"
|
|
ERROR = "ERROR"
|
|
CRITICAL = "CRITICAL"
|
|
|
|
|
|
class VenueOrderStatus(str, Enum):
|
|
"""Order status surface mirrored from venue truth."""
|
|
|
|
NEW = "NEW"
|
|
ACKED = "ACKED"
|
|
PARTIALLY_FILLED = "PARTIALLY_FILLED"
|
|
FILLED = "FILLED"
|
|
CANCELED = "CANCELED"
|
|
REJECTED = "REJECTED"
|
|
|
|
|
|
class VenueEventStatus(str, Enum):
|
|
"""Status alias for normalized venue events."""
|
|
|
|
ACKED = "ACKED"
|
|
REJECTED = "REJECTED"
|
|
RATE_LIMITED = "RATE_LIMITED"
|
|
PARTIALLY_FILLED = "PARTIALLY_FILLED"
|
|
FILLED = "FILLED"
|
|
CANCELED = "CANCELED"
|
|
CANCELED_REJECTED = "CANCEL_REJECTED"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class VenueOrder:
|
|
"""Venue-specific order identity and fill state."""
|
|
|
|
internal_trade_id: str
|
|
venue_order_id: str
|
|
venue_client_id: str
|
|
side: TradeSide
|
|
intended_size: float
|
|
filled_size: float = 0.0
|
|
average_fill_price: float = 0.0
|
|
status: VenueOrderStatus = VenueOrderStatus.NEW
|
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
@property
|
|
def remaining_size(self) -> float:
|
|
return max(0.0, float(self.intended_size) - float(self.filled_size))
|
|
|
|
|
|
@dataclass
|
|
class TradeSlot:
|
|
"""A single execution slot managed by the v2 kernel."""
|
|
|
|
slot_id: int
|
|
trade_id: str = ""
|
|
asset: str = ""
|
|
side: TradeSide = TradeSide.FLAT
|
|
entry_price: float = 0.0
|
|
size: float = 0.0
|
|
initial_size: float = 0.0
|
|
leverage: float = 0.0
|
|
entry_time: Optional[datetime] = None
|
|
unrealized_pnl: float = 0.0
|
|
realized_pnl: float = 0.0
|
|
closed: bool = False
|
|
exit_leg_ratios: Tuple[float, ...] = (1.0,)
|
|
active_leg_index: int = 0
|
|
active_exit_order: Optional[VenueOrder] = None
|
|
active_entry_order: Optional[VenueOrder] = None
|
|
fsm_state: TradeStage = TradeStage.IDLE
|
|
close_reason: str = ""
|
|
last_event_time: Optional[datetime] = None
|
|
seen_event_ids: Tuple[str, ...] = ()
|
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
def is_free(self) -> bool:
|
|
return self.fsm_state in {TradeStage.IDLE, TradeStage.CLOSED} and float(self.size or 0.0) <= 0.0 and not self.active_entry_order and not self.active_exit_order
|
|
|
|
def is_open(self) -> bool:
|
|
return self.fsm_state in {
|
|
TradeStage.ENTRY_WORKING,
|
|
TradeStage.POSITION_OPENED,
|
|
TradeStage.POSITION_OPEN,
|
|
TradeStage.EXIT_WORKING,
|
|
} and not self.closed
|
|
|
|
def mark_price(self, price: float) -> None:
|
|
if price is None or price != price or price <= 0:
|
|
return
|
|
self.entry_price = self.entry_price or price
|
|
if self.entry_price <= 0 or self.size <= 0:
|
|
self.unrealized_pnl = 0.0
|
|
return
|
|
delta = (price - self.entry_price) / self.entry_price
|
|
if self.side == TradeSide.SHORT:
|
|
delta = -delta
|
|
self.unrealized_pnl = delta * self.size * self.entry_price * self.leverage
|
|
|
|
def next_exit_ratio(self) -> float:
|
|
if self.active_leg_index < len(self.exit_leg_ratios):
|
|
ratio = float(self.exit_leg_ratios[self.active_leg_index])
|
|
return max(0.0, min(1.0, ratio))
|
|
return 1.0
|
|
|
|
def consume_exit_leg(self) -> float:
|
|
ratio = self.next_exit_ratio()
|
|
self.active_leg_index = min(self.active_leg_index + 1, max(len(self.exit_leg_ratios), 1))
|
|
return ratio
|
|
|
|
def remaining_size(self) -> float:
|
|
return max(0.0, float(self.size))
|
|
|
|
def attach_entry_order(self, order: VenueOrder) -> None:
|
|
self.active_entry_order = order
|
|
|
|
def attach_exit_order(self, order: VenueOrder) -> None:
|
|
self.active_exit_order = order
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
def _order_dict(order: Optional[VenueOrder]) -> Optional[Dict[str, Any]]:
|
|
if order is None:
|
|
return None
|
|
return {
|
|
"internal_trade_id": order.internal_trade_id,
|
|
"venue_order_id": order.venue_order_id,
|
|
"venue_client_id": order.venue_client_id,
|
|
"side": order.side.value,
|
|
"intended_size": float(order.intended_size or 0.0),
|
|
"filled_size": float(order.filled_size or 0.0),
|
|
"average_fill_price": float(order.average_fill_price or 0.0),
|
|
"status": order.status.value,
|
|
"metadata": dict(order.metadata),
|
|
}
|
|
|
|
return {
|
|
"slot_id": self.slot_id,
|
|
"trade_id": self.trade_id,
|
|
"asset": self.asset,
|
|
"side": self.side.value,
|
|
"entry_price": float(self.entry_price or 0.0),
|
|
"size": float(self.size or 0.0),
|
|
"initial_size": float(self.initial_size or 0.0),
|
|
"leverage": float(self.leverage or 0.0),
|
|
"entry_time": self.entry_time.isoformat() if hasattr(self.entry_time, "isoformat") else None,
|
|
"unrealized_pnl": float(self.unrealized_pnl or 0.0),
|
|
"realized_pnl": float(self.realized_pnl or 0.0),
|
|
"closed": bool(self.closed),
|
|
"exit_leg_ratios": [float(r) for r in self.exit_leg_ratios],
|
|
"active_leg_index": int(self.active_leg_index or 0),
|
|
"active_exit_order": _order_dict(self.active_exit_order),
|
|
"active_entry_order": _order_dict(self.active_entry_order),
|
|
"fsm_state": self.fsm_state.value,
|
|
"close_reason": self.close_reason,
|
|
"last_event_time": self.last_event_time.isoformat() if hasattr(self.last_event_time, "isoformat") else None,
|
|
"seen_event_ids": list(self.seen_event_ids),
|
|
"metadata": dict(self.metadata),
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class KernelIntent:
|
|
"""Command emitted by the algo and written to the hot-path intent region."""
|
|
|
|
timestamp: datetime
|
|
intent_id: str
|
|
trade_id: str
|
|
slot_id: int
|
|
asset: str
|
|
side: TradeSide
|
|
action: KernelCommandType
|
|
reference_price: float
|
|
target_size: float
|
|
leverage: float
|
|
exit_leg_ratios: Tuple[float, ...] = (1.0,)
|
|
reason: str = ""
|
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
stage: TradeStage = TradeStage.INTENT_CREATED
|
|
order_type: str = "MARKET"
|
|
limit_price: float = 0.0
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class VenueEvent:
|
|
"""Normalized venue truth mapped into DITAv2 semantics."""
|
|
|
|
timestamp: datetime
|
|
event_id: str
|
|
trade_id: str
|
|
slot_id: int
|
|
kind: KernelEventKind
|
|
status: VenueEventStatus
|
|
venue_order_id: str = ""
|
|
venue_client_id: str = ""
|
|
side: TradeSide = TradeSide.FLAT
|
|
asset: str = ""
|
|
price: float = 0.0
|
|
size: float = 0.0
|
|
filled_size: float = 0.0
|
|
remaining_size: float = 0.0
|
|
reason: str = ""
|
|
raw_payload: Dict[str, Any] = field(default_factory=dict)
|
|
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class KernelTransition:
|
|
"""Durable kernel transition used for debug journaling."""
|
|
|
|
timestamp: datetime
|
|
trade_id: str
|
|
slot_id: int
|
|
prev_state: TradeStage
|
|
next_state: TradeStage
|
|
trigger: str
|
|
intent_id: str = ""
|
|
event_id: str = ""
|
|
control_mode: str = ""
|
|
control_verbosity: str = ""
|
|
details: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class KernelOutcome:
|
|
"""Result of applying a command or venue event."""
|
|
|
|
accepted: bool
|
|
slot_id: int
|
|
trade_id: str
|
|
state: TradeStage
|
|
diagnostic_code: KernelDiagnosticCode = KernelDiagnosticCode.OK
|
|
severity: KernelSeverity = KernelSeverity.INFO
|
|
transitions: Tuple[KernelTransition, ...] = ()
|
|
emitted_events: Tuple[VenueEvent, ...] = ()
|
|
details: Dict[str, Any] = field(default_factory=dict)
|