Skip to content

Convert daily resolution market orders to MarketOnClose/MarketOnOpen#9534

Merged
Martin-Molinero merged 5 commits into
QuantConnect:masterfrom
Martin-Molinero:bug-daily-resolution-scheduled-events
Jun 16, 2026
Merged

Convert daily resolution market orders to MarketOnClose/MarketOnOpen#9534
Martin-Molinero merged 5 commits into
QuantConnect:masterfrom
Martin-Molinero:bug-daily-resolution-scheduled-events

Conversation

@Martin-Molinero

@Martin-Molinero Martin-Molinero commented Jun 16, 2026

Copy link
Copy Markdown
Member

Description

A market order placed intraday — for example through a scheduled event — on an asset subscribed only at daily resolution has no fresh intraday price to fill against, so it was filling at the stale previous daily close. This is a common footgun when mixing daily resolution assets with minute resolution assets or intraday scheduled events.

QCAlgorithm.MarketOrder now converts these orders so they fill at a real daily open/close instead of the stale previous close:

Situation Behavior
Market closed (any resolution) MarketOnOpen (unchanged)
Market open, daily-only subscription, before MOC buffer MarketOnClose (today's close)
Market open, daily-only subscription, inside the MOC submission buffer near the close MarketOnOpen (next open)
Market open, asset has intraday data plain Market (unchanged)

Notes:

  • Even right after the open (e.g. 09:31) only the previous daily close is available, so the order is still converted.
  • The conversion is applied in backtesting only. In live trading an open-market market order fills at the real current price, so it is left as a regular market order.
  • Two distinct one-time warning messages inform the user about each conversion case.

Related Issue

Daily/Hour resolution market orders (and orders placed from intraday scheduled events) filling at a stale previous close.

Motivation and Context

Filling at a stale previous close silently mis-prices fills for daily resolution strategies, especially when combined with intraday scheduling or mixed-resolution universes. Routing these to MarketOnClose/MarketOnOpen produces a realistic daily open/close fill.

Requires Documentation Change

No public API change. New behavior is described via the algorithm warnings.

How Has This Been Tested?

Added DailyResolutionMarketOrderConversionRegressionAlgorithm (daily SPY + minute IBM) asserting:

  • 09:31 (right after open): daily order → MarketOnClose; minute order is not converted and fills immediately.
  • 15:55 (inside the MOC buffer near close): daily order → MarketOnOpen, filling next session.
  • Per-order fill-time and all-filled assertions.

Ran locally end-to-end (3 orders, both conversion warnings observed, all assertions pass).

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My code follows the code style of this project.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Regression statistics updated

The conversion changes the fills of a few existing daily-resolution algorithms that place market orders intraday. All are legitimate improvements (orders no longer fill at the stale previous close), the in-algorithm assertions still pass, and only the affected fills/statistics changed:

  • IndexOptionCallITMExpiryDailyRegressionAlgorithm / IndexOptionCallOTMExpiryDailyRegressionAlgorithm — the SPX index option entry is bought via MarketOrder one minute after the open. On daily resolution this previously filled at the stale previous close; it now converts to MarketOnClose and fills at the daily close. Same economics (End Equity unchanged), one extra data point, new OrderListHash.
  • AllShortableSymbolsCoarseSelectionRegressionAlgorithm (C# and Python) — places MarketOrders on daily-resolution coarse-selected symbols. An intraday order's type changes (Market → converted); End Equity and all other statistics are identical, only the OrderListHash changed.
  • ResolutionSwitchingAlgorithmSamplesNotMisalignedAbsolute (Tests/Engine/Results/BacktestingResultHandlerTests.cs) — a sampling change-detector. The algorithm's RemoveSecurity liquidation fires at 15:50 while the market is open; on daily resolution it previously filled at the stale previous close and now converts, shifting the equity/performance samples (benchmark samples unchanged). Expected sample values were updated accordingly.

Markets that never close (crypto/forex) and futures are excluded from the conversion, and the conversion is not applied in live trading.

🤖 Generated with Claude Code

Martin-Molinero and others added 5 commits June 16, 2026 10:44
A market order placed intraday (e.g. through a scheduled event) on an
asset subscribed only at daily resolution has no fresh intraday price to
fill against, so it was filling at the stale previous daily close. This
is common when mixing daily resolution assets with minute resolution
assets or intraday scheduled events.

QCAlgorithm.MarketOrder now converts these orders so they fill at a real
daily open/close instead of the stale previous close:
 - market closed (any resolution): MarketOnOpen, as before
 - market open, daily-only subscription: MarketOnClose (today's close),
   or MarketOnOpen (next open) when already within the MarketOnClose
   submission buffer near the close

Assets with intraday data are left untouched, and the conversion is only
applied in backtesting; in live trading an open-market market order fills
at the real current price.

Adds DailyResolutionMarketOrderConversionRegressionAlgorithm covering the
MarketOnClose and MarketOnOpen conversion paths plus a minute resolution
asset that is correctly left as a regular market order.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rrent price"

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Daily-resolution market orders placed intraday are now converted to
MarketOnClose/MarketOnOpen so they fill at a real daily open/close
instead of the stale previous close. This shifts the affected fills:

 - IndexOptionCall{ITM,OTM}ExpiryDaily: the SPX option entry, placed one
   minute after the open, now fills at the daily close. Same economics,
   one extra data point and a new order list hash.
 - AllShortableSymbols (C# + Python): an intraday order's type changed
   from Market to a converted order; identical End Equity, new hash.
 - ResolutionSwitchingAlgorithm sampling test: the RemoveSecurity
   liquidation (fired at 15:50) previously filled at the stale previous
   close; it now converts, shifting the equity/performance samples.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Martin-Molinero Martin-Molinero merged commit 62d6301 into QuantConnect:master Jun 16, 2026
7 of 8 checks passed
@Martin-Molinero Martin-Molinero deleted the bug-daily-resolution-scheduled-events branch June 16, 2026 16:09
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