Principle:Nautechsystems Nautilus trader Order Position Event Handling
| Field | Value |
|---|---|
| sources | https://github.com/nautechsystems/nautilus_trader , https://nautilustrader.io/docs/ |
| domains | algorithmic trading, event-driven architecture, order management, position management |
| last_updated | 2026-02-10 12:00 GMT |
Overview
Order and position event handling defines the reactive pattern by which a trading strategy responds to changes in order state (fills, rejections, cancellations) and position state (opened, changed, closed) to maintain coherent trading logic and risk management.
Description
When a strategy submits an order, the result is not immediate. The order passes through multiple state transitions -- initialized, submitted, accepted, partially filled, filled, or rejected/cancelled. Similarly, positions evolve as orders fill -- a position may be opened, increased, decreased, or closed. Each transition generates an event that the strategy can observe and react to.
This event-driven feedback loop is essential because:
- Order fills drive position updates: When an order fills, the strategy may need to place follow-up orders (e.g., a stop-loss after an entry fill, or a take-profit bracket).
- Rejections require recovery logic: If an order is rejected, the strategy must decide whether to retry, adjust parameters, or abandon the trade.
- Position changes inform risk management: When a position is opened, the strategy may set risk limits; when closed, it may record P&L and prepare for the next trade.
- Partial fills require dynamic adjustment: When an order is partially filled, the strategy may need to adjust remaining order quantities or place additional orders.
The event handling model separates execution feedback (what happened to my orders) from market data (what is happening in the market), allowing strategies to maintain clean separation between signal generation and order management logic.
Usage
Apply order and position event handling when:
- Building strategies that place follow-up orders in response to fills (e.g., stop-loss placement after entry).
- Implementing position tracking and P&L logging at the strategy level.
- Creating strategies that must react to order rejections or cancellations with recovery logic.
- Designing multi-leg strategies where subsequent legs depend on the completion of earlier legs.
Theoretical Basis
Order and position event handling combines two patterns:
1. Event Sourcing for Order State
Each order maintains its state as a sequence of events. The current state is the result of applying all events in order. The strategy observes these events and reacts accordingly. This guarantees that the strategy's view of order state is always consistent with the execution engine's view.
ORDER EVENT SEQUENCE:
OrderInitialized -> OrderSubmitted -> OrderAccepted -> OrderFilled
-> OrderRejected
-> OrderCanceled
-> OrderExpired
POSITION EVENT SEQUENCE (derived from order fills):
OrderFilled (new) -> PositionOpened
OrderFilled (add) -> PositionChanged
OrderFilled (close) -> PositionClosed
2. Callback Chain Pattern
The strategy defines handler methods that the framework calls in response to specific events. This creates a chain:
[Execution Engine]
|
v
[Order State Machine] --applies event--> [Updated Order]
|
v
[Message Bus] --routes event--> [Strategy.on_order_filled()]
[Strategy.on_position_opened()]
[Strategy.on_position_closed()]
Pseudocode:
CLASS Strategy:
FUNCTION on_order_filled(event: OrderFilled):
IF event is for an entry order:
PLACE stop-loss order at entry_price - stop_distance
PLACE take-profit order at entry_price + target_distance
LOG entry details
ELSE IF event is for an exit order:
LOG exit details and P&L
FUNCTION on_position_opened(event: PositionOpened):
LOG "Position opened: {event.position}"
UPDATE internal risk tracking
FUNCTION on_position_closed(event: PositionClosed):
LOG "Position closed: {event.position}"
RECORD realized P&L
RESET internal state for next trade
FUNCTION on_order_rejected(event: OrderRejected):
LOG warning "Order rejected: {event.reason}"
DECIDE whether to retry or abort
Key invariant: Position events are always preceded by the corresponding order fill event. The framework guarantees that on_order_filled is called before on_position_opened/on_position_changed/on_position_closed for the same fill.