from __future__ import annotations from decimal import Decimal from nautilus_trader.config import InstrumentProviderConfig from nautilus_trader.config import LiveExecClientConfig from nautilus_trader.config import PositiveInt from .enums import BINGX_VENUE from .enums import BingxEnvironment def require_mainnet_opt_in(environment: BingxEnvironment, allow_mainnet: bool, *, context: str) -> None: """ Fail closed unless the caller explicitly opts into BingX LIVE mainnet. """ if environment is BingxEnvironment.LIVE and not allow_mainnet: raise ValueError(f"{context} LIVE requires allow_mainnet=True") class BingxInstrumentProviderConfig(InstrumentProviderConfig, frozen=True): """ Configuration for the BingX perpetual futures instrument provider. """ symbol_filters: tuple[str, ...] | None = None default_maker_fee: Decimal = Decimal("0.0002") default_taker_fee: Decimal = Decimal("0.0005") class BingxExecClientConfig(LiveExecClientConfig, frozen=True): """ Configuration for the BingX live execution client. """ venue = BINGX_VENUE api_key: str | None = None secret_key: str | None = None environment: BingxEnvironment = BingxEnvironment.VST allow_mainnet: bool = False base_url_http: str | None = None base_url_http_backup: str | None = None base_url_ws_private: str | None = None http_timeout_secs: PositiveInt = 10 recv_window_ms: PositiveInt = 5_000 max_retries: PositiveInt = 3 retry_delay_initial_ms: PositiveInt = 250 retry_delay_max_ms: PositiveInt = 2_000 instrument_provider: BingxInstrumentProviderConfig = BingxInstrumentProviderConfig(load_all=True) use_gtd: bool = False use_reduce_only: bool = True use_position_ids: bool = False prefer_websocket: bool = True ws_listenkey_keepalive_interval_secs: PositiveInt = 1_800 ws_event_stale_after_ms: PositiveInt = 15_000 ws_reconnect_initial_ms: PositiveInt = 500 ws_reconnect_max_ms: PositiveInt = 10_000 poll_open_orders_interval_ms: PositiveInt = 500 poll_account_interval_ms: PositiveInt = 2_000 poll_positions_interval_ms: PositiveInt = 2_000 default_leverage: PositiveInt = 1 exchange_leverage_cap: PositiveInt = 3 sizing_mode: str = "engine" leverage_by_symbol: dict[str, PositiveInt] | None = None margin_type_by_symbol: dict[str, str] | None = None enforce_integer_leverage: bool = True journal_strategy: str | None = None journal_db: str | None = None def validate_mainnet_opt_in(self) -> None: require_mainnet_opt_in(self.environment, self.allow_mainnet, context="BingX execution client")