Skip to content

Fail loudly on canonical continuous future orders, add Future.Canonical and mapped-contract guidance - #9681

Draft
jhonabreul wants to merge 1 commit into
QuantConnect:masterfrom
jhonabreul:feature-futures-canonical-mapped-ergonomics
Draft

Fail loudly on canonical continuous future orders, add Future.Canonical and mapped-contract guidance#9681
jhonabreul wants to merge 1 commit into
QuantConnect:masterfrom
jhonabreul:feature-futures-canonical-mapped-ergonomics

Conversation

@jhonabreul

@jhonabreul jhonabreul commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Description

Ordering the canonical continuous futures symbol fails silently: CalculateOrderQuantity(canonical, 1.0) returns a plausible quantity, and SetHoldings(canonical, 0.5) submits an order rejected with only:

The security with symbol '/ES' is marked as non-tradable.

Related traps: Future.Mapped is null during Initialize, so passing it to order methods dies with a bare NRE; stop/limit prices computed from adjusted continuous prices sit far from the mapped contract's raw prices.

Cause: nothing on the canonical order path names the problem or points to Future.Mapped, and the buying power path computes quantities for a security that can never trade.

The fix:

  • PortfolioTarget.Percent rejects canonical future symbols with an instructive error and returns null, so CalculateOrderQuantity returns 0 and SetHoldings no longer submits doomed orders. Restricted to futures.
  • QCAlgorithm.PreOrderChecksImpl non-tradable rejection now uses Messages.QCAlgorithm.CanonicalSymbolNotTradable for canonical symbols, telling the user to trade Future.Mapped. Messages are language-aware for Python.
  • QCAlgorithm.GetSecurityForOrder throws ArgumentNullException with the same guidance for null symbols instead of an opaque NRE. Covers all order helpers.
  • Future.Canonical added as an alias of Symbol.Canonical (future.canonical in Python); Future.Mapped XML docs now state it is null until the first universe selection.
  • PreOrderChecksImpl warns once when a future order's stop/limit/trigger price deviates more than 10% from market price while the continuous subscription uses a non-Raw DataNormalizationMode.
  • SignalExportTargetTests future cases switched from holdings on the canonical security (now rejected) to a real ES contract.

Not changed: slice.Bars lookups with the canonical symbol already resolve the continuous bar (asserted in the regression algorithm).

Related Issue

N/A

Note: sibling PR #9675 covers the null-symbol NRE in AddConsolidator/GetSubscription; this PR covers the order path.

Motivation and Context

The silent canonical-order failure is especially costly to debug. Loud, named errors close the worst silent failure mode in futures algorithms.

Requires Documentation Change

No — error messages and a new property alias.

How Has This Been Tested?

  • New regression algorithm ContinuousFutureCanonicalOrdersRegressionAlgorithm (C# + Python): asserts the new errors and null/zero results end-to-end, that canonical bars still resolve, and that the mapped contract trades normally.
  • New AlgorithmTradingTests covering canonical order rejection, zero order quantity, null-symbol guidance, and the price-deviation warning (fires once for non-Raw, never for Raw or near-market prices).
  • PortfolioTargetTests.PercentReturnsNullForCanonicalFutureSymbol.
  • Suites: AlgorithmTradingTests + all Framework.Portfolio tests: 813 passed, 0 failed. ContinuousFuture*/FuturesFramework* regression algorithms: all passed.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactor (non-breaking change which improves implementation)
  • Performance (non-breaking change which improves performance. Please add associated performance test and results)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Non-functional change (xml comments/documentation/etc)

Breaking only narrowly: PortfolioTarget.Percent/CalculateOrderQuantity now return null/0 with an error for canonical future symbols instead of a quantity that could not be traded anyway.

Checklist:

  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My branch follows the naming convention bug-<issue#>-<description> or feature-<issue#>-<description>

…nical

- PortfolioTarget.Percent rejects canonical future symbols with an
  instructive error, so CalculateOrderQuantity returns 0 with a clear
  message and SetHoldings no longer submits doomed orders
- Non-tradable order rejections for canonical symbols now point to
  Future.Mapped and explain it is not set until after Initialize
- Order methods throw a named ArgumentNullException for null symbols
  (common case: ordering Future.Mapped from Initialize) instead of NRE
- Add Future.Canonical as an alias of Symbol.Canonical
- Warn once when a future stop/limit/trigger price deviates more than
  10% from the contract market price while the continuous subscription
  uses a non-Raw data normalization mode
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant