feat: Implement idempotency and recovery mechanisms for order execution
- Add IdempotencyKeyFactory for generating unique user references based on execution legs. - Introduce OrderReconciler to reconcile order statuses with historical data. - Implement PartialFillRecovery to handle partial fills by canceling orders and placing hedges. - Create TriangularExecutionSequencer for executing triangular arbitrage strategies. - Enhance storage with new tables for trades, orders, and PnL events. - Develop AsyncExecutionWriter for asynchronous writing of execution records to the database. - Add unit tests for execution persistence, sequencer behavior, fill monitoring, and idempotency checks. - Update KrakenRestClient to ensure proper payloads for order placement and querying.
This commit is contained in:
@@ -28,6 +28,44 @@ class OpportunityRecord:
|
||||
executed: bool = False
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class TradeRecord:
|
||||
trade_ref: str
|
||||
started_at: datetime
|
||||
finished_at: datetime | None
|
||||
status: str
|
||||
realized_pnl: float | None
|
||||
estimated_pnl: float | None
|
||||
capital_used: float | None
|
||||
cycle: str | None = None
|
||||
leg_count: int | None = None
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class OrderRecord:
|
||||
trade_ref: str
|
||||
order_ref: str
|
||||
leg_index: int
|
||||
pair: str
|
||||
side: str
|
||||
volume: float
|
||||
user_ref: int | None
|
||||
status: str | None
|
||||
filled_volume: float | None
|
||||
avg_price: float | None
|
||||
raw_response: dict[str, Any]
|
||||
recorded_at: datetime
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class PnLRecord:
|
||||
trade_ref: str
|
||||
recorded_at: datetime
|
||||
kind: str
|
||||
pnl_usd: float
|
||||
source: str
|
||||
|
||||
|
||||
class MarketSnapshotRepository:
|
||||
def __init__(self, store: DuckDBStore) -> None:
|
||||
self._store = store
|
||||
@@ -76,3 +114,106 @@ class OpportunityRepository:
|
||||
record.executed,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class TradeRepository:
|
||||
def __init__(self, store: DuckDBStore) -> None:
|
||||
self._store = store
|
||||
|
||||
def insert(self, record: TradeRecord) -> None:
|
||||
with self._store.connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO trades (
|
||||
trade_ref,
|
||||
started_at,
|
||||
finished_at,
|
||||
status,
|
||||
realized_pnl,
|
||||
estimated_pnl,
|
||||
capital_used,
|
||||
cycle,
|
||||
leg_count
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
[
|
||||
record.trade_ref,
|
||||
record.started_at,
|
||||
record.finished_at,
|
||||
record.status,
|
||||
record.realized_pnl,
|
||||
record.estimated_pnl,
|
||||
record.capital_used,
|
||||
record.cycle,
|
||||
record.leg_count,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class OrderRepository:
|
||||
def __init__(self, store: DuckDBStore) -> None:
|
||||
self._store = store
|
||||
|
||||
def insert(self, record: OrderRecord) -> None:
|
||||
with self._store.connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO orders (
|
||||
trade_ref,
|
||||
order_ref,
|
||||
leg_index,
|
||||
pair,
|
||||
side,
|
||||
volume,
|
||||
user_ref,
|
||||
status,
|
||||
filled_volume,
|
||||
avg_price,
|
||||
raw_response,
|
||||
recorded_at
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
[
|
||||
record.trade_ref,
|
||||
record.order_ref,
|
||||
record.leg_index,
|
||||
record.pair,
|
||||
record.side,
|
||||
record.volume,
|
||||
record.user_ref,
|
||||
record.status,
|
||||
record.filled_volume,
|
||||
record.avg_price,
|
||||
orjson.dumps(record.raw_response).decode("utf-8"),
|
||||
record.recorded_at,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class PnLRepository:
|
||||
def __init__(self, store: DuckDBStore) -> None:
|
||||
self._store = store
|
||||
|
||||
def insert(self, record: PnLRecord) -> None:
|
||||
with self._store.connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO pnl_events (
|
||||
trade_ref,
|
||||
recorded_at,
|
||||
kind,
|
||||
pnl_usd,
|
||||
source
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""",
|
||||
[
|
||||
record.trade_ref,
|
||||
record.recorded_at,
|
||||
record.kind,
|
||||
record.pnl_usd,
|
||||
record.source,
|
||||
],
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user