Exchange Executor Abstraction

Deep dive into the ExchangeExecutor Protocol, CCXT integration with exchange-specific adaptations, rate limiting, order placement pipeline, and the Paper Trading sandbox simulator.

โฑ๏ธ 7 min read๐Ÿ“Š Level: Intermediate

DepthSight uses a clean abstraction layer to decouple the strategy runner from raw exchange APIs. The system relies on a Python Protocol called ExchangeExecutor to guarantee static typing boundaries while allowing multiple execution strategies โ€” live exchanges, paper trading, and mock testing.


ExchangeExecutor Protocol

The ExchangeExecutor (bot_module/exchanges/base.py, ~59 lines) is a static Python Protocol defining the standard interaction contract. Any backend implementation (Binance, Bybit, Paper Trading) must satisfy these methods.

Rendering diagram...

Protocol Signature

Sources:

The protocol uses typing.Protocol (structural subtyping) โ€” any class implementing all these methods with matching signatures satisfies the contract without explicit inheritance. This enables easy mocking and testing.


CCXT Implementation (CCXTExecutor)

The CCXTExecutor (bot_module/exchanges/ccxt_executor.py, ~2,068 lines) is the primary production executor. It uses the asynchronous CCXT Pro library to communicate with target exchanges.

Order Placement Pipeline (place_order(), lines 605โ€“889)

The order placement process involves 11 steps:

Step 1 โ€” Symbol Normalization (line 608):

Sources:

Step 2 โ€” Order Type Mapping: Binance order types are mapped to CCXT equivalents:

Binance TypeCCXT TypeNotes
MARKET"market"Standard market order
LIMIT"limit"Limit order with price
STOP_MARKET"market"+ triggerPrice or stopLossPrice param
TAKE_PROFIT_MARKET"market"+ takeProfitPrice param
TRAILING_STOP_MARKET"market"+ callbackRate param

Step 3 โ€” Exchange-Specific Trigger Parameters: Each exchange handles stop/trigger orders differently:

ExchangeTrigger ParamNotes
Binance FuturesstopPrice, workingTypeStandard stop-market
BybittriggerPrice, triggerDirectionDirection 1=up, 2=down
BitgetstopLossPrice / takeProfitPriceSeparate SL/TP params
Gate.iostopLossPrice / takeProfitPrice+ settle: "usdt"
BingXstopLossPriceSandbox needs hedge mode
OKXposSideRequired for futures

Step 4 โ€” Binance Futures Algo Orders (lines 726โ€“819): For STOP_MARKET, TAKE_PROFIT_MARKET, TRAILING_STOP_MARKET on Binance Futures, the executor bypasses CCXT's create_order and calls fapiPrivatePostAlgoOrder directly for algo order placement:

Sources:

Step 5 โ€” Rate Limit Compliance: CCXT's built-in enableRateLimit: True manages request timing. No custom rate limiting logic is needed โ€” CCXT handles token bucket per-exchange internally.

Step 6 โ€” Response Mapping (line 883): The raw CCXT order is mapped to a Binance-compatible response via _map_ccxt_order_to_binance() (lines 1933โ€“1991), ensuring the controller receives a consistent format regardless of the underlying exchange.

Balance Fetching (get_account_balance(), lines 1365โ€“1477)

Sources:

For BingX sandbox (lines 1410โ€“1470), a special fallback chain tries multiple field names (availableMargin, availableBalance, maxWithdrawAmount, trialFundBalance, etc.) due to the sandbox's non-standard response format.

Exchange Info Caching (fetch_exchange_info(), lines 521โ€“603)

Exchange market info is cached via CCXT's load_markets():

Sources:

Individual symbol filters are accessible via:

  • get_tick_size(symbol) โ€” price increment precision
  • get_lot_size_params(symbol) โ€” quantity step size, min/max
  • get_min_notional(symbol) โ€” minimum order value

WebSocket User Data Stream

The executor manages exchange-specific user data streams (account updates, order fills):

Sources:

Paper Trading Simulator (PaperTradingExecutor)

To test strategies with zero risk, DepthSight includes a local matching engine sandbox.

Architecture

Strategy Signal -> PaperTradingExecutor
    |
    โ”œโ”€ Virtual Balance Check (paper_wallets table)
    โ”œโ”€ Market Data Matching (live DataConsumer L2 book)
    โ”œโ”€ Fill Simulation (price overlap detection)
    โ””โ”€ Trade Recording (trades table, trade_mode="PAPER")

Key Features

FeatureImplementation
Virtual BalancesStored in paper_wallets table โ€” per-user, per-asset
Order MatchingLimit orders filled when simulated ticker overlaps order price
Market OrdersFilled immediately at next available price + simulated slippage
L2 Book IntegrationUses live DataConsumer Level 2 updates for fill precision
Execution ParityImplements the exact ExchangeExecutor protocol โ€” switching a bot from paper to live requires changing one config parameter (mode: "live")

Execution Parity

Because PaperTradingExecutor implements the exact same ExchangeExecutor protocol as CCXTExecutor, the TradingController is completely agnostic to which executor is active:

Sources:

This design guarantees zero drift between backtest/paper and live performance.


Executor Factory

The create_exchange_executor() factory function (bot_module/exchanges/factory.py) dynamically selects the correct implementation based on exchange ID:

exchange_idExecutor ClassNotes
binanceCCXTExecutorFutures + Spot, testnet support via _patch_binance_demo_urls()
bybitCCXTExecutorLinear inverse + spot
bitgetCCXTExecutorHedge mode + one-way mode fallback
gateioCCXTExecutorSwap + spot with settle param
bingxCCXTExecutorSandbox with special balance parsing
paperPaperTradingExecutorLocal sandbox, no exchange connection