NAUTILUS / RUST source 3eb18933
Pages

Rust edition: this page follows the live DeepWiki structure but treats the current Rust crates as implementation authority. Non-Rust surfaces are identified at their boundary and are not presented as Rust APIs.

RiskEngine and Pre-trade Checks

Relevant Rust source files

  • crates/risk/src/engine/mod.rs
  • crates/execution/src/engine/mod.rs
  • crates/common/src/throttler.rs

Purpose and Scope

The RiskEngine is the central component responsible for global risk management across all strategies and portfolios within a trading node. This page details the pre-trade risk validation pipeline, including price and quantity checks, trading state restrictions, notional limits, and order rate throttling. It ensures that all trading commands comply with defined risk parameters before reaching the execution layer.


Overview

The RiskEngine sits between trading strategies and the ExecutionEngine in the order flow pipeline. It acts as a high-performance gatekeeper, performing mandatory pre-trade validation on all TradingCommand messages.

Core Responsibilities:

  • Order Validation: Checks price, quantity, and notional value against instrument specifications.
  • Trading State Management: Enforces global states (ACTIVE, REDUCING, HALTED) to restrict order types.
  • Rate Limiting: Employs throttlers to limit the rate of order submissions and modifications.
  • Re-entrancy Handling: Uses queued endpoints and specialized senders to prevent recursive calls during event processing.
  • Error Reporting: Generates OrderDenied or OrderModifyRejected events when checks fail.

Architecture and Message Flow

The RiskEngine is integrated into the system via the MessageBus. It registers specific endpoints to handle trading commands synchronously or asynchronously.

Entity Mapping: Risk Validation Flow

The following diagram bridges the natural language concepts of risk management to the specific code entities and message bus endpoints used in the implementation.

RiskEngine gating strategy commands before ExecutionEngine and Interactive Brokers, with rejected commands never crossing the broker boundary.

Re-entrancy and Queued Execution

In live trading, a strategy might call submit_order() from within an event handler (e.g., on_order_filled). To prevent RefCell re-entrancy panics in Rust (where a component is mutably borrowed while another call attempts to borrow it again), the RiskEngine registers a risk_engine_queue_execute endpoint.

This endpoint uses try_get_trading_cmd_sender() to obtain a sender that queues the command for the next iteration of the event loop in live mode. In backtest or test modes where no sender is present, it falls back to the direct direct risk_engine_execute endpoint.


Trading States

The RiskEngine enforces a global TradingState which dictates permitted operations:

State Behavior
ACTIVE All trading commands permitted (default).
REDUCING Only orders or updates which reduce an open position are allowed.
HALTED All trading commands except cancels are denied.

State Transition Logic

When the state is REDUCING, the engine checks the PositionSide in the Portfolio. A BUY order is only allowed if the current position is SHORT, and a SELL order is only allowed if the position is LONG. If the position is FLAT, no new opening orders are permitted.


Pre-trade Validation Pipeline

When a SubmitOrder or SubmitOrderList command is received, the engine executes a sequence of checks.

Pre-trade Check Sequence

This diagram illustrates the logical flow of validation within the RiskEngine methods such as execute and internal check functions.

Price and Quantity Checks

  • Price Validation: Ensures price is a multiple of price_increment and does not exceed price_precision. It also checks for negative prices (permitted only for specific instrument classes).
  • Quantity Validation: Validates against min_quantity, max_quantity, and size_increment.
  • Notional Limits: Calculates the total value (quantity * price) and compares it against max_notional_per_order configured for the specific InstrumentId.

Rate Limiting and Throttling

The RiskEngine prevents "fat-finger" errors or API rate-limit violations using Throttler components.

Implementation Details

The engine initializes two throttlers:

  1. throttled_submit: Limits the rate of SubmitOrder and SubmitOrderList.
  2. throttled_modify_order: Limits the rate of ModifyOrder.

The throttlers use a sliding window defined by a RateLimit (limit and interval). If the limit is reached, the output_drop callback is triggered, which publishes an OrderDenied or OrderModifyRejected event.


Configuration

The RiskEngineConfig allows fine-grained control over risk parameters.

Parameter Description
bypass If True, all risk checks are skipped.
max_order_submit_rate String format "limit/HH:MM:SS" for submission rate.
max_order_modify_rate String format "limit/HH:MM:SS" for modification rate.
max_notional_per_order Mapping InstrumentId to maximum allowed notional value.
debug Enables verbose logging of risk check results.

Summary of Key Classes

Class File Role
RiskEngine Main component orchestrating pre-trade checks.
RiskEngineConfig Configuration schema for risk limits and throttlers.
Throttler Core logic for rate-limiting and message buffering/dropping.
RateLimit Represents a non-zero limit per nanosecond interval.