Type/to search
Getting Started
Welcome to FMZ Quant Trading Platform
Quick Start
Key Security
Platform Basics
Account and Billing
Live Robot Billing and Top-up
Sub-accounts
Exchange
General Protocol
Local Credential Files
Exchange-Specific Notes
Securities and Futures
Crypto
Docker
Strategy Library
Live Trading
Writing Strategies
Development Tools
Backtesting System
Advanced Topics
Data and Research
Integrations

Besides polling at a fixed interval, a strategy can wait for events and handle them as they arrive, which avoids useless requests and reacts faster to market changes.

EventLoop

EventLoop waits for events such as the completion of concurrent tasks started with exchange.Go() or HttpQuery_Go(), readable data on a WebSocket connection, or thread messages; when one occurs it returns the event information and the strategy then reads the corresponding data. Events are recorded only from the first call of EventLoop(), so call EventLoop(-1) once before starting concurrent tasks:

javascript
function main() { EventLoop(-1) // start recording events so none are missed var r1 = exchange.Go("GetTicker") var r2 = exchange.Go("GetDepth") var ev = EventLoop(1000) // wait up to 1 second for either task to finish Log("event:", ev) Log("ticker:", r1.wait(), "depth:", r2.wait()) }

ctx.subscribe / ctx.poll

JavaScript and Rust strategies can also use the docker's event subscription interface: ctx.subscribe() subscribes to market data or order updates for an account and symbol and returns a stream ID; ctx.poll() takes the next event (optionally with a timeout), and the strategy handles it according to its kind. Python strategies do not support it.

javascript
function main() { ctx.subscribe(0, "BTC_USDT", {channel: "ticker"}) // the first argument is the account's index in exchanges ctx.subscribe(0, "", {channel: "orders"}) // order updates while (true) { const ev = ctx.poll([], 1000) // [] means all subscriptions; wait up to 1 second if (!ev) { continue } if (ev.kind === 1) { Log("ticker:", ev.symbol, ev.bid, ev.ask, ev.last) } else if (ev.kind === 16) { Log("order:", ev.id, ev.state, ev.filledQty) } } }
  • channel can be "ticker", "bbo", "depth", "trade", "kline" (interval is the period in seconds) or "orders".
  • Event kind: 1 ticker, 3 depth (the event only signals that the order book changed; read the levels with ctx.book(ev.ex, ev.symbol, n)), 4 trade, 5 K-line, 16 order update.
  • If market data subscriptions are not consumed in time, only the latest data is kept or the oldest is dropped; order updates are never dropped, so the strategy must keep calling ctx.poll().

In Rust the calls are ctx::subscribe() and ctx::poll(); events are raw structures whose prices and quantities are fixed-point integers:

rust
fn main() { let s = ctx::subscribe(0, "BTC_USDT", ctx::SubOpts::ticker()).unwrap(); loop { match ctx::poll(&[s], Some(1000)) { ctx::Polled::Event(ev) => Log!("event kind:", ev.kind), ctx::Polled::Stopped => break, _ => {} } } }