Overview

Tracking and managing orders is an important part of an algorithmic trading strategy. Intelligent order management encourages discipline and a deep understanding of your algorithm. Through the QuantConnect API you can get order fields, update their values and cancel pending orders. This can be useful for lowering trading costs and improving order fills.

When you place a trade you receive an OrderTicket for you to access the order. This allows you to safely (asynchronously) update and cancel the order while in live trading. In live trading you cannot assume order updates are processed successfully as the brokerage may have already filled the trade.

You can place several types of orders including:

Supported Order Types
Market Order MarketOrder("SPY", 100);
Limit Order var ticket = LimitOrder("SPY", 100, 100.10m);
Stop Market Order var ticket = StopMarketOrder("SPY", 100, 100.10m);
Stop Limit Order var ticket = StopLimitOrder("SPY", 100, 100.12m, 99.5m);
Market On Open Order var ticket = MarketOnOpen("SPY", 100);
Market On Close Order var ticket = MarketOnClose("SPY", 100);

Updating Orders

Once you have an order ticket you can use it to get order fields. In C# it looks like:

var currentStopPrice = _ticket.Get(OrderField.StopPrice);

Or update the order fields (LimitPrice, StopPrice, Tag or Quantity):

_ticket.Update(new UpdateOrderFields
{
    LimitPrice = newLongLimit,
    Tag = "Update #" + (longOrder.UpdateRequests.Count + 1)
});

You can also cancel your order if required:

_ticket.Cancel();

In Python, you can update order like this:

# Retrive the 'StopPrice' for an order from the ticket
currentStopPrice = _ticket.Get(OrderField.StopPrice)
# update the order fields (LimitPrice, StopPrice, Tag or Quantity)
updateOrderFields = UpdateOrderFields()
updateOrderFields.LimitPrice = newLongLimit
updateOrderFields.Tag = "Update #{0}".format(len(_ticket.UpdateRequests) + 1)
_ticket.Update(updateOrderFields)
# cancel your order if required
_ticket.Cancel()

In the video below we demonstrate putting it all together to create a moving take-profit order which gradually decreases its profit target as time passes.

Full Python Example

This is a complete port from C# to Python of this Quick Start Lesson.

```Lesson 6 - Tracking and Managing Orders: 
Immediately place 4 orders. Plot end of day price of each order in 'Order Tickets' plot. Debug log filled orders.
```
import numpy as np
from decimal import Decimal

class BasicTemplateAlgorithm(QCAlgorithm):

    def Initialize(self):
        self._limitTicket = None
        self._stopMarketTicket = None
        self._stopLimitTicket = None
        self.SetCash(25000)
        self.SetStartDate(2009,1,1)
        self.SetEndDate(2009,6,1)
        self.spy = self.AddEquity("SPY", Resolution.Minute).Symbol
        
    def OnData(self, slice):
        if self._limitTicket is None:
        
            self.MarketOrder(self.spy, 100)
            
            self._limitTicket = self.LimitOrder(
                self.spy, 
                100, 
                slice["SPY"].Close * Decimal(0.9), 
                "limit order")
                
            self._stopMarketTicket = self.StopMarketOrder(
                self.spy,
                -100,
                slice["SPY"].Close * Decimal(0.95),
                "stop market")
                
            self._stopLimitTicket = self.StopLimitOrder(
                self.spy,
                -100,
                slice["SPY"].Close * Decimal(0.9),
                slice["SPY"].Close * Decimal(0.8),
                "stop market")


    def OnEndOfDay(self):
        ```End of each day, plot our asset & order prices```
        if self._limitTicket is None:
            return
        
        self.Plot("Order Tickets", "SPY", self.Portfolio['SPY'].Price)
        
        if self._stopMarketTicket.Status != OrderStatus.Filled:
            self.Plot("Order Tickets", "Stop Price", 
                      self._stopMarketTicket.Get(OrderField.StopPrice))
            
        if self._stopLimitTicket.Status != OrderStatus.Filled:
            self.Plot("Order Tickets", "Limit Price", 
                      self._stopLimitTicket.Get(OrderField.LimitPrice))

    def OnOrderEvent(self, OrderEvent):
        ```Event when the order is filled. Debug log the order fill. :OrderEvent:``` 
        
        if OrderEvent.FillQuantity == 0:
            return
        
        fetched = self.Transactions.GetOrderById(OrderEvent.OrderId)
        
        self.Debug("{} was filled. Symbol: {}. Quantity: {}. Direction: {}"
                   .format(str(fetched.Type), 
                           str(OrderEvent.Symbol), 
                           str(OrderEvent.FillQuantity), 
                           str(OrderEvent.Direction)))

Contributors

jaredbroad jcandan jingwu74 gaviles

Contribute

Comments


  1. Olivier Van Parys says:

    Thanks Jared, the Python example really helps. Quick question, in the example you show that OrderEvent has 3 define “sub objects” one call call: Symbol, FillQuantity, Direction. In general where can we find information about the different sub objects? I went on github and ran a search on OrderEvent filtering for Python but this is like browsing across a flea market hoping to find something of interest. What is the best way to find out this type of info in general? Do you have an online drop down menu with all possible option that I can activate as I type?

  2. Olivier Van Parys says:

    Another question regarding the order execution , when using hourly data and submitting a stop order using a multiple of the close or open price as in your example , shall we assume that AT BEST such order will be filled in the next following bar/time slice? Logically the answer should be yes but just wanted to be sure

Sign In to comment in this post.