How to Configure Risk Engine Settings in Nautilus Trader: A Complete Guide

Configure risk engine settings in Nautilus Trader by instantiating RiskEngineConfig for backtests or LiveRiskEngineConfig for live trading, then passing the configuration object to the system kernel or directly to the engine constructor.

The risk engine in Nautilus Trader enforces pre-trade risk checks, rate limits, and notional caps to protect your trading capital. To configure risk engine settings, you create immutable configuration objects that define parameters such as maximum order rates, notional limits per instrument, and bypass flags. This guide explains how to configure risk engine settings using the base RiskEngineConfig class for backtesting and the extended LiveRiskEngineConfig for production environments.

Understanding Risk Engine Configuration Classes

Nautilus Trader provides two primary configuration classes for the risk engine. The base RiskEngineConfig handles common settings for both backtesting and live trading, while LiveRiskEngineConfig extends it with asynchronous execution parameters.

Base Configuration with RiskEngineConfig

The RiskEngineConfig class in nautilus_trader/risk/config.py defines the core risk parameters used by both backtest and live risk engines. This immutable configuration object validates settings at construction time using Pydantic-style type hints.

Key attributes include:

  • bypass: When set to True, all pre-trade risk checks are skipped except for duplicate ID validation. This is useful for spot-only venues that do not support the full risk model.
  • max_order_submit_rate: A rate limit string formatted as "N/HH:MM:SS" that restricts order submission frequency. For example, "100/00:00:01" allows 100 submit commands per second.
  • max_order_modify_rate: Same format as the submit limit, but controlling order modification commands.
  • max_notional_per_order: A dictionary mapping instrument_id strings to maximum notional values (e.g., {"BTC-USD": 1_000_000}) to cap individual order values.
  • debug: Enables verbose diagnostic logging when set to True.

Live Trading with LiveRiskEngineConfig

For production environments, the LiveRiskEngineConfig class in nautilus_trader/live/config.py extends the base configuration with asynchronous execution parameters. The system kernel automatically instantiates a LiveRiskEngine when this configuration type is provided and the environment is not BACKTEST.

Additional live-only attributes include:

  • qsize: Defines the internal asyncio.Queue capacity for commands and events. The default value of 100_000 is suitable for high-throughput strategies, but you can lower this for memory-constrained environments.
  • graceful_shutdown_on_exception: Determines the system's response to queue-processing errors. When True, the engine attempts a coordinated shutdown via self.shutdown_system(). When False, the process exits immediately with os._exit(1).

How the System Kernel Applies Risk Engine Settings

The system kernel in nautilus_trader/system/kernel.py handles the instantiation of the appropriate risk engine based on your configuration type. When building a trading node, the kernel inspects the top-level Config object and selects the engine implementation accordingly.


# Kernel snippet that selects the appropriate engine

if isinstance(config.risk_engine, LiveRiskEngineConfig):
    self._risk_engine = LiveRiskEngine(
        loop=self.loop,
        portfolio=self._portfolio,
        msgbus=self._msgbus,
        cache=self._cache,
        clock=self._clock,
        config=config.risk_engine,
    )
elif isinstance(config.risk_engine, RiskEngineConfig):
    self._risk_engine = RiskEngine(
        portfolio=self._portfolio,
        msgbus=self._msgbus,
        cache=self._cache,
        clock=self._clock,
        config=config.risk_engine,
    )

This wiring logic ensures that LiveRiskEngine receives the event loop and live-specific configuration, while the standard RiskEngine operates with synchronous backtest components.

Configuring Risk Engine Settings: Code Examples

Minimal Live Risk Engine Configuration

To configure risk engine settings for a live trading environment without using the high-level kernel, instantiate LiveRiskEngineConfig and pass it directly to the LiveRiskEngine constructor.

from nautilus_trader.live.config import LiveRiskEngineConfig
from nautilus_trader.live.risk_engine import LiveRiskEngine
import asyncio

# Custom configuration

risk_cfg = LiveRiskEngineConfig(
    bypass=False,                       # enforce all checks

    max_order_submit_rate="50/00:00:01",
    max_order_modify_rate="20/00:00:01",
    max_notional_per_order={"ETH-USD": 500_000},
    debug=True,                         # verbose logging

    qsize=10_000,                       # smaller internal queues

    graceful_shutdown_on_exception=True,
)

# Assuming you already have a running event loop, portfolio, msgbus, cache and clock:

loop = asyncio.get_event_loop()
risk_engine = LiveRiskEngine(
    loop=loop,
    portfolio=portfolio,
    msgbus=msgbus,
    cache=cache,
    clock=clock,
    config=risk_cfg,
)

risk_engine.start()   # launches internal command/event queue tasks

High-Level Kernel Configuration

For most use cases, configure risk engine settings through the top-level Config object, allowing the system kernel to handle engine instantiation automatically.

from nautilus_trader.config import (
    Config,
    LiveRiskEngineConfig,
    LiveDataEngineConfig,
    LiveExecEngineConfig,
    LivePortfolioConfig,
    LiveCacheConfig,
    Environment,
)

# Build a top-level config that the kernel will consume

cfg = Config(
    environment=Environment.LIVE,
    risk_engine=LiveRiskEngineConfig(
        bypass=True,           # useful for spot-only exchanges

        qsize=5_000,
    ),
    data_engine=LiveDataEngineConfig(),
    exec_engine=LiveExecEngineConfig(),
    portfolio=LivePortfolioConfig(),
    cache=LiveCacheConfig(),
)

# The kernel will automatically instantiate a LiveRiskEngine with the above config

from nautilus_trader.system.kernel import NautilusKernel
kernel = NautilusKernel(config=cfg)
kernel.start()   # starts all components including the risk engine

Backtest Risk Engine Configuration

For backtesting scenarios, use the base RiskEngineConfig class without live-specific parameters.

from nautilus_trader.risk.config import RiskEngineConfig

# In a back-test you can disable all checks:

risk_cfg = RiskEngineConfig(bypass=True)

Key Source Files

The following source files define and implement the risk engine configuration system:

Summary

  • Use RiskEngineConfig for backtesting and basic risk management with attributes like bypass, max_order_submit_rate, and max_notional_per_order.
  • Use LiveRiskEngineConfig for production environments to access live-specific settings including qsize and graceful_shutdown_on_exception.
  • Pass configuration objects either directly to engine constructors or through the top-level Config object consumed by NautilusKernel in nautilus_trader/system/kernel.py.
  • Validate settings at construction time; misconfigured values raise immediate TypeError exceptions before runtime.
  • Control rate limits using the "N/HH:MM:SS" format to protect venue API quotas from excessive order submissions or modifications.

Frequently Asked Questions

What is the difference between RiskEngineConfig and LiveRiskEngineConfig?

RiskEngineConfig is the base configuration class found in nautilus_trader/risk/config.py that provides core risk parameters like rate limits and notional caps for both backtesting and live trading. LiveRiskEngineConfig extends this base class in nautilus_trader/live/config.py to add asynchronous execution parameters specific to production environments, including qsize for queue capacity and graceful_shutdown_on_exception for error handling behavior.

How do I bypass all risk checks in Nautilus Trader?

Set the bypass parameter to True when creating your configuration object. When bypass=True, the risk engine skips all pre-trade risk checks including order-size limits, rate limits, and notional caps, while still maintaining duplicate ID validation. This is particularly useful for spot-only venues that do not support the full risk model, and can be configured for both backtests using RiskEngineConfig(bypass=True) and live trading using LiveRiskEngineConfig(bypass=True).

What happens when max_order_submit_rate is exceeded?

When the number of order submissions exceeds the threshold defined in max_order_submit_rate (formatted as "N/HH:MM:SS"), the risk engine blocks additional submit commands until the rate limit window resets. This protects your venue API quotas from excessive requests that could result in bans or throttling. The engine enforces this limit internally before passing commands to the execution layer, ensuring that only compliant order flow reaches the exchange.

How does graceful_shutdown_on_exception work in live trading?

The graceful_shutdown_on_exception parameter in LiveRiskEngineConfig determines the system's response to unexpected errors in queue-processing tasks. When set to True, the risk engine attempts a coordinated shutdown by calling self.shutdown_system() to close positions and cancel orders cleanly. When set to False, the process terminates immediately using os._exit(1) without cleanup, which may leave orphaned orders on exchanges but prevents hanging processes during critical failures.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →