fix: guard unmanaged resolution on authoritative balances
Co-authored-by: genichin <4282227+genichin@users.noreply.github.com>
This commit is contained in:
co-authored by
genichin
parent
f2b825e720
commit
5a13c0494b
@@ -13,7 +13,6 @@ import os
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from threading import Lock
|
||||
from typing import Optional
|
||||
|
||||
from trex_core.application.broker_port import (
|
||||
BalanceItem,
|
||||
@@ -134,8 +133,8 @@ class OwnershipAwareBroker:
|
||||
*,
|
||||
side: str,
|
||||
symbol: str,
|
||||
order_date: Optional[str] = None,
|
||||
submitted_at: Optional[datetime] = None,
|
||||
order_date: str | None = None,
|
||||
submitted_at: datetime | None = None,
|
||||
) -> FillStatus:
|
||||
result = self._delegate.poll_fill(
|
||||
broker_order_id,
|
||||
@@ -175,6 +174,10 @@ class OwnershipAwareBroker:
|
||||
def get_balance(self) -> list[BalanceItem]:
|
||||
return self._store.project(self._delegate.get_balance())
|
||||
|
||||
def exposes_full_balance_snapshot(self) -> bool:
|
||||
"""False: projected balances omit operator-owned/unmanaged broker positions."""
|
||||
return False
|
||||
|
||||
def account_scope_hash(self) -> str:
|
||||
return self._delegate.account_scope_hash()
|
||||
|
||||
|
||||
@@ -364,6 +364,18 @@ def _notify_unmanaged_position_transition(
|
||||
)
|
||||
|
||||
|
||||
def _broker_balances_are_authoritative_for_unmanaged_resolution(broker: BrokerPort) -> bool:
|
||||
marker = getattr(broker, "exposes_full_balance_snapshot", None)
|
||||
if callable(marker):
|
||||
try:
|
||||
return bool(marker())
|
||||
except Exception: # noqa: BLE001 - fail closed on broker self-report failure
|
||||
return False
|
||||
if isinstance(marker, bool):
|
||||
return marker
|
||||
return True
|
||||
|
||||
|
||||
def reconcile_core_holdings(
|
||||
*,
|
||||
slot_repo,
|
||||
@@ -535,7 +547,10 @@ def reconcile_core_holdings(
|
||||
symbol=sym,
|
||||
quantity=bq,
|
||||
)
|
||||
if unmanaged_position_store is not None:
|
||||
if (
|
||||
unmanaged_position_store is not None
|
||||
and _broker_balances_are_authoritative_for_unmanaged_resolution(broker)
|
||||
):
|
||||
try:
|
||||
for state in unmanaged_position_store.resolve_absent(
|
||||
instance_key=instance_key,
|
||||
@@ -555,6 +570,11 @@ def reconcile_core_holdings(
|
||||
)
|
||||
except Exception: # noqa: BLE001
|
||||
_log.exception("reconcile_core_holdings: unmanaged_position resolve failed")
|
||||
elif unmanaged_position_store is not None:
|
||||
_log.debug(
|
||||
"reconcile_core_holdings: unmanaged_position resolve skipped "
|
||||
"(non-authoritative broker balance view)"
|
||||
)
|
||||
# req-0007 / ac-0024: retry pending_resolved for B-case identities no longer mismatched.
|
||||
if alarm_emitter is not None and notification_store is not None:
|
||||
try:
|
||||
|
||||
@@ -1016,7 +1016,7 @@ def _cmd_unmanaged_list(args, cfg) -> int:
|
||||
symbol=args.symbol,
|
||||
)
|
||||
payload = {
|
||||
"instance": instance,
|
||||
"instance_key": instance,
|
||||
"status": args.status,
|
||||
"count": len(states),
|
||||
"states": states,
|
||||
|
||||
Reference in New Issue
Block a user