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 toTrue, 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 mappinginstrument_idstrings to maximum notional values (e.g.,{"BTC-USD": 1_000_000}) to cap individual order values.debug: Enables verbose diagnostic logging when set toTrue.
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 internalasyncio.Queuecapacity for commands and events. The default value of100_000is 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. WhenTrue, the engine attempts a coordinated shutdown viaself.shutdown_system(). WhenFalse, the process exits immediately withos._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:
nautilus_trader/risk/config.py: Contains the baseRiskEngineConfigclass definingbypass, rate limits, notional caps, and debug settings.nautilus_trader/live/config.py: DefinesLiveRiskEngineConfigwith additionalqsizeandgraceful_shutdown_on_exceptionparameters.nautilus_trader/live/risk_engine.py: Implements the asynchronousLiveRiskEnginethat consumes the configuration.nautilus_trader/system/kernel.py: Contains the bootstrap logic that instantiates the appropriate risk engine based on configuration type.docs/api_reference/risk.md: API documentation for thenautilus_trader.riskpackage.
Summary
- Use
RiskEngineConfigfor backtesting and basic risk management with attributes likebypass,max_order_submit_rate, andmax_notional_per_order. - Use
LiveRiskEngineConfigfor production environments to access live-specific settings includingqsizeandgraceful_shutdown_on_exception. - Pass configuration objects either directly to engine constructors or through the top-level
Configobject consumed byNautilusKernelinnautilus_trader/system/kernel.py. - Validate settings at construction time; misconfigured values raise immediate
TypeErrorexceptions 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →