67 production .py modules that the running PINK service imports but which were never committed: prod/bingx/ (HTTP client, market/user streams, journal, config), prod/clean_arch/ adapters/persistence/runtime/dita/dita_v2 production modules and their co-located tests. Rule going forward: every module imported by launch_dolphin_pink.py / pink_direct.py must appear in git ls-files. Excludes _backup dirs, __pycache__, and non-code files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
75 lines
2.2 KiB
Python
75 lines
2.2 KiB
Python
"""Execution port for DITA-driven live trading.
|
|
|
|
This port is intentionally free of Nautilus Trader node concepts.
|
|
It provides a direct exchange boundary for PINK/BLUE-compatible DITA runtimes.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime
|
|
from typing import Any, Dict, Optional
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ExchangeStateSnapshot:
|
|
"""Exchange-led account/position/order snapshot."""
|
|
|
|
timestamp: datetime
|
|
capital: float
|
|
equity: float
|
|
open_positions: Dict[str, Dict[str, Any]] = field(default_factory=dict)
|
|
open_orders: list[Dict[str, Any]] = field(default_factory=list)
|
|
all_orders: list[Dict[str, Any]] = field(default_factory=list)
|
|
all_fills: list[Dict[str, Any]] = field(default_factory=list)
|
|
account: Dict[str, Any] = field(default_factory=dict)
|
|
open_notional: float = 0.0
|
|
source: str = "exchange"
|
|
recovered: bool = False
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ExecutionReceipt:
|
|
"""Canonical receipt returned by a direct execution adapter."""
|
|
|
|
timestamp: datetime
|
|
status: str
|
|
symbol: str
|
|
side: str
|
|
action: str
|
|
quantity: float
|
|
price: float
|
|
client_order_id: str
|
|
order_id: str = ""
|
|
realized_pnl: float = 0.0
|
|
fees: float = 0.0
|
|
raw_ack: Dict[str, Any] = field(default_factory=dict)
|
|
raw_state: Dict[str, Any] = field(default_factory=dict)
|
|
|
|
|
|
class ExecutionPort(ABC):
|
|
"""Direct exchange execution boundary."""
|
|
|
|
@abstractmethod
|
|
async def connect(self) -> bool:
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def disconnect(self) -> None:
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def refresh_state(self, symbol: str | None = None, *, include_history: bool = False) -> ExchangeStateSnapshot:
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def submit_intent(self, intent: Any) -> ExecutionReceipt:
|
|
raise NotImplementedError
|
|
|
|
@abstractmethod
|
|
async def reconcile(self, symbol: str | None = None) -> ExchangeStateSnapshot:
|
|
"""Recovery-only path for catastrophic restart/hibernate scenarios."""
|
|
raise NotImplementedError
|
|
|