Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<p>Each order in an OCO set can trigger other orders. To trigger orders after an OCO order fills, call the <code class="csharp">Triggers</code><code class="python">triggers</code> or <code class="csharp">Bracket</code><code class="python">bracket</code> method on its order request. Call the method before you relate the request with the other orders. The brokerage holds the triggered orders until their parent completely fills. If another order in the set fills first, LEAN cancels the parent and the orders it triggers.</p>
<p>Each order in an OCO set can trigger other orders. To trigger orders after an OCO order fills, call the <code class="csharp">Triggers</code><code class="python">triggers</code> or <code class="csharp">Bracket</code><code class="python">bracket</code> method on its order request. Call the method before you relate the request with the other orders. The brokerage holds the triggered orders until their parent completely fills. If another order in the set fills first, LEAN cancels the parent and the orders it triggers. A triggered order can trigger other orders in turn, which are grandchildren of the OCO order.</p>

<div class="section-example-container">
<pre class="csharp">// Two breakout entries that cancel each other, each with its own exit orders.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,58 @@ <h4>Example 1: Exit Each Trade at a Price Range</h4>
self.order_factory.stop_market_order(self._spy, -100, round(fill_price * 0.99, 2), tag="Stop loss")
])</pre>
</div>

<h4>Example 2: Buy Back After the Take Profit</h4>
<p>The following algorithm buys SPY each day at 10 AM Eastern Time when it has no position, and then places OCO exit orders. The take-profit order triggers a limit order that buys SPY back at the entry price. The buy-back order is a bracket order, so its exit orders are grandchildren of the take-profit order. If the stop loss fills first, LEAN cancels the take profit, the buy-back order, and its exit orders.</p>
<div class="section-example-container">
<pre class="csharp">public class OneCancelsOtherGrandchildExampleAlgorithm : QCAlgorithm
{
private Symbol _spy;

public override void Initialize()
{
SetStartDate(2024, 1, 1);
SetEndDate(2024, 3, 31);
_spy = AddEquity("SPY", Resolution.Minute).Symbol;
Schedule.On(DateRules.EveryDay(_spy), TimeRules.At(10, 0), Enter);
}

private void Enter()
{
if (Portfolio.Invested || Transactions.GetOpenOrders(_spy).Count &gt; 0)
{
return;
}
var fillPrice = MarketOrder(_spy, 100).AverageFillPrice;
var takeProfitPrice = Math.Round(fillPrice * 1.01m, 2);
var stopLossPrice = Math.Round(fillPrice * 0.99m, 2);
// The buy-back order and its exit orders wait for the take profit to fill.
var buyBack = OrderFactory.LimitOrder(_spy, 100, Math.Round(fillPrice, 2)).Bracket(takeProfitPrice, stopLossPrice);
OneCancelsOtherOrder(new List&lt;SubmitOrderRequest&gt;
{
OrderFactory.LimitOrder(_spy, -100, takeProfitPrice).Triggers(buyBack),
OrderFactory.StopMarketOrder(_spy, -100, stopLossPrice)
});
}
}</pre>
<pre class="python">class OneCancelsOtherGrandchildExampleAlgorithm(QCAlgorithm):

def initialize(self) -&gt; None:
self.set_start_date(2024, 1, 1)
self.set_end_date(2024, 3, 31)
self._spy = self.add_equity("SPY", Resolution.MINUTE).symbol
self.schedule.on(self.date_rules.every_day(self._spy), self.time_rules.at(10, 0), self._enter)

def _enter(self) -&gt; None:
if self.portfolio.invested or self.transactions.get_open_orders(self._spy):
return
fill_price = self.market_order(self._spy, 100).average_fill_price
take_profit_price = round(fill_price * 1.01, 2)
stop_loss_price = round(fill_price * 0.99, 2)
# The buy-back order and its exit orders wait for the take profit to fill.
buy_back = self.order_factory.limit_order(self._spy, 100, round(fill_price, 2)).bracket(take_profit_price, stop_loss_price)
self.one_cancels_other_order([
self.order_factory.limit_order(self._spy, -100, take_profit_price).triggers(buy_back),
self.order_factory.stop_market_order(self._spy, -100, stop_loss_price)
])</pre>
</div>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<p>Each order in an OUO set can trigger other orders. To trigger orders after an OUO order fills, call the <code class="csharp">Triggers</code><code class="python">triggers</code> method on its order request before you relate it with the other orders. The brokerage holds the triggered orders until their parent completely fills. If another order in the set completely fills, LEAN cancels the parent and the orders it triggers. This rule applies even if the parent partially filled.</p>
<p>Each order in an OUO set can trigger other orders. To trigger orders after an OUO order fills, call the <code class="csharp">Triggers</code><code class="python">triggers</code> method on its order request before you relate it with the other orders. The brokerage holds the triggered orders until their parent completely fills. If another order in the set completely fills, LEAN cancels the parent and the orders it triggers. This rule applies even if the parent partially filled. A triggered order can trigger other orders in turn, which are grandchildren of the OUO order.</p>

<div class="section-example-container">
<pre class="csharp">// Reverse the long position when the stop loss fills.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,56 @@ <h4>Example 1: Exit Illiquid Positions in Parts</h4>
self.order_factory.stop_market_order(self._iwm, -500, round(fill_price * 0.99, 2), tag="Stop loss")
])</pre>
</div>

<h4>Example 2: Reverse the Position on the Stop Loss</h4>
<p>The following algorithm buys IWM each day at 10 AM Eastern Time when it has no position, and then places OUO exit orders. The stop-loss order triggers a market order that sells 500 more shares to open a short position. The short entry is a bracket order, so its exit orders are grandchildren of the stop-loss order. If the take profit completely fills first, LEAN cancels the stop loss, the short entry, and its exit orders.</p>
<div class="section-example-container">
<pre class="csharp">public class OneUpdatesOtherGrandchildExampleAlgorithm : QCAlgorithm
{
private Symbol _iwm;

public override void Initialize()
{
SetStartDate(2024, 1, 1);
SetEndDate(2024, 3, 31);
_iwm = AddEquity("IWM", Resolution.Minute).Symbol;
Schedule.On(DateRules.EveryDay(_iwm), TimeRules.At(10, 0), Enter);
}

private void Enter()
{
if (Portfolio.Invested || Transactions.GetOpenOrders(_iwm).Count &gt; 0)
{
return;
}
var fillPrice = MarketOrder(_iwm, 500).AverageFillPrice;
var stopLossPrice = Math.Round(fillPrice * 0.99m, 2);
// The short entry and its exit orders wait for the stop loss to fill.
var shortEntry = OrderFactory.MarketOrder(_iwm, -500).Bracket(Math.Round(stopLossPrice * 0.98m, 2), Math.Round(fillPrice, 2));
OneUpdatesOtherOrder(new List&lt;SubmitOrderRequest&gt;
{
OrderFactory.LimitOrder(_iwm, -500, Math.Round(fillPrice * 1.01m, 2)),
OrderFactory.StopMarketOrder(_iwm, -500, stopLossPrice).Triggers(shortEntry)
});
}
}</pre>
<pre class="python">class OneUpdatesOtherGrandchildExampleAlgorithm(QCAlgorithm):

def initialize(self) -&gt; None:
self.set_start_date(2024, 1, 1)
self.set_end_date(2024, 3, 31)
self._iwm = self.add_equity("IWM", Resolution.MINUTE).symbol
self.schedule.on(self.date_rules.every_day(self._iwm), self.time_rules.at(10, 0), self._enter)

def _enter(self) -&gt; None:
if self.portfolio.invested or self.transactions.get_open_orders(self._iwm):
return
fill_price = self.market_order(self._iwm, 500).average_fill_price
stop_loss_price = round(fill_price * 0.99, 2)
# The short entry and its exit orders wait for the stop loss to fill.
short_entry = self.order_factory.market_order(self._iwm, -500).bracket(round(stop_loss_price * 0.98, 2), round(fill_price, 2))
self.one_updates_other_order([
self.order_factory.limit_order(self._iwm, -500, round(fill_price * 1.01, 2)),
self.order_factory.stop_market_order(self._iwm, -500, stop_loss_price).triggers(short_entry)
])</pre>
</div>