Module 08: Execution Engine — The Lifecycle of an OrderFrom initial submission to final execution report
1. Role of the Execution Engine
The ExecutionEngine is the order-management control layer. It does not communicate directly with external exchanges; instead, it routes commands via the ExecutionClient adapter layer.
flowchart LR
subgraph input["📝 Command Input"]
direction TB
submit["SubmitOrder"]
cancel["CancelOrder"]
modify["ModifyOrder"]
end
ee["⚙️ ExecutionEngine<br/>Central Command Hub"]
subgraph output["⚡ Event Output"]
direction TB
accepted["OrderAccepted"]
filled["OrderFilled"]
rejected["OrderRejected"]
end
subgraph adapt["🔌 Adapters & Exchanges"]
direction TB
binance["Binance Client"]
ib["IB Client"]
sim["Simulator"]
end
input ==> ee
ee ==> adapt
adapt ==> ee
ee ==> output
style ee fill:#0f1419,stroke:#4fc3f7,stroke-width:2px
style input fill:#0f1419,stroke:#ab47bc,stroke-width:1px
style output fill:#0f1419,stroke:#ef5350,stroke-width:1px
2. The Full Order Lifecycle
sequenceDiagram
participant S as 🎯 Strategy
participant RE as 🛡️ RiskEngine
participant EE as ⚙️ ExecutionEngine
participant EC as 🔌 ExecutionClient
participant EX as 🏦 Exchange
participant Cache as 💾 Cache
participant Port as 💰 Portfolio
S->>RE: SubmitOrder(Market BUY 1 BTC)
Note over RE: Risk Check Passed ✅
RE->>EE: Forward Command
EE->>EE: Emit OrderSubmitted Event
EE->>Cache: Update State → SUBMITTED
EE->>EC: Route to Binance Adapter
EC->>EX: REST API Order Placement
EX-->>EC: Order Acceptance Confirmation
EC->>EE: OrderAccepted Event
EE->>Cache: Update State → ACCEPTED
EX-->>EC: Execution Report
EC->>EE: OrderFilled Event
EE->>Cache: Update State → FILLED
EE->>Port: Update Position & PnL
EE->>S: Broadcast Fill Notification (via MessageBus)
3. Order Command API
The following are the most frequently used order operations within a strategy:
# Market Order — Immediate Execution
order = self.order_factory.market(
instrument_id=btc_usdt_id,
order_side=OrderSide.BUY,
quantity=Quantity.from_str("0.01"),
)
self.submit_order(order)
# Limit Order — Resting Liquidity
order = self.order_factory.limit(
instrument_id=btc_usdt_id,
order_side=OrderSide.BUY,
quantity=Quantity.from_str("0.01"),
price=Price.from_str("48000.00"),
time_in_force=TimeInForce.GTC,
)
self.submit_order(order)
# Stop Market Order — Loss Mitigation
order = self.order_factory.stop_market(
instrument_id=btc_usdt_id,
order_side=OrderSide.SELL,
quantity=Quantity.from_str("0.01"),
trigger_price=Price.from_str("45000.00"),
)
self.submit_order(order)
# Cancel Order
self.cancel_order(order)
# Modify Order (Price or Quantity Update)
self.modify_order(order, price=Price.from_str("47500.00"))
# Cancel All Orders
self.cancel_all_orders(instrument_id=btc_usdt_id)4. Contingency Orders
NautilusTrader supports three types of order contingency strategies:
OTO — One Triggers Other
When Order A executes, Order B is automatically triggered.
Example: Automatically placing a stop-loss after a long entry.
OCO — One Cancels Other
If either Order A or B is executed, the other is automatically canceled.
Example: Stop-loss and take-profit brackets triggering mutually exclusive execution.
OUO — One Updates Other
When Order A partially executes, the quantity of Order B is automatically updated.
Example: Dynamically matching stop-loss quantity with the open position size.
5. Simulated Exchange
In backtesting and sandbox environments, the ExecutionClient interfaces with a SimulatedExchange rather than a live venue:
| Feature | Simulated Exchange | Live Exchange |
|---|---|---|
| Matching Engine | Built-in matching logic | Exchange’s matching engine |
| Latency Simulation | Configurable fixed latency | Live network latency |
| Commissions | Calculated via configuration models | Actually charged by the exchange |
| Slippage | Configurable slippage models | Live market slippage (adverse selection) |
| Partial Fills | Simulated based on order book depth | Live market depth queue execution |
6. Interactive Exercise
You want to buy BTC at 50,000, while simultaneously setting a stop-loss at 48,000 and a take-profit at 55,000 (where the execution of one cancels the other). Which order types and contingency structures should you use?
Steps:
- Place a Limit BUY Order @ 50,000 (Master Order).
- Configure an OTO condition: The execution of the Master Order triggers the following two child orders.
- Child Order A: Stop Market SELL @ 48,000 (
StopMarketOrder). - Child Order B: Limit SELL @ 55,000 (
LimitOrder). - Configure an OCO link between Child Orders A and B: The execution of either will automatically cancel the other.
💡 This represents the classic “entry + stop-loss + take-profit” trio, commonly referred to as a Bracket Order.
7. Module Key Takeaways
- Execution Engine: Manages the entire lifecycle of all orders without interfacing directly with exchanges.
- Commands → Routing → Events: Strategies submit commands, the engine routes them to adapters, and adapters report execution events.
- Contingency Orders: Supports OTO (trigger), OCO (cancel), and OUO (update) mechanisms for advanced logic.
- Simulated Exchange: Fully emulates live exchange matching dynamics during backtesting.
- Order Factory: Orders must be constructed exclusively using
self.order_factory.