Files
sentiment-engine/prod/exec_unified/working.py
Codex ec95bd6663 exec(unified): sync local build — kernel_port + dialect §11 + friction §12 + size threading
Lands the /root/dev local increments (share was ENOSPC; now writable) into the canonical repo:
- kernel_port.py: real ExecPort over the DITAv2 kernel (duck-typed; injected to_kernel_intent).
- dialect.py §11: BingX boundary — clientOrderId(H4)/dash/quantize/payload (PostOnly=timeInForce).
- friction.py §12: effective-bps + naive-baseline savings; side-lane journal that can't raise
  (b46ebd2); BingX commission-sign flip. DDL ships with code (register in applier verify-set).
- drive_loop/executor/working: Decimal size threaded through plan/working types (exit size cap).
All pure stdlib+Decimal, mutation-litmus RED on the two load-bearing asserts. 132 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 08:05:26 +02:00

88 lines
3.4 KiB
Python

"""Working-order registry — the state the drive loop sweeps (spec §7).
A ``WorkingOrder`` is a maker quote that did not terminally fill on submit: it is either
resting on the book or was rejected (post-only that would have crossed). Both live here;
the drive loop resolves them on a TTL sweep.
The registry reads time through an INJECTED clock (no ambient ``time.monotonic`` — C1
venue-side portability, and deterministic tests). All sizes/prices are ``Decimal`` — the
best-practice audit's H1: PINK used float, the port does not.
Provenance: pink_direct.py working-order lifecycle (register/expired/note_fill/note_cancel,
L975-1046) + exec_router.py WorkingOrder registry. Audit BI-1 (attempt counter).
"""
from __future__ import annotations
from dataclasses import dataclass, field
from decimal import Decimal
from enum import Enum
from typing import Callable
from .contract import Side
class Action(Enum):
ENTER = "ENTER" # opens/increases a position (ACQUIRE urgency)
EXIT = "EXIT" # decreases/closes (PROTECT/HARVEST/ROTATE/CATASTROPHIC)
@dataclass
class WorkingOrder:
"""A maker quote in flight. Mutable: ``deadline`` and ``attempt`` evolve as the drive
loop reprices/retries; identity is ``request_id``."""
request_id: str # this attempt's id (unique per attempt — audit H4)
base_request_id: str # parent request (survives retries; FIX OrigClOrdID)
asset: str
side: Side
action: Action
limit_price: Decimal
deadline: float # in injected-clock units; <= now() means "resolve me"
created: float
size: Decimal = Decimal("0") # base qty the caller asked for (venue needs it; exits cap to slot)
attempt: int = 0
meta: dict = field(default_factory=dict)
class WorkingRegistry:
"""In-memory registry of working quotes, swept by the drive loop.
NOT persisted here — durable/atomic persistence is a venue-seam concern (audit BI-5:
never /tmp; durable path + tmp-rename). This object is the hot, in-process view.
"""
def __init__(self, clock: Callable[[], float]) -> None:
self._clock = clock
self._orders: dict[str, WorkingOrder] = {}
def register(self, wo: WorkingOrder) -> WorkingOrder:
self._orders[wo.request_id] = wo
return wo
def working(self, request_id: str) -> WorkingOrder | None:
"""The working order for this id, or None if already resolved (fill/cancel raced)."""
return self._orders.get(request_id)
def expired(self) -> list[WorkingOrder]:
"""Every working order whose deadline has passed (snapshot — safe to mutate during)."""
now = self._clock()
return [wo for wo in list(self._orders.values()) if now >= wo.deadline]
def expire_now(self, request_id: str) -> None:
"""Pull a quote's deadline to now so the next sweep resolves it through the ONE
shared miss/escalation path (rejected post-only, or a venue CANCEL_ACK surfacing
via reconcile). pink_direct.py:1010-1011, 1290-1292 — do NOT build a second path.
"""
wo = self._orders.get(request_id)
if wo is not None:
wo.deadline = self._clock()
def note_fill(self, request_id: str) -> None:
self._orders.pop(request_id, None)
def note_cancel(self, request_id: str) -> None:
self._orders.pop(request_id, None)
def __len__(self) -> int:
return len(self._orders)