Skip to content
All library documents

Setting Up a Rust Live Trading Node with OKX

Article NautilusTrader

Summary

This guide shows how to assemble and run a Rust live-trading node connected to OKX. It covers registering venue data and execution adapters, configuring a trader and account, adding a grid market-making strategy, and supplying credentials through environment variables. It also notes that the asynchronous node requires a Tokio runtime and describes demo-environment configuration.

The example demonstrates the setup flow rather than evaluating a trading strategy. It uses a perpetual swap instrument and configures grid levels, position limits, quote adjustments, and order resubmission. The sample disables execution reconciliation for simplicity; the guide recommends enabling it in production so cached state can be aligned with the venue at startup. It provides no performance evidence, and the example’s settings and credentials handling need to be adapted to a specific deployment.

Key ideas

  • A live node connects to venues through separate data and execution adapter clients.
  • The builder configures identity, logging, venue clients, reconciliation, and shutdown behavior.
  • A grid market-making strategy can be added before starting the asynchronous node.
  • Venue credentials are supplied through environment variables, and demo mode uses demo credentials.
  • The example disables reconciliation, while the guide recommends enabling it for production.

Tags

Full text
# Run Live Trading (Rust)


# Run Live Trading (Rust)

The `LiveNode` connects to real venues and data sources through adapter clients. This guide
walks through a complete live trading setup using OKX as an example.

For the node lifecycle, see [Live trading](../concepts/live.md). For command outcomes, see
[Execution policies](../concepts/execution/policies.md#command-outcomes). For state recovery, see
[Execution reconciliation](../concepts/execution/reconciliation.md). For project setup and feature flags,
see the [Rust](../concepts/rust.md#project-setup) concept guide.

## Dependencies

Add the live crate, your venue adapter, and supporting crates to
`Cargo.toml`:

```toml
[dependencies]
nautilus-common = "0.65"
nautilus-live = "0.65"
nautilus-model = "0.65"
nautilus-okx = "0.65"
nautilus-trading = { version = "0.65", features = ["examples"] }

anyhow = "1"
dotenvy = "0.15"
log = "0.4"
tokio = { version = "1", features = ["full"] }
```

## Build the node

The `LiveNode` uses a builder pattern. Add data and execution client
factories for your venue, configure logging, and build.

```rust
use log::LevelFilter;
use nautilus_common::{enums::Environment, logging::logger::LoggerConfig};
use nautilus_live::node::LiveNode;
use nautilus_model::identifiers::{AccountId, TraderId};
use nautilus_okx::{
    common::enums::OKXInstrumentType,
    config::{OKXDataClientConfig, OKXExecutionClientConfig},
    factories::{OKXDataClientFactory, OKXExecutionClientFactory},
};

let trader_id = TraderId::from("TESTER-001");
let account_id = AccountId::from("OKX-001");

let data_config = OKXDataClientConfig::builder()
    .instrument_types(vec![OKXInstrumentType::Swap])
    .build();

let exec_config = OKXExecutionClientConfig::builder()
    .account_id(account_id)
    .instrument_types(vec![OKXInstrumentType::Swap])
    .build();

let log_config = LoggerConfig {
    stdout_level: LevelFilter::Info,
    ..Default::default()
};

let mut node = LiveNode::builder(trader_id, Environment::Live)?
    .with_name("MY-NODE-001".to_string())
    .with_logging(log_config)
    .add_data_client(
        None,
        Box::new(OKXDataClientFactory::new()),
        Box::new(data_config),
    )?
    .add_exec_client(
        None,
        Box::new(OKXExecutionClientFactory::new()),
        Box::new(exec_config),
    )?
    .with_reconciliation(false) // Simplified; enable in production
    .with_delay_post_stop_secs(5)
    .build()?;
```

:::warning
This example disables reconciliation for simplicity. In production, remove
`.with_reconciliation(false)` so the engine aligns cached state with the
venue on startup. See [Execution reconciliation](../concepts/execution/reconciliation.md).
:::

## Add strategies and run

```rust
use nautilus_model::{identifiers::InstrumentId, types::Quantity};
use nautilus_trading::examples::strategies::{
    GridMarketMaker, GridMarketMakerConfig,
};

let mut config = GridMarketMakerConfig::builder()
    .instrument_id(InstrumentId::from("ETH-USDT-SWAP.OKX"))
    .max_position(Quantity::from("0.10"))
    .num_levels(3)
    .grid_step_bps(100)
    .skew_factor(0.5)
    .requote_threshold_bps(10)
    .expire_time_secs(8)
    .on_cancel_resubmit(true)
    .build();

// OKX rejects hyphens in client order IDs
config.base.use_hyphens_in_client_order_ids = false;

let strategy = GridMarketMaker::new(config);

node.add_strategy(strategy)?;
node.run().await?;
```

The node runs until interrupted (Ctrl+C) or shut down programmatically.

## Environment variables

OKX reads API credentials from environment variables. Use a `.env` file
with `dotenvy` or set them in your shell:

```bash
export OKX_API_KEY="your_api_key"
export OKX_API_SECRET="your_api_secret"
export OKX_API_PASSPHRASE="your_passphrase"
```

For demo trading, set `.environment(OKXEnvironment::Demo)` on both config builders and use demo
API credentials from OKX.

Each adapter documents its required variables in the
[integration guide](../integrations/) for that venue.

## Async runtime

`LiveNode::run()` is async and requires a Tokio runtime. Use `#[tokio::main]`
on your main function:

```rust
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenvy::dotenv().ok();

    // ... node setup ...

    node.run().await?;
    Ok(())
}
```

## Adapter examples

Most adapters include runnable examples with data testers and execution
testers:

| Adapter             | Example directory                               |
| ------------------- | ----------------------------------------------- |
| Architect AX        | `crates/adapters/architect_ax/examples/`        |
| Betfair             | `crates/adapters/betfair/examples/`             |
| Binance             | `crates/adapters/binance/examples/`             |
| Blockchain          | `crates/adapters/blockchain/examples/`          |
| Bybit               | `crates/adapters/bybit/examples/`               |
| Coinbase            | `crates/adapters/coinbase/examples/`            |
| Databento           | `crates/adapters/databento/examples/`           |
| Deribit             | `crates/adapters/deribit/examples/`             |
| Derive              | `crates/adapters/derive/examples/`              |
| dYdX                | `crates/adapters/dydx/examples/`                |
| Hyperliquid         | `crates/adapters/hyperliquid/examples/`         |
| Interactive Brokers | `crates/adapters/interactive_brokers/examples/` |
| Kraken              | `crates/adapters/kraken/examples/`              |
| Lighter             | `crates/adapters/lighter/examples/`             |
| OKX                 | `crates/adapters/okx/examples/`                 |
| Polymarket          | `crates/adapters/polymarket/examples/`          |
| Sandbox             | `crates/adapters/sandbox/examples/`             |
| Tardis              | `crates/adapters/tardis/examples/`              |

Shown in full with attribution under the source's licence. Licence: LGPL-3.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.