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
@@ -0,0 +1,27 @@
<p>The exit orders that the <code class="csharp">BracketOrder</code><code class="python">bracket_order</code> and <code class="csharp">Bracket</code><code class="python">bracket</code> methods create can't trigger other orders. To make an exit trigger another order, build the bracket from its parts with the order factory. For more information, see <a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/custom-contingent-orders'>Custom Contingent Orders</a>.</p>

<ol>
<li>Call the <code class="csharp">Triggers</code><code class="python">triggers</code> method on the exit order request with the order to trigger.</li>
<li>Relate the exit order requests with the <code class="csharp">OrderFactory.OneCancelsOther</code><code class="python">order_factory.one_cancels_other</code> method.</li>
<li>Pass the exit order requests to the <code class="csharp">Triggers</code><code class="python">triggers</code> method of the entry order request.</li>
<li>Pass the entry order request to the <code class="csharp">Order</code><code class="python">order</code> method.</li>
</ol>

<div class="section-example-container">
<pre class="csharp">// The take profit triggers a new entry at the entry price.
var takeProfit = OrderFactory.LimitOrder(_symbol, -100, price * 1.02m)
.Triggers(OrderFactory.LimitOrder(_symbol, 100, price * 0.999m));
var stopLoss = OrderFactory.StopMarketOrder(_symbol, -100, price * 0.99m);
var entry = OrderFactory.LimitOrder(_symbol, 100, price * 0.999m)
.Triggers(OrderFactory.OneCancelsOther(takeProfit, stopLoss));
var tickets = Order(entry);</pre>
<pre class="python"># The take profit triggers a new entry at the entry price.
take_profit = self.order_factory.limit_order(self._symbol, -100, price * 1.02).triggers(
self.order_factory.limit_order(self._symbol, 100, price * 0.999))
stop_loss = self.order_factory.stop_market_order(self._symbol, -100, price * 0.99)
entry = self.order_factory.limit_order(self._symbol, 100, price * 0.999).triggers(
self.order_factory.one_cancels_other(take_profit, stop_loss))
tickets = self.order(entry)</pre>
</div>

<p>The order that the exit triggers is a grandchild of the entry. The brokerage holds it until the exit completely fills. If the other exit fills first, LEAN cancels the exit and its grandchild. The <code class="csharp">Order</code><code class="python">order</code> method returns the order tickets of the entry, the take profit, the order it triggers, and the stop loss, in that order.</p>
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,70 @@ <h4>Example 1: Bracket Orders on New Highs</h4>
quantity = self.calculate_order_quantity(self._spy, 0.5)
self.bracket_order(self._spy, quantity, take_profit_price=round(bar.close * 1.02, 2), stop_loss_price=round(bar.close * 0.99, 2))</pre>
</div>

<h4>Example 2: Re-Enter After the Take Profit</h4>
<p>The following algorithm buys SPY with a bracket order when it has no position. The entry is 1% below the close price. The take profit is 2% above the close price, and the stop loss is 2% below it. When the take profit fills, it triggers a new entry at the entry price. When the new entry fills, the algorithm places new exit orders as one cancels other orders.</p>
<div class="section-example-container">
<pre class="csharp">public class BracketReEntryExampleAlgorithm : QCAlgorithm
{
private Symbol _spy;

public override void Initialize()
{
SetStartDate(2024, 1, 1);
SetEndDate(2024, 12, 31);
_spy = AddEquity("SPY", Resolution.Daily).Symbol;
}

public override void OnData(Slice slice)
{
if (Transactions.GetOpenOrders(_spy).Count &gt; 0 || !slice.Bars.TryGetValue(_spy, out var bar))
{
return;
}
var entryPrice = Math.Round(bar.Close * 0.99m, 2);
var takeProfitPrice = Math.Round(bar.Close * 1.02m, 2);
var stopLossPrice = Math.Round(bar.Close * 0.98m, 2);
if (Portfolio[_spy].Invested)
{
// Exit the position of the new entry.
OneCancelsOtherOrder(new List&lt;SubmitOrderRequest&gt;
{
OrderFactory.LimitOrder(_spy, -100, takeProfitPrice),
OrderFactory.StopMarketOrder(_spy, -100, stopLossPrice)
});
return;
}
var takeProfit = OrderFactory.LimitOrder(_spy, -100, takeProfitPrice)
.Triggers(OrderFactory.LimitOrder(_spy, 100, entryPrice));
var stopLoss = OrderFactory.StopMarketOrder(_spy, -100, stopLossPrice);
Order(OrderFactory.LimitOrder(_spy, 100, entryPrice).Triggers(OrderFactory.OneCancelsOther(takeProfit, stopLoss)));
}
}</pre>
<pre class="python">class BracketReEntryExampleAlgorithm(QCAlgorithm):

def initialize(self) -&gt; None:
self.set_start_date(2024, 1, 1)
self.set_end_date(2024, 12, 31)
self._spy = self.add_equity("SPY", Resolution.DAILY).symbol

def on_data(self, slice: Slice) -&gt; None:
bar = slice.bars.get(self._spy)
if self.transactions.get_open_orders(self._spy) or not bar:
return
entry_price = round(bar.close * 0.99, 2)
take_profit_price = round(bar.close * 1.02, 2)
stop_loss_price = round(bar.close * 0.98, 2)
if self.portfolio[self._spy].invested:
# Exit the position of the new entry.
self.one_cancels_other_order([
self.order_factory.limit_order(self._spy, -100, take_profit_price),
self.order_factory.stop_market_order(self._spy, -100, stop_loss_price)
])
return
take_profit = self.order_factory.limit_order(self._spy, -100, take_profit_price).triggers(
self.order_factory.limit_order(self._spy, 100, entry_price))
stop_loss = self.order_factory.stop_market_order(self._spy, -100, stop_loss_price)
self.order(self.order_factory.limit_order(self._spy, 100, entry_price).triggers(
self.order_factory.one_cancels_other(take_profit, stop_loss)))</pre>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<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>

<div class="section-example-container">
<pre class="csharp">// Two breakout entries that cancel each other, each with its own exit orders.
var breakoutUp = OrderFactory.StopMarketOrder(_symbol, 100, high).Bracket(high + range, low);
var breakoutDown = OrderFactory.StopMarketOrder(_symbol, -100, low).Bracket(low - range, high);
var tickets = OneCancelsOtherOrder(new List&lt;SubmitOrderRequest&gt; { breakoutUp, breakoutDown });</pre>
<pre class="python"># Two breakout entries that cancel each other, each with its own exit orders.
breakout_up = self.order_factory.stop_market_order(self._symbol, 100, high).bracket(high + range_, low)
breakout_down = self.order_factory.stop_market_order(self._symbol, -100, low).bracket(low - range_, high)
tickets = self.one_cancels_other_order([breakout_up, breakout_down])</pre>
</div>

<p>The method returns the order ticket of each OCO order followed by the order tickets of the orders it triggers. For a complete example, see <a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/custom-contingent-orders#99-Examples'>Custom Contingent Orders</a>.</p>
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,6 @@
])</pre>
</div>

<p>The child orders are independent of each other and can be for different securities. To relate the child orders, pass them through the <code class="csharp">OrderFactory.OneCancelsOther</code><code class="python">order_factory.one_cancels_other</code> or <code class="csharp">OrderFactory.OneUpdatesOther</code><code class="python">order_factory.one_updates_other</code> method first, as described in <a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/custom-contingent-orders'>Custom Contingent Orders</a>. A child order can trigger its own child orders, which are grandchild orders of the parent. To create a chain, call the <code class="csharp">Triggers</code><code class="python">triggers</code> method on the child order request.</p>

<div class="section-example-container">
<pre class="csharp">// The IBM order triggers the BAC order once it fills.
var child = OrderFactory.MarketOrder(_ibm, 10).Triggers(OrderFactory.MarketOrder(_bac, 20));
var tickets = OneTriggersOtherOrder(parent, new List&lt;SubmitOrderRequest&gt; { child });</pre>
<pre class="python"># The IBM order triggers the BAC order once it fills.
child = self.order_factory.market_order(self._ibm, 10).triggers(self.order_factory.market_order(self._bac, 20))
tickets = self.one_triggers_other_order(parent, [child])</pre>
</div>

<p>The brokerage holds the grandchild order until the child order completely fills. The method returns the order tickets in the order parent, child, and grandchild, with each parent before the orders it triggers. If you cancel the parent, LEAN cancels the child and the grandchild.</p>

<p>The following images show the two outcomes of an OTO set. In the first image, the parent order fills and triggers the child order, which fills later:</p>
<img class="docs-image" src="https://cdn.quantconnect.com/i/tu/oto-child-filled.webp" alt="An OTO set has a parent buy limit order at 45,000 and a child sell limit order at 58,000. The brokerage holds the child order until the price falls to 45,000 and the parent fills. The price then rises to 58,000 and the child order fills.">

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<p>The child orders are independent of each other and can be for different securities. To relate the child orders, pass them through the <code class="csharp">OrderFactory.OneCancelsOther</code><code class="python">order_factory.one_cancels_other</code> or <code class="csharp">OrderFactory.OneUpdatesOther</code><code class="python">order_factory.one_updates_other</code> method first, as described in <a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/custom-contingent-orders'>Custom Contingent Orders</a>. A child order can trigger its own child orders, which are grandchild orders of the parent. To create a chain, call the <code class="csharp">Triggers</code><code class="python">triggers</code> method on the child order request.</p>

<div class="section-example-container">
<pre class="csharp">// The IBM order triggers the BAC order once it fills.
var child = OrderFactory.MarketOrder(_ibm, 10).Triggers(OrderFactory.MarketOrder(_bac, 20));
var tickets = OneTriggersOtherOrder(parent, new List&lt;SubmitOrderRequest&gt; { child });</pre>
<pre class="python"># The IBM order triggers the BAC order once it fills.
child = self.order_factory.market_order(self._ibm, 10).triggers(self.order_factory.market_order(self._bac, 20))
tickets = self.one_triggers_other_order(parent, [child])</pre>
</div>

<p>The brokerage holds the grandchild order until the child order completely fills. The method returns the order tickets in the order parent, child, and grandchild, with each parent before the orders it triggers. If you cancel the parent, LEAN cancels the child and the grandchild.</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<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>

<div class="section-example-container">
<pre class="csharp">// Reverse the long position when the stop loss fills.
var stopLoss = OrderFactory.StopMarketOrder(_symbol, -100, price * 0.99m).Triggers(OrderFactory.MarketOrder(_symbol, -100));
var tickets = OneUpdatesOtherOrder(new List&lt;SubmitOrderRequest&gt;
{
OrderFactory.LimitOrder(_symbol, -100, price * 1.02m),
stopLoss
});</pre>
<pre class="python"># Reverse the long position when the stop loss fills.
stop_loss = self.order_factory.stop_market_order(self._symbol, -100, price * 0.99).triggers(
self.order_factory.market_order(self._symbol, -100))
tickets = self.one_updates_other_order([
self.order_factory.limit_order(self._symbol, -100, price * 1.02),
stop_loss
])</pre>
</div>

<p>The quantity of a triggered order doesn't change when LEAN reduces the quantity of its parent.</p>
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,29 @@
<tr>
<th>Method</th>
<th>Description</th>
<th>Examples</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="csharp">request.Triggers(children)</code><code class="python">request.triggers(children)</code></td>
<td>The request triggers the child orders when it completely fills (OTO).</td>
<td><a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/one-triggers-other-orders#03-Place-Related-Orders'>Place Related Orders</a></td>
</tr>
<tr>
<td><code class="csharp">request.Bracket(takeProfitPrice, stopLossPrice)</code><code class="python">request.bracket(take_profit_price, stop_loss_price)</code></td>
<td>The request triggers a take-profit order and a stop-loss order that cancel each other.</td>
<td><a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/bracket-orders#03-Place-Related-Orders'>Place Related Orders</a></td>
</tr>
<tr>
<td><code class="csharp">OrderFactory.OneCancelsOther(requests)</code><code class="python">order_factory.one_cancels_other(requests)</code></td>
<td>The first fill of a request cancels the others (OCO).</td>
<td><a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/one-cancels-other-orders#03-Place-Related-Orders'>Place Related Orders</a></td>
</tr>
<tr>
<td><code class="csharp">OrderFactory.OneUpdatesOther(requests)</code><code class="python">order_factory.one_updates_other(requests)</code></td>
<td>A partial fill of a request reduces the quantity of the others (OUO).</td>
<td><a href='/docs/v2/writing-algorithms/trading-and-orders/order-types/contingent-orders/one-updates-other-orders#03-Place-Related-Orders'>Place Related Orders</a></td>
</tr>
</tbody>
</table>
Expand Down