feat: add bounded KIS account read recovery
This commit is contained in:
@@ -30,6 +30,7 @@ from typing import Callable, Optional
|
||||
|
||||
from trex_core.application.alarm_emitter import AlarmEmitter
|
||||
from trex_core.application.broker_port import (
|
||||
BalanceItem,
|
||||
BrokerPort,
|
||||
CancelOutcome,
|
||||
CancelState,
|
||||
@@ -84,6 +85,7 @@ class ExecutionService:
|
||||
stale_pending_threshold_sec: Optional[int] = None,
|
||||
instance_key: str = "default",
|
||||
alarm_emitter: Optional[AlarmEmitter] = None,
|
||||
balance_reader: Optional[Callable[[], list[BalanceItem]]] = None,
|
||||
) -> None:
|
||||
self._svc = slot_service
|
||||
self._repo = repo
|
||||
@@ -104,6 +106,10 @@ class ExecutionService:
|
||||
)
|
||||
# dcy-033 / REQ-100: best-effort alarm emitter (None = no alarms sent).
|
||||
self._alarm_emitter = alarm_emitter
|
||||
# dcy-041 / GitHub #45: pending-sell quantity may use a bounded
|
||||
# account snapshot only through this injected reader. Reconciliation
|
||||
# remains wired directly to the live broker.
|
||||
self._sell_dispatch_balance_reader = balance_reader or broker.get_balance
|
||||
|
||||
# ------------------------------------------------------------
|
||||
def run_once(self) -> ExecutionResult:
|
||||
@@ -136,7 +142,7 @@ class ExecutionService:
|
||||
# surfaces via reconcile_core_holdings (REQ-062 A). No mirror
|
||||
# fallback by design.
|
||||
if sell_balance is None:
|
||||
sell_balance = self._balance_map()
|
||||
sell_balance = self._sell_dispatch_balance_map()
|
||||
bal = sell_balance.get(slot.symbol or "", 0)
|
||||
# dcy-021 / REQ-062 (D4): full sell (slot.qty is None) => broker
|
||||
# balance; partial sell => min(order qty, broker balance). Broker
|
||||
@@ -313,6 +319,13 @@ class ExecutionService:
|
||||
"""Current broker balance as {symbol: hldg_qty} (REQ-062 ground truth)."""
|
||||
return {b.symbol: int(b.hldg_qty) for b in self._broker.get_balance()}
|
||||
|
||||
def _sell_dispatch_balance_map(self) -> dict:
|
||||
"""Balance used only to size a not-yet-submitted pending sell."""
|
||||
return {
|
||||
b.symbol: int(b.hldg_qty)
|
||||
for b in self._sell_dispatch_balance_reader()
|
||||
}
|
||||
|
||||
def _resolve_fill_price(self, fs, slot) -> tuple[float | None, bool]:
|
||||
"""Resolve the fill price from FillStatus, with limit_price backfill.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user