Order Types
Market On Open Orders
Place Orders
To send a MOO order, call the MarketOnOpenOrdermarket_on_open_order method and provide a Symbol and quantity. Submit the order at least two minutes before the market opens to be included in the opening auction. If you do not have sufficient capital for the order, it's rejected.
// Buy 100 shares of IBM at the market open
MarketOnOpenOrder("IBM", 100);
// Sell 100 shares of IBM at the market open
MarketOnOpenOrder("IBM", -100); # Buy 100 shares of IBM at the market open
self.market_on_open_order("IBM", 100)
# Sell 100 shares of IBM at the market open
self.market_on_open_order("IBM", -100)
You can provide a tag and order properties to the MarketOnOpenOrdermarket_on_open_order method.
MarketOnOpenOrder(symbol, quantity, tag: tag, orderProperties: orderProperties);
self.market_on_open_order(symbol, quantity, tag=tag, order_properties=order_properties)
Monitor Order Fills
MOO orders fill at the opening auction. If the auction is heavily skewed to one side of the market, your MOO order may not fill. To monitor the fills of your order, save a reference to the order ticket.
// Buy 10 shares of SPY at the market open
var ticket = MarketOnOpenOrder("SPY", 10);
Debug($"Quantity filled: {ticket.QuantityFilled}; Fill price: {ticket.AverageFillPrice}"); # Buy 10 shares of SPY at the market open
ticket = self.market_on_open_order("SPY", 10)
self.debug(f"Quantity filled: {ticket.quantity_filled}; Fill price: {ticket.average_fill_price}")
You won't know the fill price of the order until after the market opens. If the asset price moves before the market open to where you can't afford the quantity of the order, the brokerage rejects your order. To increase the probability of a successful trade, leave a sufficient buying power buffer to handle daily price gaps.
For more information about how LEAN models order fills in backtests, see Trade Fills.
Update Orders
You can update the quantity and tag of MOO orders until the order fills or the brokerage prevents modifications. To update an order, pass an UpdateOrderFields object to the Updateupdate method on the OrderTicket. If you don't have the order ticket, get it from the transaction manager. The Updateupdate method returns an OrderResponse to signal the success or failure of the update request.
// Create a new order and save the order ticket
var ticket = MarketOnOpenOrder("AAPL", 100, tag:"original tag");
// Update the order
var response = ticket.Update(new UpdateOrderFields()
{
Quantity = 75,
Tag = "new tag"
});
// Check if the update was successful
if (response.IsSuccess)
{
Debug("Order updated successfully");
} # Create a new order and save the order ticket
ticket = self.market_on_open_order("AAPL", 100, tag="original tag")
# Update the order
update_settings = UpdateOrderFields()
update_settings.quantity = 75
update_settings.tag = "new tag"
response = ticket.update(update_settings)
# Check if the update was successful
if response.is_success:
self.debug("Order updated successfully")
To update individual fields of an order, call any of the following methods:
UpdateQuantityupdate_quantityUpdateTagupdate_tag
var quantityResponse = ticket.UpdateQuantity(quantity, tag); var tagResponse = ticket.UpdateTag(tag);
response = ticket.update_quantity(quantity, tag) response = ticket.update_tag(tag)
When you update an order, LEAN creates an UpdateOrderRequest object, which have the following attributes:
To get a list of UpdateOrderRequest objects for an order, call the UpdateRequestsupdate_requests method.
var updateRequests = ticket.UpdateRequests();
update_requests = ticket.update_requests()
Cancel Orders
To cancel a MOO order, call the Cancelcancel method on the OrderTicket. If you don't have the order ticket, get it from the transaction manager. The Cancelcancel method returns an OrderResponse object to signal the success or failure of the cancel request.
var response = ticket.Cancel("Cancelled trade");
if (response.IsSuccess)
{
Debug("Order successfully cancelled");
} response = ticket.cancel("Cancelled Trade")
if response.is_success:
self.debug("Order successfully cancelled")
When you cancel an order, LEAN creates a CancelOrderRequest, which have the following attributes:
To get the CancelOrderRequest for an order, call the CancelRequestcancel_order_request method on the order ticket. The method returns nullNone if the order hasn't been cancelled.
var request = ticket.cancel_order_request();
request = ticket.cancel_order_request()
Asynchronous Orders
When you trade a large portfolio of assets, you may want to send orders in batches and not wait for the response of each one. To send asynchronous orders, set the asynchronous argument to trueTrue.
MarketOnOpenOrder("SPY", 10, asynchronous: true); self.market_on_open_order("SPY", 10, asynchronous=True);
Brokerage Support
Each brokerage has a set of assets and order types they support. To avoid issues with MOO orders, set the brokerage model to a brokerage that supports them.
SetBrokerageModel(BrokerageName.QuantConnectBrokerage);
self.set_brokerage_model(BrokerageName.QUANTCONNECT_BROKERAGE)
To check if your brokerage has any special requirements for MOO orders, see the Orders section of the brokerage model documentation.
Requirements
You can submit MOO orders at any time for Equity, Equity Options, and Index Options.
Markets that operate 24/7 don't support MOO orders. The Forex market doesn't operate during the weekend. However, MOO orders are invalid if you place them after this market closes for the weekend.
MOO orders don't support the GoodTilDate time in force. If you submit a MOO order with the GoodTilDate time in force, LEAN automatically adjusts the time in force to be GoodTilCanceled.
Examples
The following backtest verifies the
MarketOnOpenOrder
market_on_open_order
behavior. The following table shows the first trade in the backtest:
| Submitted Time | Filled Time | Symbol | Price | Quantity | Type | Status | Value | Tag |
|---|---|---|---|---|---|---|---|---|
| 2021-07-01T10:31:00Z | 2021-07-02T09:31:00Z | SPY | 431.67 | 10 | Market On Open | Filled | 4316.70 |
On July 1, 2021 at 10:31 AM Eastern Time (ET), the algorithm places a market on open order to buy SPY. The fill model fills the order on July 2, 2021 at 9:31 AM at a price of $431.67, which is the
official opening auction price
for July 2, 2021.
To reproduce these results, backtest the following algorithm:
public class MarketOnOpenOrderAlgorithm : QCAlgorithm
{
private Symbol _symbol;
public override void Initialize()
{
SetStartDate(2024, 9, 1);
SetEndDate(2024, 9, 4);
SetCash(100000);
UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw;
_symbol = AddEquity("SPY").Symbol;
}
public override void OnData(Slice data)
{
if (Time.Day == 1 && Time.Hour == 10 && Time.Minute == 31)
{
MarketOnOpenOrder(_symbol, 10);
}
}
} class MarketOnOpenOrderAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 9, 4)
self.set_cash(100000)
self.universe_settings.data_normalization_mode = DataNormalizationMode.RAW
self.add_equity("SPY")
def on_data(self, data):
if self.time.day == 1 and self.time.hour == 10 and self.time.minute == 31:
self.market_on_open_order("SPY", 10)