Skip to content

Fix duplicate OnData when dynamically adding an at-expiry contract#9575

Open
jonathanwu906 wants to merge 1 commit into
QuantConnect:masterfrom
jonathanwu906:bug-9279-double-ondata-scheduled-add
Open

Fix duplicate OnData when dynamically adding an at-expiry contract#9575
jonathanwu906 wants to merge 1 commit into
QuantConnect:masterfrom
jonathanwu906:bug-9279-double-ondata-scheduled-add

Conversation

@jonathanwu906

@jonathanwu906 jonathanwu906 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Description

Adding a delistable contract (e.g. AddOptionContract) at/after its delisting date from inside a scheduled event caused OnData to fire twice at the same timestamp — the second slice carrying only a Delisting.Warning. This makes it fire once per period as expected.

Related Issue

Closes #9279

Motivation and Context

CorporateEventEnumeratorFactory always attaches a DelistingEventProvider for a CanBeDelisted() security. When the subscription starts on/after the delisting date (a near/at-expiry contract added dynamically, e.g. in a Schedule.On callback), the provider emits a DelistingType.Warning on its first tradable date, which arrives as a separate slice at the same time → the duplicate OnData.

The provider's date-based emission is intentional (covered by DelistingEnumeratorTests), so the fix is in the factory: skip the provider when the subscription starts on/after the delisting date.

Requires Documentation Change

No.

How Has This Been Tested?

  • New regression algorithm AddOptionContractInScheduledEventRegressionAlgorithm: fails without the fix (throws → RuntimeError), passes with it.
  • DelistingEnumeratorTests pass (provider unchanged); existing option/future delisting regressions produce identical OrderListHash.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

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>

Note for reviewers

A subscription starting on/after its delisting date now receives no delisting events (both Warning and Delisted). This looks correct for an already-expired asset — happy to only skip the Warning if you prefer.

Adding a delistable contract (e.g. via AddOptionContract) at or after its delisting date from inside a scheduled event caused DelistingEventProvider to emit a stale delisting warning immediately, producing a spurious extra slice and a second OnData call at the same time (GH QuantConnect#9279). CorporateEventEnumeratorFactory now only attaches a DelistingEventProvider when the subscription starts before the delisting date. Adds a regression algorithm that fails without the fix and passes with it.
@jonathanwu906

Copy link
Copy Markdown
Contributor Author

@Martin-Molinero this implements a fix for #9279, based on the cause you identified — a stale Delisting.Warning emitted immediately for a contract added at/after its delisting date.

The fix is in CorporateEventEnumeratorFactory: skip attaching the DelistingEventProvider when the subscription starts on/after the delisting date, leaving the provider's own (tested) date-based behavior untouched. I added a regression algorithm that fails without the fix and passes with it, and the existing option/future delisting regressions are unchanged (identical OrderListHash).

One design question: a subscription added at/after its delisting date now receives no delisting events (both Warning and Delisted). Happy to change it to skip only the Warning if you'd prefer.

Would appreciate a review when you have a chance — thanks!

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.

Double OnData Call When Add Subcription in Scheduled Event

1 participant