Skip to content

Data Flow

Binance CLOB and Order Flow Imbalance (Python)

binance_clob_example.py keeps a local BTC_USDT order book from Binance's depth stream and saves its top 20 levels to State. orderflow_imbalance_worker.py reads that state and computes the imbalance.

sequenceDiagram
    participant Binance
    participant WSM as WebSocketManager
    participant API as API gateway
    participant Clob as binance_clob_example.py
    participant Imb as orderflow_imbalance_worker.py

    Clob->>API: websocketmanager.Connect (stream URL, auto_reconnect)
    Clob->>API: SendRaw SUBSCRIBE btcusdt@depth@100ms
    Clob->>API: StartPublish x.examples.binance-clob.depth
    Clob->>API: subscribe x.examples.binance-clob.depth
    Binance->>WSM: depthUpdate (every 100 ms)
    WSM->>API: publish frame to the topic
    API-->>Clob: depth event
    Note over Clob: Applies the diff to the local book<br/>(REST snapshot from Binance on a gap)

    loop Every 10 s
        Clob->>API: save_state websocketmanager/x.examples.binance-clob.orderbook.BTC_USDT (top 20 + spread)
    end

    loop Every 2 s
        Imb->>API: get_state websocketmanager/x.examples.binance-clob.orderbook.BTC_USDT
        Note over Imb: New lastUpdateId? Compute weighted imbalance
        Imb->>API: save_state statestore/x.examples.orderflow.imbalance.BTC_USDT
    end

    Clob->>API: websocketmanager.Disconnect (on exit)

orderflow_imbalance_worker.py has no connection of its own: it reads only the state written by binance_clob_example.py, which must be running.

Alpaca CLOB (Python)

sequenceDiagram
    participant Alpaca
    participant WSM as WebSocketManager
    participant API as API gateway
    participant Ex as alpaca_clob_example.py

    Ex->>API: websocketmanager.Connect wss://stream.data.alpaca.markets/v1beta3/crypto/us
    Ex->>API: subscribe x.examples.alpaca-clob.orderbook
    Ex->>API: StartPublish x.examples.alpaca-clob.orderbook
    Ex->>API: SendRaw {"action":"auth","key":…,"secret":…}
    Ex->>API: SendRaw {"action":"subscribe","orderbooks":["BTC/USD"]}
    Alpaca->>WSM: full book (r=true), then updates
    WSM->>API: publish frame
    API-->>Ex: frame
    Note over Ex: Applies it to the local book
    loop Every 10 s
        Ex->>API: save_state statestore/x.examples.alpaca-clob.orderbook.BTC_USD
    end

The order matters: a topic subscription starts at the topic's tail, and Alpaca's first message after the subscribe is the full book, so the example subscribes to the topic and starts publishing before it subscribes at Alpaca. run_alpaca_market_data_example.py follows the same order for five symbols on x.examples.alpaca-ticks.

Engine pipeline (C# notebooks)

The devkit notebooks deploy the published engines on demo; devkit-pipeline.verso runs the same chain in-process on real Binance klines.

flowchart LR
    BIN[Binance klines] -->|WebSocketManager| K[act.exchange.binance.candle.update]
    K --> BC[BinanceCandles]
    BC --> C[act.exchange.binance.candle.closed.BTC_USDT.&lt;interval&gt;]
    C --> SMA[SimpleMovingAverage<br/>e.g. 7 and 20 days]
    C --> MA[MovingAverage<br/>strategy]
    SMA --> I[sc.&lt;scenario&gt;.indicator.sma7.changed.BTC_USDT]
    MA --> O[sc.&lt;scenario&gt;.trading.order.submitted]
    O --> SE[SimulatedExecutor]
    SE --> F[sc.&lt;scenario&gt;.trading.order.filled]
  • Candles are world-scoped market data; indicators, orders and fills are scenario-scoped and carry the triggering candle's eventtime.
  • MovingAverage orders limit orders at the candle's close: SimulatedExecutor fills limit orders only.
  • Every worker subscribed to a topic gets every message on it.

State Keys

The scripts' keys and topics are their own, outside every published contract, so they live in the naming library's experimental scope x.* (lib.docs.virtufin.com/naming). Pairs are canonical (BTC_USDT, BTC_USD); the venue's own symbol appears only where a script talks to it.

Service / key Written by Content
websocketmanager / x.examples.binance-clob.orderbook.BTC_USDT binance_clob_example.py Top 20 bids/asks, best bid/ask, spread, lastUpdateId
statestore / x.examples.alpaca-clob.orderbook.BTC_USD alpaca_clob_example.py Top 20 bids/asks and spread
statestore / x.examples.orderflow.imbalance.BTC_USDT orderflow_imbalance_worker.py Weighted bids/asks, imbalance, spread, pressure signal

The gateway accepts only the services it registers (statestore, websocketmanager, workmanager).

Topics used by the scripts

Topic Published by (via WebSocketManager) Read by
x.examples.binance-clob.depth binance_clob_example.py binance_clob_example.py
x.examples.binance-depth.BTC_USDT websocketmanager_example.ts nobody in the examples
x.examples.alpaca-clob.orderbook alpaca_clob_example.py alpaca_clob_example.py
x.examples.alpaca-ticks run_alpaca_market_data_example.py run_alpaca_market_data_example.py