diff --git a/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/03 Place Related Orders.html b/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/03 Place Related Orders.html index f0bfe37708..6777f8072a 100644 --- a/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/03 Place Related Orders.html +++ b/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/03 Place Related Orders.html @@ -1,4 +1,4 @@ -
Each order in an OCO set can trigger other orders. To trigger orders after an OCO order fills, call the Triggerstriggers or Bracketbracket 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.
Each order in an OCO set can trigger other orders. To trigger orders after an OCO order fills, call the Triggerstriggers or Bracketbracket 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.
// Two breakout entries that cancel each other, each with its own exit orders. diff --git a/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/99 Examples.html b/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/99 Examples.html index 31f0e9b664..08bd3f1854 100644 --- a/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/99 Examples.html +++ b/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/02 One Cancels Other Orders/99 Examples.html @@ -46,3 +46,58 @@Example 1: Exit Each Trade at a Price Range
self.order_factory.stop_market_order(self._spy, -100, round(fill_price * 0.99, 2), tag="Stop loss") ])
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.
+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 > 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<SubmitOrderRequest>
+ {
+ OrderFactory.LimitOrder(_spy, -100, takeProfitPrice).Triggers(buyBack),
+ OrderFactory.StopMarketOrder(_spy, -100, stopLossPrice)
+ });
+ }
+}
+class OneCancelsOtherGrandchildExampleAlgorithm(QCAlgorithm):
+
+ def initialize(self) -> 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) -> 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)
+ ])
+Each order in an OUO set can trigger other orders. To trigger orders after an OUO order fills, call the Triggerstriggers 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.
Each order in an OUO set can trigger other orders. To trigger orders after an OUO order fills, call the Triggerstriggers 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.
// Reverse the long position when the stop loss fills. diff --git a/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/04 One Updates Other Orders/99 Examples.html b/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/04 One Updates Other Orders/99 Examples.html index fdf5608c88..aacca0d6d7 100644 --- a/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/04 One Updates Other Orders/99 Examples.html +++ b/03 Writing Algorithms/22 Trading and Orders/03 Order Types/13 Contingent Orders/04 One Updates Other Orders/99 Examples.html @@ -46,3 +46,56 @@Example 1: Exit Illiquid Positions in Parts
self.order_factory.stop_market_order(self._iwm, -500, round(fill_price * 0.99, 2), tag="Stop loss") ])
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.
+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 > 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<SubmitOrderRequest>
+ {
+ OrderFactory.LimitOrder(_iwm, -500, Math.Round(fillPrice * 1.01m, 2)),
+ OrderFactory.StopMarketOrder(_iwm, -500, stopLossPrice).Triggers(shortEntry)
+ });
+ }
+}
+class OneUpdatesOtherGrandchildExampleAlgorithm(QCAlgorithm):
+
+ def initialize(self) -> 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) -> 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)
+ ])
+