PINK Phase 2 (G3): ExchangeEvent seam + BingxUserStream + mode-parity
exchange_event.py: abstract ExchangeEvent/ExchangeEventKind seam venue.py: VenueAdapter extended with subscribe()/account_snapshot() bingx_user_stream.py: PINK-only WS client with listenKey lifecycle, gzip, ping/pong, 24h rotation sentinel, reconnect backoff, gap-backfill mock_venue.py: subscribe()/account_snapshot() for offline tests Gate G3 mode-parity: WS and poll paths produce identical k_capital, fees, realized PnL, reconcile status for same logical event sequence. 89/89 total offline tests pass.
This commit is contained in:
60
prod/clean_arch/dita_v2/venue.py
Normal file
60
prod/clean_arch/dita_v2/venue.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""Venue adapter contracts for DITAv2."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Any, AsyncIterator, Dict, List, Optional, Protocol
|
||||
|
||||
from .contracts import (
|
||||
KernelCommandType,
|
||||
KernelIntent,
|
||||
KernelEventKind,
|
||||
TradeSide,
|
||||
VenueEvent,
|
||||
VenueEventStatus,
|
||||
VenueOrder,
|
||||
VenueOrderStatus,
|
||||
)
|
||||
from .exchange_event import ExchangeEvent
|
||||
|
||||
|
||||
class VenueAdapter(Protocol):
|
||||
"""Abstract venue adapter used by the kernel."""
|
||||
|
||||
def submit(self, intent: KernelIntent) -> List[VenueEvent]:
|
||||
...
|
||||
|
||||
def cancel(self, order: VenueOrder, *, reason: str = "") -> List[VenueEvent]:
|
||||
...
|
||||
|
||||
def open_orders(self) -> List[VenueOrder]:
|
||||
...
|
||||
|
||||
def open_positions(self) -> List[Dict[str, Any]]:
|
||||
...
|
||||
|
||||
def reconcile(self) -> List[VenueEvent]:
|
||||
...
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Phase 2 — stream seam (spec G3)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
async def subscribe(self) -> AsyncIterator[ExchangeEvent]:
|
||||
"""
|
||||
Yield ExchangeEvent instances in arrival order. Implementations
|
||||
must handle reconnection, keepalive, and 24h rotation internally.
|
||||
The iterator never terminates normally — callers cancel it on
|
||||
shutdown. Both the WS and poll-failover paths implement this
|
||||
interface so the kernel layer is source-agnostic.
|
||||
"""
|
||||
... # pragma: no cover
|
||||
|
||||
async def account_snapshot(self) -> ExchangeEvent:
|
||||
"""
|
||||
Return a single ACCOUNT_UPDATE + POSITION_UPDATE merged event
|
||||
by calling the exchange REST API. Used for gap-backfill on
|
||||
reconnect and as the poll-failover path.
|
||||
"""
|
||||
... # pragma: no cover
|
||||
Reference in New Issue
Block a user