Files
siloqy/prod/clean_arch/runtime
Codex c864e9c550 PINK: S1 leverage cache, S2 background refresh, Gap 1/2/3 fee+slippage logging
S1 — Leverage cache (bingx_direct.py):
  _ensure_leverage(): per-symbol asyncio.Lock + cached value check; skips ~350ms
  POST when exchange already has the requested leverage.  Saves ~350ms/trade.
  Cache updated ONLY on success; failed POST leaves cache stale → correct retry.
  Persist: JSON sidecar /tmp/.bingx_leverage_cache_{env}.json; survives restarts.
  connect(): _verify_leverage_drift() detects when another process changed leverage
  at the exchange and updates cache to exchange truth (logs WARNING on drift).
  Multi-runner contract: leverage is account-level on BingX; documented that
  concurrent runners with different leverage desires for same symbol conflict.
  20 mock tests: same-lev skip, change-triggers-POST, failure-no-cache-update,
  concurrent-same-symbol (lock prevents race), drift-detect, persist/restore,
  multi-runner known-limitation documentation test.

S2 — Background state refresh (bingx_direct.py):
  MARKET fills: asyncio.create_task(_refresh_state_background) — does not block
  submit path.  WS FILL_SETTLED + ACCOUNT_UPDATE deliver capital truth anyway.
  LIMIT fills: synchronous refresh retained (include_history=False, not True) —
  needed to detect resting order state for next pump cycle.
  Saves ~600–900ms/trade on MARKET exits. ENTER similarly improved.

Gap 1 — VenueEvent friction fields (contracts.py):
  Added: fee, fee_asset, fee_source, is_maker, exchange_ts, slippage_bps,
  mark_at_submit — all with defaults so existing callers are unaffected.
  Detailed inline docs for sign conventions and provenance codes.

Gap 2 — Fee estimation + WS_SETTLED provenance (bingx_direct.py, pink_clickhouse.py):
  submit_intent: estimates fee from fill_price × fill_qty × taker/maker rate;
  annotates ack_row with _fee_estimated, _fee_source, _is_maker_est.
  persist_fee_settled(): new method writes fee_settled_events row when WS
  ORDER_TRADE_UPDATE delivers actual commission ("n" field); fee_source="WS_SETTLED".
  pink_direct._run_account_stream: calls persist_fee_settled on FILL_SETTLED.

Gap 3 — Slippage measurement (bingx_direct.py, bingx_venue.py, pink_clickhouse.py):
  Captures mark_at_submit before the order POST; computes slippage_bps signed
  by side: positive = adverse (taker overpaid / maker undersold), negative =
  price improvement.  Measured for BOTH taker and maker fills for symmetry.
  Flows through VenueEvent → trade_events.slippage_bps + trade_exit_legs.slippage_bps.

S3 / SOR — Maker order placement: comprehensive TODO block in submit_intent with:
  SHORT/LONG-aware price offset design, OBF integration requirements,
  TODO_ADD_PARAMSET_VIBRISS for spread_bps threshold, intelligent timeout_s
  calibration requirements, price-impact awareness gap, SOR abstraction CRITICAL TODO.
  REST/WS split: documented why BingX (and all retail venues) separate these
  and why a unified VenueAdapter protocol is the long-term solution.

151/151 existing tests green + 20 new leverage cache tests = 171 total.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 12:25:12 +02:00
..