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.<interval>]
C --> SMA[SimpleMovingAverage<br/>e.g. 7 and 20 days]
C --> MA[MovingAverage<br/>strategy]
SMA --> I[sc.<scenario>.indicator.sma7.changed.BTC_USDT]
MA --> O[sc.<scenario>.trading.order.submitted]
O --> SE[SimulatedExecutor]
SE --> F[sc.<scenario>.trading.order.filled]
- Candles are world-scoped market data; indicators, orders and fills are scenario-scoped and carry the
triggering candle's
eventtime. MovingAverageorders limit orders at the candle's close:SimulatedExecutorfills 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 |