"""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)