Overall Statistics
Total Trades
19
Average Win
0%
Average Loss
0%
Compounding Annual Return
361.927%
Drawdown
1.000%
Expectancy
0
Net Profit
1.549%
Sharpe Ratio
80.254
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
2.508
Beta
0.209
Annual Standard Deviation
0.045
Annual Variance
0.002
Information Ratio
-10.344
Tracking Error
0.156
Treynor Ratio
17.194
Total Fees
$19.00
Estimated Strategy Capacity
$14000000.00
Lowest Capacity Asset
PEP R735QTJ8XC9X
from AlgorithmImports import *

'''
    Class to handle bracket orders
'''
class BracketOrder:
    def __init__(self, algorithm, orderId, symbol, parentTicket, totQuantity, stopPrice, profitPrice):
        self.algorithm = algorithm

        self.parentId = orderId
        self.symbol = symbol
        self.parentTicket = parentTicket
        self.totQuantity = totQuantity
        self.stopPrice = stopPrice
        self.profitPrice = profitPrice

        # Initialize future properties
        self.filledQuantity = 0
        self.stopOrderTicket = None
        self.profitOrderTicket = None
    
    '''
        Handle order changes

        Orderstatus enum:
        https://www.quantconnect.com/docs/algorithm-reference/trading-and-orders#Trading-and-Orders-Tracking-Order-Events
    '''
    def HandleOrderChange(self, orderEvent):
        eventFillQuantity = orderEvent.FillQuantity

        # If the orderstatus is PartiallyFilled or Filled it will have a filledQuantity > 0
        if (eventFillQuantity > 0):
            self.filledQuantity += eventFillQuantity

            # Place/add to stop order (negative because we are selling)
            self.PlaceStopOrder(-eventFillQuantity)

            # Place/add to profit order
            self.PlaceProfitOrder(eventFillQuantity)
    
    '''
        Place/add to stop market order when the parent order is (partially) filled
    '''
    def PlaceStopOrder(self, stopQuantity):
        # Create new profit order ticket if non exists
        if (self.stopOrderTicket is None):
            self.stopOrderTicket = self.algorithm.StopMarketOrder(self.symbol, stopQuantity, self.stopPrice)
            self.algorithm.bracketOrders[self.stopOrderTicket.OrderId] = self
            self.algorithm.Debug(f"AFTER STOP ORDER, {self.algorithm.bracketOrders.keys()}")

        # Update existing profit order ticket
        updateSettings = UpdateOrderFields()
        updateSettings.Quantity = stopQuantity
        response = self.stopOrderTicket.Update(updateSettings)


    '''
        Place/add to profit taking order when the parent order is (partially) filled
    '''
    def PlaceProfitOrder(self, profitQuantity):
        # Create new profit order ticket if non exists
        if (self.profitOrderTicket is None):
            self.profitOrderTicket = self.algorithm.LimitOrder(self.symbol, profitQuantity, self.profitPrice)
            self.algorithm.bracketOrders[self.profitOrderTicket.OrderId] = self

        # Update existing profit order ticket
        updateSettings = UpdateOrderFields()
        updateSettings.Quantity = profitQuantity
        response = self.profitOrderTicket.Update(updateSettings)    
from AlgorithmImports import *
from BracketOrder import BracketOrder

class TestingOrders(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2020, 5, 5)  # Set Start Date
        self.SetEndDate(2020, 5, 10)  # Set End Date
        self.SetCash(100000)  # Set Strategy Cash

        # Add initial assets
        self.openingBarDict = {}
        self.assets = ["GOOG","AMZN", "JNJ", "PEP", "BAC"]
        for asset in self.assets:
            self.AddEquity(asset, Resolution.Minute).SetDataNormalizationMode(DataNormalizationMode.Raw)
        
        # Initiate bracket order handling dictionary
        self.bracketOrders = {}

    def OnData(self, data: Slice):
        """OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
            Arguments:
                data: Slice object keyed by symbol containing the stock data
        """

        for bar in data.Bars.Values:
            if (bar.Time.hour == 9 and bar.Time.minute == 30):
                ticker = bar.Symbol
                # Create stop limit order on break of max open/close
                placementPrice = max(bar.Close, bar.Open)
                limitPrice = placementPrice + 0.05
                qty = 10
                parentTicket = self.StopLimitOrder(ticker, qty, placementPrice, limitPrice) # Can I await this and the next line
                self.bracketOrders[parentTicket.OrderId] = BracketOrder(self, parentTicket.OrderId, parentTicket.Symbol, parentTicket, qty, placementPrice - 1, placementPrice + 1) # Can I await this
        
    def OnOrderEvent(self, orderEvent: OrderEvent):
        # Check if the order event ID is allready in the bracket order dict
        # If not, create a new BracketOrder object
        self.Debug(f"Length: {len(self.bracketOrders)}")
        #bracketOrder = self.bracketOrders[orderEvent.OrderId] --- CRASHES BECAUSE ORDER TICKET ID IS NOT A KEY YET