Market Data¶
TL;DR
Bind a venue data source, subscribe to its typed topic, and react to every event in your handler. Topic keys are compile-time literals validated against known schemas — a typo in the key is a build error, not a silent runtime failure.
Why canonical topic keys?¶
Aurum uses compile-time topic keys like bar://okx/BTCUSDT@1m instead of
runtime-registered string keys. This is a deliberate design choice with three
consequences:
Typos are build errors.
bar://okx/BTCUSDT@1n(invalid interval) does not compile. You find out in your editor, not after six hours of silent data loss in production.Schema binding is automatic. The topic literal
"bar://okx/BTCUSDT@1m"deducesTick<schema::BarRow>at compile time. Your handler cannot accept the wrong payload type — the compiler rejects it.The key format is self-describing. The scheme identifies the resource family (
bar://), the authority identifies the source (okx), and the path encodes the instrument and parameters (BTCUSDT@1m). Clients can parse keys without an external schema registry.
Alternative considered: runtime string keys (like Kafka topics). Runtime keys are more flexible — you can add topics without recompiling. But they push data contract errors to runtime: a consumer expecting a different schema than the producer receives garbled data with no compile-time warning. For a trading system where data correctness is the primary requirement, Aurum chose compile-time safety over runtime flexibility.
Bind a feed¶
#include <aurum/venue/okx.hpp>
bind<Datafeed>(venue::okx::Bar("BTCUSDT", "1m"));
bind<Datafeed>(venue::okx::Orderbook("BTCUSDT"));
The bind<Datafeed> call registers the feed with the engine. The venue
factory normalizes the exchange-specific connection details — you pass the
symbol and interval; the factory handles authentication, reconnection, and
protocol decoding.
Subscribe to its topics¶
on(TOPIC<"bar://okx/BTCUSDT@1m">,
[](const Tick<schema::BarRow>& tick) {
if (tick.payload.close_timestamp == 0) return;
log::info("close={}", tick.payload.close.to_string());
});
on(TOPIC<"book://okx/BTCUSDT@full">,
[](const Tick<schema::BookRow>&) {
// Read the current projected book through the runtime view.
});
The topic literal and payload type form one contract. A mismatched schema is a compile-time error where the SDK has a canonical binding.
Note
An unconfirmed bar has close_timestamp == 0. The bar event still fires —
it carries open, high, low, and volume but the close is not yet final. A
handler that intentionally ignores unconfirmed bars can appear idle until
the current interval closes. This is correct behavior, not a data feed
failure.
Canonical topic families¶
Family |
Example |
Payload |
|---|---|---|
Bars |
|
|
Books |
|
|
Factors |
|
Scalar factor value |
Order events |
|
Order event envelope |
Resource discovery¶
A running application publishes a resource catalog. Forge and Terminal use that catalog to discover exact topic keys, schemas, delivery models, and history availability.
Warning
Clients must not guess a topic from its display label. Terminal shows a human-readable label for each resource; the underlying key may differ. If you construct a key from a label, your subscription will silently receive no data because the key does not match any published resource. Always copy the key from the catalog.
Common mistakes¶
- Ignoring unconfirmed bars.
A bar event with
close_timestamp == 0is an in-progress bar. If your handler processes it as a complete bar, your calculations will use an unconfirmed close price that may change when the interval ends. Checkclose_timestampbefore using the close value.- Constructing keys from labels.
Terminal labels are for display; topic keys are for subscriptions. They are not the same string. Always use the exact key from the resource catalog or the venue factory documentation.
- Binding a feed without a subscriber.
bind<Datafeed>registers the connection, but data only flows when at least one handler subscribes throughon(). If you bind a feed and see no data, check that you have anon()call for that topic.- Assuming all order books are the same depth.
book://okx/BTCUSDT@fulldelivers the full book.@5and@bbo-tbtdeliver different depths. The depth is encoded in the key; there is no default. Specify the depth you need in the factory call.
Next steps¶
To use market data in a paper trading simulation, read Simulation and Replay.
For the exact topic key reference, read Resource Contracts.
For WebSocket subscription from an external client, read Runtime WebSocket.