Skip to content

Fix OnAssignmentOrderEvent fired before portfolio has assigned shares#9334

Open
tsen1220 wants to merge 1 commit intoQuantConnect:masterfrom
tsen1220:bug-9321-assignment-event-before-portfolio-update
Open

Fix OnAssignmentOrderEvent fired before portfolio has assigned shares#9334
tsen1220 wants to merge 1 commit intoQuantConnect:masterfrom
tsen1220:bug-9321-assignment-event-before-portfolio-update

Conversation

@tsen1220
Copy link

@tsen1220 tsen1220 commented Mar 13, 2026

Description

EmitOptionNotificationEvents processed fills one at a time in a single foreach loop, firing HandlePositionAssigned (which triggers OnAssignmentOrderEvent) immediately after the option fill — before the underlying delivery fill was processed. This meant the assigned shares were not yet in the portfolio when the user's OnAssignmentOrderEvent / on_assignment_order_event() callback executed.

Split the single foreach into two passes: first process all fills via HandleOrderEvent to update the portfolio, then iterate again to fire assignment events. This ensures the underlying shares are in the portfolio and OnOrderEvent has already been called when OnAssignmentOrderEvent fires.

Both C# and Python algorithms are affected and fixed, since they share the same engine code path.

Related Issue

Fixes #9321

Motivation and Context

Users cannot reliably handle assignment in OnAssignmentOrderEvent (e.g. liquidate the delivered shares, open a new strategy) because the portfolio does not yet reflect the assigned position. The only workaround was to use OnOrderEvent instead, which is unintuitive.

Requires Documentation Change

No.

How Has This Been Tested?

Added 6 new unit tests in BrokerageTransactionHandlerTests:

  • OptionAssignmentEventFiredAfterPortfolioUpdate (2 cases) — verifies portfolio state and event ordering for at-expiry assignment (Short Call + Short Put)
  • EarlyAssignmentEventFiredAfterPortfolioUpdate (4 cases) — verifies portfolio state and event ordering for early assignment (Short Call + Short Put, full + partial)

Each test asserts:

  1. The underlying position is correct in the portfolio at the moment OnAssignmentOrderEvent fires
  2. OnOrderEvent for the underlying fill has already been called before OnAssignmentOrderEvent

All 6 new tests and 32 existing related tests pass.

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)

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>

EmitOptionNotificationEvents processed fills one at a time and fired
HandlePositionAssigned immediately after the option fill, before the
underlying delivery fill was processed. Split the single foreach into
two passes: first process all fills to update the portfolio, then fire
assignment events.

Fixes QuantConnect#9321
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.

on_assignment_order_event() called before the shares are actually on the portfolio.

1 participant