from __future__ import annotations from typing import Any from typing import Literal from typing import Mapping from prod.utils.trade_sizing_bridge import TradeSizingDefaults from prod.utils.trade_sizing_bridge import build_engine_ready_sizing from prod.utils.trade_sizing_bridge import load_trade_sizing_defaults_from_control_plane SizingMode = Literal["engine", "testnet", "live_market"] ENGINE_MODE: SizingMode = "engine" TESTNET_MODE: SizingMode = "testnet" LIVE_MARKET_MODE: SizingMode = "live_market" def normalize_sizing_mode(mode: Any) -> SizingMode: """Normalize a caller-provided sizing mode.""" if isinstance(mode, str): normalized = mode.strip().lower() if normalized == TESTNET_MODE: return TESTNET_MODE if normalized == LIVE_MARKET_MODE: return LIVE_MARKET_MODE return ENGINE_MODE def build_split_sizing_payload( *, sizing_mode: Any = ENGINE_MODE, sizing_lev: float, capital: float | None = None, mark_price: float | None = None, quantity_step: float | None = None, venue_notional_cap: float | None = None, exchange_leverage_cap: int | None = None, margin_budget_fraction_override: float | None = None, system_fraction_override: float | None = None, control_plane: Mapping[str, Any] | None = None, hz_client: Any | None = None, defaults: TradeSizingDefaults | None = None, notes: dict[str, Any] | None = None, ) -> dict[str, Any] | None: """Return a BingX-ready sizing payload in testnet or live-market mode.""" mode = normalize_sizing_mode(sizing_mode) if mode == ENGINE_MODE: return None resolved_defaults = defaults or load_trade_sizing_defaults_from_control_plane( hz_client=hz_client, control_plane=control_plane, fallback=TradeSizingDefaults(), ) result = build_engine_ready_sizing( sizing_lev=sizing_lev, capital=capital, mark_price=mark_price, quantity_step=quantity_step, venue_notional_cap=venue_notional_cap, exchange_leverage_cap=exchange_leverage_cap, margin_budget_fraction_override=margin_budget_fraction_override, system_fraction_override=system_fraction_override, control_plane=control_plane, hz_client=hz_client, defaults=resolved_defaults, notes=notes or {}, ) payload = result.to_engine_payload() payload["sizing_mode"] = mode return payload