NautilusTrader
ConceptsExecution
These docs track the unreleased nightly build and may change without notice. Switch to the latest stable docs.

Execution Policies

NautilusTrader coordinates local state with trading venues across a distributed boundary. This page defines the policies that govern order commands, order events, persistence, and reconciliation, including their documented behavior and known limits. Use it when interpreting an order state, implementing an execution adapter, or designing live recovery procedures.

For the component and routing model, see Execution. For every order status and the primary state transitions, see Orders.

Policy summary

BoundaryBehaviorLimit
Order stateEach applied event must satisfy the order state machine and identity checks.A status alone does not identify whether venue evidence or reconciliation produced it.
Command outcomeAdapters distinguish definitive local failures, definitive venue results, and unknown outcomes.A transport result does not necessarily prove what the venue did.
Command deliveryAdapters retry state-changing commands only when repeating the same request is safe.NautilusTrader does not guarantee exactly-once delivery across the venue boundary.
Event applicationOrder identity and transition checks reject invalid events; fills reject a repeated trade_id.No blanket exactly-once guarantee applies to every event type or across lost retained state.
Persistence before sendThe cache enqueues the order and resolved execution-client origin before calling the client.The built-in cache backends do not wait for durable storage before the client can send.
Bounded recoveryReconciliation recovers reported order state without applying unsupported fill economics.Partial history does not prove historical position economics, realized PnL, or average price.
Terminal policyReconciliation may resolve missing or timed-out orders after configured retries.A policy resolution is not a venue-confirmed rejection or cancellation.

Order state

Orders are event sourced. Every order starts with OrderInitialized, and OrderCore::apply validates the event against the order identity and the transition allowed from its present status. It rejects an invalid transition or a repeated fill trade_id before changing the order, then appends each accepted event to the order's event history.

The order state flow shows the primary lifecycle. The model also accepts selected recovery and real-world edge cases, including fills received while a command is pending and late fills for canceled orders. Each event page under Events documents its fields and typical transition.

Ordering

Within one live node, the runner handles each selected message branch to completion before it selects another. This serializes kernel-side order mutation. The order appends each accepted event in application order and does not reorder its history by event timestamp.

When several channels are ready, the runner's priority determines which it handles next. Events from independent adapter tasks or venues can therefore interleave, and event timestamps do not define a global FIFO order. See Dispatch priority and overload behavior.

Duplicate application

NautilusTrader does not use event_id as a universal order-level deduplication key and does not guarantee exactly-once application for every order event. Its narrower protections are:

  • An order rejects a second fill with the same trade_id.
  • The execution engine prevents the same trade_id from being applied again to the target position.
  • Fill voids use the original trade_id and reject duplicate, stale, conflicting, or excessive cumulative corrections.
  • Other repeated lifecycle events must still pass the state transition. Some state-preserving updates and repeated pending requests are valid events and can be appended again.

These checks depend on the order and position evidence retained in the cache. Restored state keeps its earlier trade IDs and event history available after restart. If that state and the required venue history are absent, NautilusTrader cannot infer exactly-once application from the missing evidence. Reports that describe one logical fill with different trade IDs remain distinct and are subject to the normal overfill and integrity checks.

The optional event store has a separate boundary. Its capture adapter deduplicates repeated dispatches of one message identity within a bounded recent window, and replay applies each stored sequence entry once. This does not make an uncommitted capture durable or make venue delivery exactly once.

Command outcomes

Execution commands resolve according to the evidence available:

EvidenceMeaningResult
Definitive local failureValidation proves that the command was not sent.Denies a submit or rejects a modify or cancel when the failure is attributable to that command.
Definitive venue resultThe matching engine or venue explicitly confirms the outcome.Applies the corresponding accepted, updated, canceled, or rejected event.
Unknown live outcomeThe command may have reached the venue, but no result is known.Keeps the command in flight for stream updates, polling, queries, or reconciliation.

The failure event depends on the command and when the failure becomes definitive:

CommandEventMeaning
Submit or submit order listOrderDeniedLocal checks prevent submission; no OrderSubmitted event is emitted.
Submit or submit order listOrderRejectedThe submit entered execution and was later proven unsuccessful.
ModifyOrderModifyRejectedThe requested modification was proven unsuccessful.
Cancel, cancel-all, or batch cancelOrderCancelRejectedThe requested cancellation was proven unsuccessful.

For modify or cancel preparation, NautilusTrader emits the matching rejection only when the failure is attributable to that command and proves it was not sent. Otherwise, it logs the failure without inventing an outcome.

A successful batch response can still contain definitive per-order failures. A whole-request failure without per-order evidence does not prove that every child command failed.

Unknown live outcomes

Transport errors, timeouts, disconnects, task cancellation, exhausted adapter request retries, missing acknowledgements, and parse failures after transmission usually leave the venue outcome unknown. HTTP status codes and rate limits are definitive only when venue-specific semantics prove that the command was not accepted.

An in-flight order is awaiting resolution:

  • SUBMITTED: Initial submission awaiting acceptance or rejection.
  • PENDING_UPDATE: Modification awaiting confirmation.
  • PENDING_CANCEL: Cancellation awaiting confirmation.

Delivery and retry limits

A request can reach a venue even when its response is lost. NautilusTrader therefore does not make a broad exactly-once delivery claim for submit, modify, or cancel commands.

An adapter may retry a state-changing command only when the venue protocol makes repetition safe, such as through stable request identity and duplicate detection or idempotent semantics for the same target. Otherwise, the adapter sends once and uses stream updates, queries, polling, or reconciliation to resolve an unknown outcome.

Retryability and command outcome are separate. A failure can be safe to retry while still leaving the earlier attempt ambiguous. Once an attempt may have reached the venue, a later failure remains ambiguous unless authoritative evidence resolves the same semantic command.

Persistence before transport

Creating a client order ID, publishing OrderInitialized, and sending SubmitOrder are in-process actions. They do not by themselves confirm durable storage.

For a submission handled by the built-in execution engine:

  1. The order exists in the cache with its ClientOrderId and OrderInitialized event before the final execution-client call.
  2. The engine selects and validates the execution client.
  3. The cache enqueues the resolved order-to-client origin for persistence, then updates the in-memory origin index.
  4. The engine calls the selected ExecutionClient.
  5. The cache backend processes its queued writes independently of venue transport and acknowledgement.

The enqueue steps fail before the client call when the cache backend cannot accept them. Successful enqueue does not mean the backing store has committed the order or origin. The built-in Redis and PostgreSQL cache backends process these writes asynchronously.

The final step is only the call into the adapter's ExecutionClient. The adapter owns the later wire send and maps venue responses or stream updates to order events. Neither a successful client call nor an OrderSubmitted event proves venue acceptance.

Persistence gap

A process failure can therefore occur after the venue receives an order but before the local order and origin become durable. Startup reconciliation can recover that order when the venue reports it, but incomplete venue history can leave the node without enough evidence to reconstruct the full execution history.

The optional event store also captures asynchronously and does not gate message dispatch on durable commit. Live restart continues to use restored cache state plus venue reconciliation.

Reconciliation authority

The cached order event stream is the source of local derived order state. During live recovery, adapter reports provide the venue evidence used to align that state. Reconciliation applies the reports in order-status, fill, and position phases so position checks build on the reconciled order and fill state.

Recovery means restoring available cached state, reconciling available venue reports, and holding the strategy-start barrier until startup reconciliation finishes. It does not prove that the venue returned complete history or that every unknown command outcome was resolved.

An explicitly bounded report set changes NETTING position and portfolio economics only when the reports are complete and coherent, retained state is compatible, and replay matches one authoritative position report. Otherwise, NautilusTrader updates the reported order state without applying the unsupported fill to a position or portfolio. See Bounded history safety.

Reports for orders absent from the cache can create external orders. Active claims assign an external order to a strategy; unclaimed orders use the EXTERNAL strategy. See External order creation.

External orders and fills still participate in position tracking and portfolio calculations when their evidence passes the same reconciliation rules. The bounded-history safeguards apply whether or not a strategy claims the activity.

Startup reconciliation runs before trader components start. A startup failure stops the node from starting unless a documented compatibility path handles that specific condition.

Terminal reconciliation provenance

The reconciliation field identifies an event generated through reconciliation. It does not by itself distinguish a venue status report from a local policy resolution:

Evidence pathPrior statusTerminal eventAvailable event provenance
Explicit venue status reportAny transition allowed by the modelOrderRejected/OrderCanceledreconciliation=true; a rejection keeps the reported reason, or UNKNOWN when none is reported.
In-flight retry exhaustionSUBMITTEDOrderRejectedreconciliation=true, reason INFLIGHT_TIMEOUT.
In-flight retry exhaustionPENDING_UPDATE/PENDING_CANCELOrderCanceledreconciliation=true; the event has no reason field.
Full-history order remains missing after retries and targeted querySUBMITTED/ACCEPTEDOrderRejectedreconciliation=true, reason NOT_FOUND_AT_VENUE.
Full-history order remains missing after retries and targeted queryPARTIALLY_FILLEDOrderCanceledreconciliation=true; the event has no reason field.

Local terminal state is not venue confirmation

The first row is backed by an explicit venue status. The remaining rows restore a terminal local state after an operator-configured retry policy expires. They do not prove that the venue rejected the submit or canceled the working order.

OrderCanceled has no reason field, so the event alone cannot distinguish a venue-reported cancellation from the two synthetic reconciliation paths. Consumers that require that distinction must preserve the associated reconciliation inputs and operational logs. The optional event store captures raw venue reports when enabled, but no OrderCanceled field carries the policy reason.

See Runtime checks for query coordination, recent-order protection, and missing-order behavior.

On this page