Nautilus Dev - Execution Testing Spec

Nautilus’s developer-guide page “Execution Testing Spec” defines a rigorous, ID-prefixed test matrix (TC-E01..TC-E101) that every ExecutionClient adapter must pass to be considered baseline-compliant. The matrix is driven by a generic ExecTester strategy (Python: nautilus_trader.test_kit.strategies.tester_exec; Rust: nautilus_testkit::testers) that exercises ten functional groups - market orders, limit orders, stop/conditional orders, modification, cancellation, brackets, order flags, rejection handling, lifecycle (start/stop including reconcile-from-prior-session), and options trading. Tests are skipped per documented adapter capability rather than per the framework’s surface area, so an adapter passes a subset of the matrix matching its supported order types, TIFs, actions, and flags. Cortana does NOT author a new ExecutionClient - it consumes the shipped IBKR adapter (nautilus_trader[ib]) - so day-1 use of this spec is verification of IBKR-exec behaviors, not authoring a fresh test suite. The page is filed as reference for: (a) running ExecTester against the IBKR paper Gateway during the spike to baseline what works; (b) authoring Cortana-specific exec tests that piggyback on the framework’s ExecTesterConfig parameter surface (OCA IBOrderTags, emulated bracket TP/SL on MARK_PRICE, reconcile-on-startup with open positions); (c) future MK4+ paper-exec wrapper around UW (unlikely, but the spec applies if it ever happens).

Cortana orientation

This is a medium-relevance reference, not a build target. Cortana’s day-1 use of the spec is reading the IBKR adapter’s capability matrix (documented in the IBKR adapter guide, cross-referenced from nautilus-ib.md) and confirming that the ExecTester test cases that map to Cortana’s actual order shapes (market entry, emulated-bracket TP/SL, OCA-tagged exits, reconcile-on-startup of an open SPY 0DTE position) all green on paper before MK3 cutover. We verify; we do not author a new ExecutionClient.

If MK4+ ever introduces a paper-exec wrapper around UW (the documented “data-only adapter” sketch in nautilus-adapters.md extended into an exec adapter - currently no plan), this spec becomes the authoring contract.

Reference: the test matrix shape

The spec is organized as ten groups of identified test cases. Each group has a summary table (TC ID, name, description, skip-when condition), then per-test “test cards” with Prerequisite, Action, Event sequence, Pass criteria, Skip when, and (where relevant) adapter-specific Considerations, plus Python and Rust config snippets driving the ExecTester strategy.

Test IDs use spaced numbering (TC-E01..TC-E06 then TC-E10..TC-E19 then TC-E20..TC-E27, etc.) so new tests can be inserted into a group without renumbering downstream IDs. An adapter passes groups 1-5 to be “baseline compliant.” Groups 6-10 add capabilities that not all venues support.

The ten groups

GroupCoverageBaseline?
1 - Market ordersTC-E01..TC-E06 - submit-and-fill BUY/SELL, IOC TIF, FOK TIF, quote-qty, close-position-on-stop.yes
2 - Limit ordersTC-E10..TC-E19 - GTC BUY/SELL, BUY+SELL pair, IOC aggressive/passive, FOK fill/no-fill, GTD accept + expiry, DAY.yes
3 - Stop and conditionalTC-E20..TC-E27 - STOP_MARKET BUY/SELL, STOP_LIMIT BUY/SELL, MIT BUY/SELL, LIT BUY/SELL.yes
4 - Order modificationTC-E30..TC-E36 - modify-price for limit + stop, cancel-replace for limit + stop, modify-rejected on adapter-no-modify-support.yes
5 - Order cancellationTC-E40..TC-E44 - cancel single, cancel-all-on-stop, individual cancels on stop, batch cancel on stop, cancel-already-canceled (rejection).yes
6 - Bracket ordersTC-E50..TC-E53 - bracket BUY (entry+TP+SL), bracket SELL, entry-fill activates TP/SL, bracket with post-only entry.optional
7 - Order flagsTC-E60..TC-E63 - PostOnly accepted, ReduceOnly on close, display-qty / iceberg, custom adapter order_params.optional
8 - Rejection handlingTC-E70..TC-E73 - PostOnly rejection (would-cross), ReduceOnly rejection (no position), unsupported order type → OrderDenied, unsupported TIF → OrderDenied.optional
9 - Lifecycle (start/stop)TC-E80..TC-E87 - open-position-on-start, cancel-orders-on-stop, close-positions-on-stop, unsubscribe-on-stop, reconcile open orders / filled orders / open long / open short from a prior session.optional
10 - Options tradingTC-E90..TC-E101 - limit BUY/SELL on a CryptoOption, alt-pricing via order_params (e.g., OKX px_usd / px_vol), unsupported-order-type denial, conditional-order rejection on options, FOK limit option, cancel option order, reconcile option position.optional

Required preconditions across all groups

The spec page enumerates these prerequisites verbatim:

  1. Demo / testnet account with valid API credentials (preferred, not required).
  2. Account funded with sufficient margin for the test instrument and quantities.
  3. Target instrument available and loadable via the InstrumentProvider.
  4. Environment variables set - {VENUE}_API_KEY, {VENUE}_API_SECRET (or sandbox variants).
  5. Demo / production key separation - venue demo and production keys are typically separate and not interchangeable; using the wrong credentials produces HTTP 401.
  6. Risk engine bypassed - LiveRiskEngineConfig(bypass=True) to avoid interference with the test path.
  7. Reconciliation enabled - LiveExecEngineConfig(reconciliation=True) to verify state consistency on (re)connect.

Plus a basic smoke test that runs before any matrix work: open a position with a market order on start, place a buy + sell post-only limit pair, idle 30 seconds, stop (cancelling open orders, closing the position). Smoke pass = no errors, position opened + closed cleanly, limit orders acknowledged.

Reference: required exec-test categories (verbatim from the spec)

Compiled into a single list for cross-referencing into the brain. The spec demands an adapter exercise these behaviors:

  • Order submission - market BUY/SELL, limit BUY/SELL, stop-market BUY/SELL, stop-limit BUY/SELL, MIT BUY/SELL, LIT BUY/SELL, trailing-stop variants (trailing-stop coverage is mentioned in the general Nautilus orders taxonomy but the dev spec page focuses on the non-trailing conditional types listed above).
  • Order modification - native modify (OrderPendingUpdateOrderUpdated) when supported; cancel-replace fallback (OrderPendingCancelOrderCanceled → new OrderInitializedOrderSubmittedOrderAccepted) always.
  • Order cancellation - single, cancel-all-on-stop, individual cancels on stop, batch cancel on stop, cancel-already-canceled rejection (OrderCancelRejected).
  • Fills - full fill, partial fill (cumulative-qty check), close via market on stop, close via reduce-only on stop.
  • Rejections - OrderRejected (venue-side) for PostOnly cross-the-spread and ReduceOnly with no position; OrderDenied (adapter-side, pre-submission) for unsupported order types and TIFs.
  • Reconcile-on-startup - open orders → OrderStatusReport per order with status ACCEPTED; filled orders → FillReport per historical fill with price/qty/commission; open long position → PositionStatusReport with LONG/qty/avg-entry; open short position → PositionStatusReport with SHORT/qty/avg-entry.
  • Partial fills - implicit across all groups; the spec’s consideration on TC-E01 reads “Partial fills are valid; verify the cumulative filled quantity matches the order quantity.”
  • OCO/OCA via brackets - entry + TP + SL contingent group; entry fill activates TP and SL; per-venue OCA-group activation mechanism may differ (some immediate-active, some via OCA group).
  • Brackets - enable_brackets=True, bracket_entry_order_type=OrderType.LIMIT|MARKET, bracket_offset_ticks=500 default for TP/SL distance.
  • Emulation behavior - emulation_trigger: TriggerType? parameter on ExecTesterConfig; affects groups 2 (limit) and 3 (stop / conditional). Emulated orders run through the OrderEmulator pipeline per nautilus-orders.md.
  • Paper-exec equivalence - implicit in the prerequisites; the spec asserts that the test path is identical against demo/testnet, sandbox, and live. Per nautilus-execution.md: “Strategy code is identical across all three contexts.” The matrix is therefore the same for paper as for live; only credentials differ.

Reference: ExecTester strategy

Both Python and Rust ship a generic ExecTester Strategy whose behavior is fully driven by a typed ExecTesterConfig. The Strategy itself is not Cortana code - it is platform test infrastructure - but its config surface is the vocabulary for spec-driven adapter verification.

Python entry point

from nautilus_trader.common import Environment
from nautilus_trader.live import LiveExecEngineConfig, LiveNode, LiveRiskEngineConfig
from nautilus_trader.model import TraderId
 
node = (
    LiveNode.builder("TESTER-001", TraderId("TESTER-001"), Environment.SANDBOX)
    .with_risk_engine_config(LiveRiskEngineConfig(bypass=True))
    .with_exec_engine_config(LiveExecEngineConfig(reconciliation=True))
    .add_exec_client(None, adapter_exec_client_factory, exec_client_config)
    .build()
)
node.add_strategy_from_config(importable_strategy_config)

The spec note: “Legacy examples still use nautilus_trader.live.node.TradingNode, but new Rust-backed PyO3 adapters should prefer nautilus_trader.live.LiveNode. Use LiveNode.builder(...) when you need to register adapter client factories before the node is built.”

Rust entry point

use nautilus_testkit::testers::{ExecTester, ExecTesterConfig};
 
let tester_config = ExecTesterConfig::new(strategy_id, instrument_id, client_id, order_qty);
let tester = ExecTester::new(tester_config);
node.add_strategy(tester)?;
node.run().await?;

Reference example: crates/adapters/{adapter}/examples/node_exec_tester.rs.

ExecTesterConfig parameter surface

The page closes with a parameter reference - the knobs that drive which test cards each ExecTester run exercises:

ParameterTypeDefaultAffects groups
instrument_idInstrumentIdrequiredAll
order_qtyDecimalrequiredAll
order_display_qtyDecimal?None2, 7
order_expire_time_delta_minsPositiveInt?None2
order_paramsdict?None7, 10
client_idClientId?NoneAll
subscribe_quotes / subscribe_trades / subscribe_bookboolTrue / True / False-
book_type, book_depth, book_interval_ms, book_levels_to_print(book-related)L2_MBP / None / 1000 / 10-
open_position_on_start_qtyDecimal?None1, 9
open_position_time_in_forceTimeInForceGTC1
enable_limit_buys / enable_limit_sellsboolTrue2, 4, 5, 6
enable_stop_buys / enable_stop_sellsboolFalse3, 4
limit_time_in_forceTimeInForce?None2, 6
tob_offset_ticksPositiveInt5002, 4
stop_order_typeOrderTypeSTOP_MARKET3
stop_offset_ticksPositiveInt1003
stop_limit_offset_ticksPositiveInt?None3
stop_time_in_forceTimeInForce?None3
stop_trigger_typeTriggerType?None3
enable_bracketsboolFalse6
bracket_entry_order_typeOrderTypeLIMIT6
bracket_offset_ticksPositiveInt5006
modify_orders_to_maintain_tob_offsetboolFalse4
modify_stop_orders_to_maintain_offsetboolFalse4
cancel_replace_orders_to_maintain_tob_offsetboolFalse4
cancel_replace_stop_orders_to_maintain_offsetboolFalse4
use_post_onlyboolFalse2, 6, 7, 8
use_quote_quantityboolFalse1, 7
emulation_triggerTriggerType?None2, 3
cancel_orders_on_stopboolTrue5, 9
close_positions_on_stopboolTrue9
close_positions_time_in_forceTimeInForce?None9
reduce_only_on_stopboolTrue7, 9
use_individual_cancels_on_stopboolFalse5
use_batch_cancel_on_stopboolFalse5
dry_run, log_databoolFalse / True-
test_reject_post_onlyboolFalse8
test_reject_reduce_onlyboolFalse8
can_unsubscribeboolTrue9

The Affects groups column is what makes this a testing spec rather than just a config dump: each parameter is calibrated to drive a specific subset of the TC-E* matrix. Setting enable_brackets=True without also enabling at least one limit side is a misconfiguration; the spec’s per-card snippets show the correct combinations.

Group-by-group reference

Group 1 - Market orders

Six tests covering single-fill market submission. The canonical event sequence the spec demands:

OrderInitialized → OrderSubmitted → OrderAccepted → OrderFilled

Considerations the spec calls out:

  • “Some adapters simulate market orders as aggressive limit IOC orders (check adapter guide). The event sequence from the strategy’s perspective should be identical regardless of the venue mechanism.”
  • “Fill price should be within the recent bid/ask spread.”
  • “Partial fills are valid; verify the cumulative filled quantity matches the order quantity.”

For Cortana, this is the entry-leg behavior (V1 uses MARKET entries on the bracket parent per nautilus-ib.md). TC-E01

  • TC-E06 are the binding subset - open and close.

Group 2 - Limit orders

Ten tests covering GTC, IOC (aggressive vs passive), FOK (fill vs no-fill), GTD (accept + expiry), and DAY. The spec’s TIF coverage map:

TCTIFExpected terminalNotes
TC-E10GTC BUYACCEPTED (open)passive; verify in cache with OrderStatus.ACCEPTED
TC-E11GTC SELLACCEPTED (open)mirror of TC-E10
TC-E12GTC BUY+SELLboth ACCEPTEDindependent sequences
TC-E13IOC aggressiveOrderFilledcrosses immediately
TC-E14IOC passiveOrderCanceledvenue cancels unfilled IOC
TC-E15FOK aggressiveOrderFilled (single fill)full qty in one event
TC-E16FOK passiveOrderCanceledno partial allowed
TC-E17GTDACCEPTED with expiry timestampverify expiry field
TC-E18GTD expiredOrderExpiredwait for elapse; “Some venues may report expiry as a cancel; verify the adapter maps this to OrderExpired.”
TC-E19DAYACCEPTED (open through session)“DAY orders may behave differently on 24/7 crypto venues vs traditional markets.”

For Cortana on IBKR, DAY is the primary TIF - every order must be flat by close. GTD is acceptable when the expiry is < session end. GTC is forbidden in 0DTE strategy code (an invariant violation per nautilus-orders.md and nautilus-ib.md).

Group 3 - Stop and conditional orders

Eight tests, two per stop type (BUY + SELL each for STOP_MARKET, STOP_LIMIT, MIT, LIT). The spec emphasizes that “Verifying trigger and fill requires the market to move, which may not happen during the test” - the matrix tests acceptance, not trigger. Trigger behavior is venue-side and inherently non-deterministic during a short test window.

For Cortana, V1 uses STOP_MARKET as the SL bracket leg. TC-E20 (STOP_MARKET BUY) and TC-E21 (SELL) are the relevant cards.

Group 4 - Order modification

Seven tests. Two paths:

  1. Native modify - OrderPendingUpdateOrderUpdated. Adapter declares support; ExecTester drives via modify_orders_to_maintain_tob_offset=True (or stop variant).
  2. Cancel-replace fallback - universal. Spec verbatim: “This is the universal alternative when the adapter does not support native modify. Two distinct orders in the cache: the canceled original and the new replacement.” Driven via cancel_replace_orders_to_maintain_tob_offset=True.

TC-E36 (Modify rejected) tests the rejection path on adapters that don’t support modify. IBKR supports native modify, so this card is skipped for the IBKR adapter.

Group 5 - Order cancellation

Five tests - single cancel, cancel-all-on-stop, individual cancels on stop, batch cancel on stop, cancel-already-canceled rejection. Cortana’s market_exit() path triggers TC-E41 (Cancel all on stop) shape - multiple open orders, all canceled cleanly.

TC-E44 (Cancel already-canceled order) is the OrderCancelRejected path - adapter must reject cleanly, not error or no-op.

Group 6 - Bracket orders

Four tests. The spec’s Group 6 baseline shape:

  • TC-E50 (Bracket BUY): limit-buy entry + TP-sell + SL-sell, all three orders accepted (entry below bid, TP above ask, SL below entry).
  • TC-E51 (Bracket SELL): mirror of TC-E50.
  • TC-E52 (Entry fill activates TP/SL): spec note - “the TP/SL activation mechanism varies by venue (some activate immediately, some are OCA groups).” IBKR is the OCA-group case (per nautilus-ib.md - must explicitly set IBOrderTags(ocaGroup=..., ocaType=1)).
  • TC-E53 (Bracket with post-only entry): entry + TP both post-only; SL is not post-only.

Cortana V1 uses MARKET-entry brackets, so the bracket-cards as written (LIMIT entry default in bracket_entry_order_type) require adjustment to OrderType.MARKET to map.

Group 7 - Order flags

Four tests - PostOnly accepted, ReduceOnly on close, display-qty (iceberg), custom adapter order_params.

For Cortana, ReduceOnly on close (TC-E61) is the binding behavior. SL bracket leg must be reduce_only=True per nautilus-orders.md so a sizing or race bug cannot flip the position. The spec verifies the close path applies the flag.

Group 8 - Rejection handling

Four tests, split across two rejection origins:

  • Venue-side rejection (OrderRejected):
    • TC-E70 - PostOnly that would cross the spread.
    • TC-E71 - ReduceOnly with no position.
  • Adapter-side denial (OrderDenied), pre-submission:
    • TC-E72 - Unsupported order type.
    • TC-E73 - Unsupported TIF.

The distinction is load-bearing: OrderDenied is emitted by the adapter (or the RiskEngine) before the order leaves Nautilus; OrderRejected is emitted after the venue refuses. Both are typed events with reason strings - the spec ensures adapters route through the correct one.

Group 9 - Lifecycle (start/stop)

Eight tests. The reconciliation subset (TC-E84..TC-E87) is the core spec value for Cortana:

TCWhat’s reconciledReport variantPass criteria
TC-E84Open orders from prior sessionOrderStatusReportorder in cache with correct venue_order_id, status=ACCEPTED, price/qty/side/type
TC-E85Filled orders from prior sessionFillReportorder in cache with correct venue_order_id, status=FILLED, fill price/qty/commission
TC-E86Open long positionPositionStatusReportposition in cache with correct instrument, side=LONG, qty, avg-entry
TC-E87Open short positionPositionStatusReportposition in cache with correct instrument, side=SHORT, qty, avg-entry

Spec note for reconcile-cards: “Use external_order_claims to claim the instrument so the adapter reconciles orders for it… Verify that the reconciled order count matches the venue-reported count.”

This directly closes Cortana’s project_pm_ibkr_exit_invariant.md trust class - restart-with-open-position must rehydrate cache from broker truth (covered by nautilus-execution.md § Reconcile-on-startup; TC-E86/E87 are the test that the IBKR adapter implements that promise).

Group 10 - Options trading

Eight tests against a CryptoOption instrument. The spec headlines: “Options instruments typically have different constraints from linear derivatives: venues may restrict order types, support alternative pricing modes, or disallow conditional orders. Exact restrictions vary by venue; consult the adapter guide.”

The spec uses CryptoOption (Deribit / OKX style); IBKR equity options are documented separately on the adapter integration page. Cortana’s options use the IBKR adapter, so Group 10’s cards are pattern references - we’d implement Cortana-equivalents (SPY 0DTE option order acceptance, cancellation, reconcile) using the same shape but against IBKR’s OPT contracts.

Cortana MK3 implications - IBKR exec verification, not authoring

Day-1 use: confirm IBKR adapter passes the relevant subset

The IBKR adapter is platform code (nautilus_trader[ib]) maintained by the Nautilus team. It already passes the developer-spec matrix for the capabilities it declares. Cortana’s day-1 work is not re-running the matrix - it’s running the Cortana-specific subset that exercises the order shapes Cortana actually submits, against the IBKR paper Gateway, before MK3 cutover.

The Cortana-specific exec test plan (to be authored as a tests/ subtree post-spike if MK3 GO):

Cortana behaviorMaps to TCVerify
Market entry (bracket parent)TC-E01 / TC-E06OrderFilled within spread; close-on-stop submits opposite-side market
Bracket TP child (LIMIT)TC-E10 / TC-E11 + TC-E50Accept with OrderStatus.ACCEPTED; activates after entry fill (TC-E52)
Bracket SL child (STOP_MARKET)TC-E20 / TC-E21 + TC-E50Accept with correct trigger; activates after entry fill
OCA group on bracketTC-E50 + IBKR-specificTP+SL share ocaGroup; one fills, the other cancels (ocaType=1)
Emulated TP/SL on MARK_PRICETC-E10/E11/E20/E21 with emulation_trigger=MARK_PRICEOrder goes through EMULATEDRELEASED states; trigger fires locally
Reduce-only SLTC-E61SL has reduce_only=True; cannot flip the position
market_exit() cancel-all on stopTC-E41Multiple legs all canceled cleanly
Reconcile open SPY 0DTE position on restartTC-E86PositionStatusReport with LONG/qty/avg-entry; cache rehydrates correctly
Reconcile open TP/SL orders on restartTC-E84OrderStatusReport per leg; venue order IDs preserved
Cancel-already-canceled idempotencyTC-E44OrderCancelRejected not error

Spike-day Saturday actions (concrete):

  1. After the Step 1 / Step 2 plumbing is up, run the platform’s smoke-test config (open_position_on_start_qty=1 + post-only limit pair, 30-sec idle, stop) against IBKR paper Gateway. This is the spec’s basic-smoke pre-test.
  2. Run ExecTester with enable_brackets=True, bracket_entry_order_type=OrderType.MARKET, emulation_trigger= TriggerType.MARK_PRICE against an SPY 0DTE strike - exercises TC-E50 + TC-E52 + the OCA tag path.
  3. Restart the engine mid-trade with the bracket open - verify TC-E86 + TC-E84 emit reconciliation=True events that rehydrate the cache.

What Cortana does NOT do day-1

  • Author a new ExecutionClient. No plan for one. UW remains data-only per nautilus-adapters.md. IBKR adapter is consumed as-is.
  • Run the full TC-E01..TC-E101 matrix. The platform team owns that for the IBKR adapter. We run the Cortana subset only.
  • Test the TIF combinations Cortana doesn’t use. GTC, IOC, FOK are skipped for V1 strategy code - DAY is the only TIF Cortana emits.
  • Test options-specific cards (Group 10). Those are CryptoOption-shaped against Deribit/OKX. IBKR equity options go through the IBKR adapter’s own option path; the spec’s Group 10 is a pattern reference, not a literal test set.

MK4+ paper-exec wrapper around UW (hypothetical)

If MK4+ ever introduces a paper-exec wrapper around UW (extending the data-only adapter sketch to include exec), this spec becomes the authoring contract. The wrapper would need to:

  1. Implement the ExecutionClient contract per nautilus-execution.md § ExecutionClient.
  2. Pass the baseline (groups 1-5) of TC-E01..TC-E44.
  3. Declare a capability matrix in the wrapper’s adapter guide saying which order types, TIFs, and flags are supported (so the test matrix knows which cards to skip).
  4. Emit the four reconciliation report variants (OrderStatusReport, FillReport, OrderWithFills, PositionStatusReport) to satisfy TC-E84..TC-E87.

There is no plan to author a paper-exec wrapper around UW. Cortana’s existing UW pricing-source-of-truth posture per feedback_ibkr_pricing_source.md (UW for scoring/flow only; IBKR for pricing) explicitly excludes UW from the exec path. Filing this as a hypothetical only because the spec page would apply to it.

Standalone wins regardless of MK3 GO/NO-GO

Even if the spike says NO-GO on Nautilus migration, this spec is a useful reference for MK2’s own exec test design. The MK2 codepath could adopt the same shape - generic exec-driver strategy + typed config + TC-prefixed test cards - to systematize the IBKR exec behaviors we currently test ad-hoc. Not a priority pre-spike, but the structure is portable.

Caveats and gotchas

  • ExecTester requires LiveRiskEngineConfig(bypass=True). The spec is explicit. A meta-prob veto rule placed in the RiskEngine (per nautilus-execution.md § Custom RiskEngine rules) would interfere with ExecTester runs. Cortana-specific test runs that need both RiskEngine validation AND exec-spec coverage need a separate path (e.g., CortanaTester strategy that subclasses ExecTester plus a non-bypass risk config).
  • Demo / production credential separation. Spec calls out HTTP 401 from cross-using keys. IBKR paper account DUP696099 uses the same login as live but routes via paper port 4002; per-account auth still applies.
  • reconciliation=True is mandatory for Group 9 cards. Without it, TC-E84..TC-E87 cannot pass - the engine wouldn’t sync from broker truth on (re)start. This is the same flag Cortana needs set in production.
  • TC-E36 (Modify rejected) only applies to adapters without modify support. IBKR supports native modify (OrderUpdated); this card is skipped.
  • Test IDs use spaced numbering (TC-E01..TC-E06, TC-E10..TC-E19, TC-E20..TC-E27, etc.) for insertion without renumbering. Cortana-specific extensions should follow the same convention if/when we author a CortanaTester subclass.
  • Group 6 bracket cards default to LIMIT entry. Cortana V1 uses MARKET entry; map by setting bracket_entry_order_type=OrderType.MARKET.
  • Group 10 (Options) is CryptoOption-flavored. SPY equity options on IBKR follow a different code path; the spec’s options cards are pattern references, not literal IBKR-equity-option tests.
  • Some adapters simulate market as aggressive limit IOC. Spec note on TC-E01. The strategy-side event sequence is identical (OrderInitialized → OrderSubmitted → OrderAccepted → OrderFilled) but the adapter guide should disclose the mechanism.
  • GTD expiry mapping varies by venue. Spec note on TC-E18: “Some venues may report expiry as a cancel; verify the adapter maps this to OrderExpired.” For IBKR, GTD expiry should produce OrderExpired, not OrderCanceled.
  • DAY TIF on 24/7 venues. Spec note on TC-E19. Cortana on IBKR trades a session-bound venue, so DAY semantics are clean.
  • Smoke test ≠ matrix. The basic smoke test (open position + post-only limit pair + 30-sec idle + stop) is a sanity gate, not a compliance test. An adapter that passes smoke can still fail individual matrix cards.
  • Capability matrix lives in the adapter guide. The spec defers per-adapter capability declarations (which order types, TIFs, actions, flags) to each adapter’s own page - nautilus-ib.md for IBKR, future per-adapter pages for others.

When this concept applies

  • Reading the IBKR adapter’s exec-test posture before MK3 cutover.
  • Designing a Cortana-specific tests/exec/ subtree post-spike that exercises the TC-E* cards Cortana relies on (entries, brackets, OCA, emulation, reconcile).
  • Authoring a paper-exec wrapper around UW (hypothetical MK4+; no current plan).
  • Validating that the IBKR adapter’s reconciliation behavior (TC-E84..TC-E87) closes project_pm_ibkr_exit_invariant.md in practice, not just by design.
  • Sanity-checking custom ExecTester config combinations before running them against paper.
  • Cross-referencing per-test event sequences when reading reconciliation logs for the first time.

When it breaks / does not apply

  • General concepts (kernel, message bus, cache). Those live on the Concepts pages, not the developer guide.
  • Adapter authoring patterns. This spec is for exec verification, not adapter implementation. The adapter contract itself lives in nautilus-execution.md § ExecutionClient and the (parallel) nautilus-dev-adapters.md page being filed alongside this one.
  • Strategy authoring. ExecTester is the platform’s generic test strategy; Cortana’s CortanaStrategy is the production strategy. They overlap at the order-submission API surface but not in lifecycle posture.
  • Data-feed verification. That’s the sister spec - nautilus-dev-spec-data-testing.md (parallel agent) - which defines the equivalent ID-prefixed matrix for DataClient adapters. The two specs are siblings: data first, exec second (the exec spec verbatim says “Data connectivity should be verified first using the Data Testing Spec.”).
  • Regression / unit testing. This is integration-level verification against a live or paper venue; pure-Python unit tests for strategy logic live elsewhere (see nautilus-dev-testing.md parallel - testing standards page).
  • Performance / latency benchmarks. That’s the developer_guide/benchmarking/ page (next page in the dev guide nav).

See Also

  • Nautilus Dev - Adapters (parallel agent) - adapter authoring guide; the contract this spec verifies.
  • Nautilus Dev - Testing (parallel agent) - broader testing standards, unit / integration / fuzz tiers; this exec spec is the live-venue tier within that taxonomy.
  • Nautilus Dev - Spec Data Testing (parallel agent - sister spec) - DataClient matrix; “Data connectivity should be verified first using the Data Testing Spec” per this page’s prerequisites.
  • Nautilus Execution - ExecutionEngine, ExecutionClient contract, reconciliation reports, OMS, custom RiskEngine rules; the runtime context the matrix tests against.
  • Nautilus Orders - order-type taxonomy, TIFs, bracket primitive, emulation; the vocabulary ExecTester drives.
  • Nautilus Positions - position lifecycle, NETTING vs HEDGING; what TC-E86/E87 reconcile against.
  • Nautilus IB Integration - IBKR adapter capability matrix, OCA IBOrderTags requirement, fetch_all_open_orders, paper vs live differences. Cortana’s consumed exec adapter; the spec is verified against this adapter, not authored against it.
  • Nautilus Adapters - five-component adapter contract; UW data-only adapter sketch.
  • Nautilus Live - LiveNode.builder(...) entry point referenced in the spec’s Python setup snippet.
  • Nautilus Configuration - LiveExecEngineConfig, LiveRiskEngineConfig typed contracts.
  • 2026-05-09 Nautilus Spike Plan: ~/conductor/workspaces/cortanaroi-mk2/belo-horizonte/plans/2026-05-09-nautilus-spike.md
  • ~/.claude/projects/-Users-codysmith-conductor-workspaces-cortanaroi-cortanaroi-mk2/memory/project_pm_ibkr_exit_invariant.md
    • exit invariant the reconciliation cards (TC-E84..TC-E87) close in practice.
  • ~/.claude/projects/-Users-codysmith-conductor-workspaces-cortanaroi-cortanaroi-mk2/memory/feedback_dual_tp_defense_in_depth.md
    • emulated bracket TP/SL pattern that maps to Group 6 + Group 2 cards with emulation_trigger=MARK_PRICE.
  • ~/.claude/projects/-Users-codysmith-conductor-workspaces-cortanaroi-cortanaroi-mk2/memory/feedback_ibkr_pricing_source.md
    • UW remains data-only (excluded from any future exec wrapper authoring).
  • ~/.claude/projects/-Users-codysmith-conductor-workspaces-cortanaroi-cortanaroi-mk2/memory/reference_ibkr_api.md
    • IBKR TWS API master reference complementary to the IBKR adapter integration page.
  • Source: https://nautilustrader.io/docs/latest/developer_guide/spec_exec_testing/

Timeline

2026-05-07 | Cody - Filed during pre-spike concept mastery sweep batch 7 (developer guide).