Skip to content

Add contingent orders support: bracket, oco and oto order classes - #83

Merged
Martin-Molinero merged 5 commits into
masterfrom
feature-contingent-orders
Sep 25, 2026
Merged

Martin-Molinero merged 5 commits into
masterfrom
feature-contingent-orders

Conversation

@Martin-Molinero

@Martin-Molinero Martin-Molinero commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Description

Places contingent order sets as a single Alpaca advanced order:

  • bracket: entry with take profit and stop loss.
  • oco: exits only.
  • oto: entry and one exit.
  • The Lean order settings (time in force, extended hours) are kept on the advanced order, and the brokerage side leg resizing is propagated.
  • Held legs are reported as triggered once the entry fills.
  • The contingencies of nested open orders are rebuilt through OrderContingency.Trigger/Relate. Open orders are read with nested=true, which only regroups the bracket/oco/oto legs: multi-leg option orders come with their legs either way (checked live).
  • A rejected order update is reported as a warning and the order keeps working, it was marked invalid: Alpaca rejects the replace request (e.g. order parameters are not changed) leaving the order unchanged, or rejects the replacement when the order filled first, a fill the stream reports.

Related Issue

Requires QuantConnect/Lean#9828, which adds contingent orders to Lean. This PR builds against it, so CI will pass once it's merged and released.

Motivation and Context

Support for Lean contingent orders (OCO, OTO, OUO, brackets) using the brokerage's native functionality, so the sets are placed atomically and managed on the brokerage side.

Requires Documentation Change

The supported contingent order shapes of this brokerage, see its brokerage model in Lean: equities only, crypto and options are rejected by the model (Alpaca supports advanced orders for equities).

How Has This Been Tested?

  • Unit tests of the contingent orders support (9): held statuses, advanced order settings and request building.
  • Live on an Alpaca paper account, through the Lean BrokerageTests contingent orders suite (AlpacaBrokerageTests.ContingentOrders.cs):
Case Equity (AAPL)
OTO resting: cancel the parent cancels the held child ✅
Bracket resting: cancel the entry cancels the held exits ✅
OTO / bracket with a market parent: parent fills, children released ✅
OTO / bracket: open orders rebuilt with the same contingencies, held ones held ✅
  • Not in the suite: updating every order unchanged, Alpaca rejects a replace that changes nothing (order parameters are not changed): checked live that the rejection is now a warning and the order stays submitted, and OCO, which Alpaca only takes as the exits of an existing position.
  • Existing order tests, equities, after updating the fixture prices to the current market (the stops were rejected with the old ones):
Test Market Limit Stop market Stop limit Trailing stop (CIFR, TSLA)
CancelOrders ✅ ✅ ✅ ✅ ✅ ✅
LongFromZero / ShortFromZero ✅ ✅ ✅ ✅ ✅ ✅
CloseFromLong / CloseFromShort ✅ ✅ ✅ ✅ ✅ ✅
LongFromShort ✅ ✅ ❌ ✅ ✅ ✅
ShortFromLong ✅ ✅ ❌ ❌ ✅ ✅

The ❌ fail as on master: the test moves the stop to the last traded price to force a fill, and Alpaca rejects it when the price ticked the other way (stop price must be less than current price), or it doesn't fill in time. Flaky, the long from short stop limit failed in the previous run.

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>

🤖 Generated with Claude Code

Martin-Molinero and others added 3 commits September 25, 2026 09:47
Places brackets, OCO exits and OTO sets as a single advanced order,
propagates the brokerage side leg resizing, reports triggered legs once
the entry fills and rebuilds the contingencies of nested open orders.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Martin-Molinero
Martin-Molinero force-pushed the feature-contingent-orders branch from 6918992 to 0660cef Compare September 25, 2026 12:50
Martin-Molinero and others added 2 commits September 25, 2026 11:13
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Martin-Molinero
Martin-Molinero merged commit e623e79 into master Sep 25, 2026
1 check failed
@Martin-Molinero
Martin-Molinero deleted the feature-contingent-orders branch September 25, 2026 16:16
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