PINK: seed capital from BingX ledger of record on startup
Previously: set_seed_capital(hardcoded_25000) then on_account_event(BingX_100K+) → reconcile delta ~75K → capital_frozen=True → no trades allowed. Fix: _fetch_exchange_wallet_balance() queries BingX wallet balance BEFORE seeding the kernel. set_seed_capital() and the subsequent ACCOUNT_UPDATE reconcile now agree → delta ≈ 0 → capital_frozen=False → sizing correct. Falls back to DOLPHIN_INITIAL_CAPITAL if BingX is unreachable, with WARNING. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -296,12 +296,15 @@ class PinkDirectRuntime:
|
|||||||
await result
|
await result
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
self.logger.warning("Venue connect failed: %s", exc)
|
self.logger.warning("Venue connect failed: %s", exc)
|
||||||
_reconcile_position_slot(self.kernel, initial_capital, slot_id=0)
|
# BingX is the ledger of record. Fetch wallet balance BEFORE seeding
|
||||||
|
# the kernel so set_seed_capital() and reconcile agree with the exchange.
|
||||||
|
# Using a hardcoded fallback (e.g. 25000) while the VST account holds
|
||||||
|
# 100K+ would cause a ~75K reconcile delta → capital_frozen=True.
|
||||||
|
live_capital = await self._fetch_exchange_wallet_balance(initial_capital)
|
||||||
|
_reconcile_position_slot(self.kernel, live_capital, slot_id=0)
|
||||||
|
|
||||||
# Seed the kernel's atomic K-account from exchange truth.
|
# Seed the kernel's atomic K-account from exchange truth.
|
||||||
# This is the crash/restart recovery point: if the kernel restarted
|
self.kernel.set_seed_capital(live_capital)
|
||||||
# it re-reads exchange state here before accepting any ENTERs.
|
|
||||||
self.kernel.set_seed_capital(initial_capital)
|
|
||||||
await self._seed_account_from_exchange()
|
await self._seed_account_from_exchange()
|
||||||
|
|
||||||
# Restore fee calibration + account state from the previous session if the
|
# Restore fee calibration + account state from the previous session if the
|
||||||
@@ -340,6 +343,46 @@ class PinkDirectRuntime:
|
|||||||
"funding_interval_secs": 28_800, # 8 h BingX perps
|
"funding_interval_secs": 28_800, # 8 h BingX perps
|
||||||
})
|
})
|
||||||
|
|
||||||
|
async def _fetch_exchange_wallet_balance(self, fallback: float) -> float:
|
||||||
|
"""Query BingX for the current wallet balance to use as the capital seed.
|
||||||
|
|
||||||
|
BingX VST (and live) is the ledger of record. Seeding the kernel from
|
||||||
|
a hardcoded constant while the exchange holds a different balance causes
|
||||||
|
a large reconcile delta → capital_frozen=True on every startup.
|
||||||
|
|
||||||
|
Falls back to *fallback* if the HTTP client is unavailable or the
|
||||||
|
request fails, logging a WARNING so operators know sizing is approximate.
|
||||||
|
"""
|
||||||
|
http_client = self._venue_http_client()
|
||||||
|
if http_client is None:
|
||||||
|
self.logger.warning(
|
||||||
|
"No HTTP client — capital seeded from fallback=%.2f (BingX unreachable)",
|
||||||
|
fallback,
|
||||||
|
)
|
||||||
|
return fallback
|
||||||
|
try:
|
||||||
|
from prod.clean_arch.dita_v2.bingx_user_stream import BingxUserStream
|
||||||
|
stream = BingxUserStream(http_client=http_client, ws_base_url="")
|
||||||
|
ev = await stream.account_snapshot()
|
||||||
|
balance = float(ev.wallet_balance or 0.0)
|
||||||
|
if balance <= 0:
|
||||||
|
self.logger.warning(
|
||||||
|
"BingX returned wallet_balance=%.2f ≤ 0 — using fallback=%.2f",
|
||||||
|
balance, fallback,
|
||||||
|
)
|
||||||
|
return fallback
|
||||||
|
self.logger.info(
|
||||||
|
"Capital seeded from BingX ledger: wallet=%.2f (fallback was %.2f)",
|
||||||
|
balance, fallback,
|
||||||
|
)
|
||||||
|
return balance
|
||||||
|
except Exception as exc:
|
||||||
|
self.logger.warning(
|
||||||
|
"BingX wallet fetch failed (%s) — capital seeded from fallback=%.2f",
|
||||||
|
exc, fallback,
|
||||||
|
)
|
||||||
|
return fallback
|
||||||
|
|
||||||
async def _seed_account_from_exchange(self) -> None:
|
async def _seed_account_from_exchange(self) -> None:
|
||||||
"""
|
"""
|
||||||
Startup/crash-recovery:
|
Startup/crash-recovery:
|
||||||
|
|||||||
Reference in New Issue
Block a user