feat: use broker-authoritative qty in slots RPC holdings
Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
co-authored by
genichin
parent
832dcb5fbb
commit
30bcbe1d12
@@ -9,10 +9,12 @@ from __future__ import annotations
|
||||
import logging
|
||||
from datetime import date as date_cls
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
from typing import Optional, Protocol
|
||||
from uuid import UUID
|
||||
|
||||
from trex_core.application.intents import BuyIntent, IntentService, SellIntent
|
||||
from trex_core.application.account_snapshot import AccountSnapshotUnavailable
|
||||
from trex_core.application.broker_port import BalanceItem
|
||||
from trex_core.application.messaging import RpcRequest, RpcResponse
|
||||
from trex_core.application.portfolio import (
|
||||
PauseStore,
|
||||
@@ -185,6 +187,10 @@ _FILTER_STATUS: dict[str, set[str]] = {
|
||||
}
|
||||
|
||||
|
||||
class SlotsBrokerQuantityReader(Protocol):
|
||||
def holdings_for_slots_rpc(self) -> tuple[list[BalanceItem], datetime]: ...
|
||||
|
||||
|
||||
def make_slots_rpc_handler(
|
||||
slot_repo: SlotRepository,
|
||||
*,
|
||||
@@ -197,6 +203,7 @@ def make_slots_rpc_handler(
|
||||
ledger_outbox=None,
|
||||
max_active_slots: Optional[int] = None,
|
||||
strategy_state_store=None,
|
||||
broker_quantity_reader: Optional[SlotsBrokerQuantityReader] = None,
|
||||
):
|
||||
"""Build the RPC handler for `trex.slots.req` (REQ-073/074/116).
|
||||
|
||||
@@ -252,6 +259,36 @@ def make_slots_rpc_handler(
|
||||
for s in slots
|
||||
]
|
||||
|
||||
broker_qty_by_symbol: dict[str, int] = {}
|
||||
broker_qty_available = False
|
||||
broker_qty_captured_at: Optional[datetime] = None
|
||||
if broker_quantity_reader is not None:
|
||||
try:
|
||||
holdings, broker_qty_captured_at = broker_quantity_reader.holdings_for_slots_rpc()
|
||||
broker_qty_by_symbol = {
|
||||
str(item.symbol): int(item.hldg_qty)
|
||||
for item in holdings
|
||||
}
|
||||
broker_qty_available = True
|
||||
except AccountSnapshotUnavailable:
|
||||
broker_qty_available = False
|
||||
|
||||
for row, slot in zip(slot_rows, slots):
|
||||
row["slot_quantity"] = row.get("qty")
|
||||
if slot.status.value != "holding":
|
||||
continue
|
||||
row["broker_quantity_available"] = broker_qty_available
|
||||
row["broker_quantity_captured_at"] = (
|
||||
broker_qty_captured_at.isoformat() if broker_qty_captured_at is not None else None
|
||||
)
|
||||
if broker_qty_available:
|
||||
broker_qty = int(broker_qty_by_symbol.get(str(slot.symbol), 0))
|
||||
row["qty"] = float(broker_qty)
|
||||
row["qty_source"] = "broker"
|
||||
else:
|
||||
row["qty"] = None
|
||||
row["qty_source"] = "unavailable"
|
||||
|
||||
# dcy-028 / REQ-073/074·079 (C-1): attach opaque strategy_state map per
|
||||
# row via one batched store read (read piggyback — no extra round trip).
|
||||
# Only entries matching the slot's current occupancy_seq are surfaced.
|
||||
|
||||
Reference in New Issue
Block a user