Order Types
Stop Market Orders
Introduction
Stop market orders fill as a market order when the asset reaches a specific price. A buy stop market order triggers when the asset price is greater than or equal to the stop price. A sell stop market order triggers when the asset price is less than or equal to the stop price. You can use stop market orders to buy breakouts or to mitigate the risk of large losses. However, if the market gaps past your stop price, the order may fill at a worse price than the stop price you set. There is no guarantee that a stop market order fills at the stop price.
Place Orders
To send a stop market order, call the StopMarketOrder
stop_market_order
method and provide a Symbol
, quantity, and stop price. You can also provide a tag and order properties to the StopMarketOrder
stop_market_order
method. If you do not have sufficient capital for the order, it is rejected.
StopMarketOrder(symbol, quantity, stopPrice, tag, orderProperties);
self.stop_market_order(symbol, quantity, stop_price, tag, order_properties)
To buy an asset with a stop market order, set the stop price above the current ask price.
// When Bitcoin trades up to $60,000, buy 1 Bitcoin StopMarketOrder("BTCUSD", 1, 60000);
# When Bitcoin trades up to $60,000, buy 1 Bitcoin self.stop_market_order("BTCUSD", 1, 60000)
To sell an asset with a stop market order, set the stop price below the current bid price.
// When Bitcoin trades down to $43,000, sell 1 Bitcoin StopMarketOrder("BTCUSD", -1, 43000);
# When Bitcoin trades down to $43,000, sell 1 Bitcoin self.stop_market_order("BTCUSD", -1, 43000)
Monitor Order Fills
Stop market orders fill as a market order when the security price passes the stop price. To monitor the fills of your order, save a reference to the order ticket.
// When XLK trades down to $130, sell 10 shares var ticket = StopMarketOrder("XLK", -10, 130); Debug($"Quantity filled: {ticket.QuantityFilled}; Fill price: {ticket.AverageFillPrice}");
# When XLK trades down to $130, sell 10 shares ticket = self.stop_market_order("XLK", -10, 130) self.debug(f"Quantity filled: {ticket.quantity_filled}; Fill price: {ticket.average_fill_price}")
For more information about how LEAN models order fills in backtests, see Trade Fills.
Update Orders
You can update the quantity, stop price, and tag of stop market orders until the order fills or the brokerage prevents modifications. To update an order, pass an UpdateOrderFields
object to the Update
update
method on the OrderTicket
. If you don't have the order ticket, get it from the transaction manager. The Update
update
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 = StopMarketOrder("SPY", -100, 415, tag: "original tag"); // Update the order var response = ticket.Update(new UpdateOrderFields() { Quantity = -80, StopPrice = 400, 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.stop_market_order("SPY", -100, 415, tag="original tag") # Update the order update_settings = UpdateOrderFields() update_settings.quantity = -80 update_settings.stop_price = 400 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:
UpdateQuantity
update_quantity
UpdateStopPrice
update_stop_price
UpdateTag
update_tag
var quantityResponse = ticket.UpdateQuantity(quantity, tag); var stopResponse = ticket.UpdateStopPrice(stopPrice, tag); var tagResponse = ticket.UpdateTag(tag);
response = ticket.update_quantity(quantity, tag) response = ticket.update_stop_price(stop_price, 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 UpdateRequests
update_requests
method.
var updateRequests = ticket.UpdateRequests();
update_requests = ticket.update_requests()
Cancel Orders
To cancel a stop market order, call the Cancel
cancel
method on the OrderTicket
. If you don't have the order ticket, get it from the transaction manager. The Cancel
cancel
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 CancelRequest
cancel_order_request
method on the order ticket. The method returns null
None
if the order hasn't been cancelled.
var request = ticket.cancel_order_request();
request = ticket.cancel_order_request()
Brokerage Support
Each brokerage has a set of assets and order types they support. To avoid issues with stop market orders, set the brokerage model to a brokerage that supports them.
SetBrokerageModel(BrokerageName.QuantConnectBrokerage);
self.set_brokerage_model(BrokerageName.QuantConnectBrokerage)
To check if your brokerage has any special requirements for stop market orders, see the Orders section of the brokerage model documentation.
Example
The following backtest verifies the StopMarketOrder
stop_market_order
behavior. On even days, the algorithm buys SPY at the current market price and sells when the price drops 1%. On odd days, the algorithm shorts SPY and buys when the price rises 1%. The following table shows the first four trades in the backtest:
Time | Symbol | Price | Quantity | Type | Status | Value | Tag |
---|---|---|---|---|---|---|---|
2021-07-01T13:31:00Z | SPY | 429.10 | -1 | Market | Filled | -429.10 | |
2021-07-01T13:31:00Z | SPY | 433.44 | 1 | Stop Market | Filled | 433.44 | Stop Price: 433.43 |
2021-07-02T17:04:00Z | SPY | 433.44 | 1 | Market | Filled | 433.44 | |
2021-07-02T17:04:00Z | SPY | 429.00 | -1 | Stop Market | Filled | -429.00 | Stop Price: 429.10 |
On July 1, 2021, the algorithm shorts SPY at $429.10 and then buys it back at $433.44 when the stop price is $433.43. The stop price is 1% above the market price. Note that $429.10 is not the market price when the algorithm places the first two orders. $429.10 is the fill price at the bid, but it's not far from the market price because 429.1 * 1.01 = 433.39. The fill price of the stop market order is $433.44, which, as expected, is higher than $433.43. The fill model assumes the worst-case scenario between the market price and the stop price. In this case, the worst-case scenario is the maximum of the market price and stop price.
On July 2, 2021, the algorithm buys SPY at $433.44 and sells it at $429 when the stop price is $429.10. The stop price is 1% below the market price. Note that $433.44 is not the market price when the algorithm places the second two orders. $433.44 is the fill price at the ask, but it's not far off from the market price because 433.44 * 0.99 = 429.11. The fill price of the stop market order is $429, which, as expected, is lower than $429.10. The fill model assumes the worst-case scenario between the market price and the stop price. In this case, the worst-case scenario is the minimum of the market price and stop price.
To reproduce these results, backtest the following algorithm: