Overall Statistics
Total Trades
8
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$159.84
from datetime import timedelta, time
import math

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Symbol Data

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
class SymbolData(object):
    
    def __init__(self, algorithm, symbol, criteriaDict):
        
        self.symbol = symbol
        self.symbolValue = symbol.Value
        
        self.algorithm = algorithm
        self.criteriaDict = criteriaDict
        
        #-- Trailing Stop
        self.lastPeriodMax = 0
        self.trailStopOrderTicket = None
        self.trailStopPrice = None


class ErrorSubmission_TrailStop(QCAlgorithm):
    
    
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    Iniitalization
    
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""    
    def Initialize(self):
        
        #-- Date Range
        self.SetStartDate(2020, 10, 1) # Set Start Date
        
        #-- Starting Equity
        self.SetCash(1000000)  # Set Strategy Cash # check if will be replaced

        #---------- Universe Selection -------------
        
        self.UniverseSettings.Resolution = Resolution.Minute
        self.UniverseSettings.ExtendedMarketHours = True  # test live if work
        self.maxSymbolsFromUniverseFilter = 30
        
        self.handpicked_SymbolList = [ 
                    Symbol.Create("SPY", SecurityType.Equity, Market.USA),
                    Symbol.Create("DNMR", SecurityType.Equity, Market.USA),
                    Symbol.Create("PLTR", SecurityType.Equity, Market.USA),
                    Symbol.Create("GME", SecurityType.Equity, Market.USA),
                    ]

        self.AddUniverse(self.CoarseSelectionFilter)


        #---------- Alpha Generation -------------

        #-- Criteria Settings
        self.criteriaDict = {
        }


        #---------- Portfolio Construction -------------
        
        self.maxSymbolsToTrade = 10  # maxSymbols to trade
        self.symbolDict = {} # list which stores symbols (refreshes with universe updates + handpick selection)
        self.symbolWithPositionDict = {}  # list which stores symbols with position
        self.potentialTradeDict = {}  # temp list to store potential symbols to trade
        
        for symbol in self.handpicked_SymbolList:
            if symbol not in self.symbolDict:
                self.AddEquity(symbol.Value, Resolution.Minute)
                self.symbolDict[symbol] = SymbolData(self,symbol,self.criteriaDict)

        
        #---------- Risk Management -------------
        self.useTrailStop = True
        self.trailStopPercentage = 0.25
        
        
        #---------- Schedule to run calculation -------------
        self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(TimeSpan.FromMinutes(2)), self.runAlgo)



    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    # Coarse Selection Filter
       
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    def CoarseSelectionFilter(self, coarse):
        
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        finalFilter = sortedByDollarVolume[:5]

        for coarseObject in finalFilter:
            symbol = coarseObject.Symbol
        
        return [x.Symbol for x in finalFilter]
        

    
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    runAlgo - Main execution function for the system
        - function is triggered every x minute to check for signal and execute trades
    
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""    
    def runAlgo(self):
        
        #------------------------ Exit Signals ------------------------
        #-- Trailing Stop
        if self.useTrailStop:

            for symbol in self.symbolWithPositionDict:            
                
                symbolData = self.symbolDict[symbol]
                symbolPrice = self.Securities[symbol].Close
        
                # Trailstop order not yet set
                if symbolData.trailStopOrderTicket is None:
                    # self.Debug(symbol.Value + "  set trailstop")
                    if self.Portfolio[symbol].Invested:
                        quantity = -self.Portfolio[symbol].Quantity
                        price = (1 - self.trailStopPercentage) * symbolPrice
                        symbolData.trailStopOrderTicket = self.StopMarketOrder(symbol.Value, quantity, price)  
                        self.Debug(f"Order for {symbol} quantity {quantity} at price {price}; status: {symbolData.trailStopOrderTicket.Status}")
                    
                # Trailstop order exist, adjust it if price moves higher
                else:
                    if symbolPrice > symbolData.lastPeriodMax:
                        symbolData.lastPeriodMax = symbolPrice
                        updateFields = UpdateOrderFields()
                        updateFields.StopPrice = (1 - self.trailStopPercentage) * symbolPrice
                        self.Debug(f"Stop: {updateFields.StopPrice}; OrderTicket Status: {symbolData.trailStopOrderTicket.Status == OrderStatus.Invalid}")
                        self.Quit()
                        return
                        #self.Debug(symbol.Value + " moving symbolLastPeriodMax up " + str(symbolPrice) + "   "  + str(updateFields.StopPrice))
                        symbolData.trailStopOrderTicket.Update(updateFields) 
                        return
        
            
        #------------------------ Entry Signals ------------------------
        self.potentialTradeDict.clear()  # reset potentialTradeDict
        
        # for symbol in self.Portfolio.Keys:
        for symbol in self.symbolDict:
            if symbol not in self.symbolWithPositionDict:  # run check only if symbol has no position
                currentClose = self.Securities[symbol].Close

                finalEntrySignal = 1
    
                #-- append symbol to potential tradelist
                if finalEntrySignal > 0:
                    self.potentialTradeDict[symbol] = finalEntrySignal


        #------------------------ Portfolio Construction + Execution ------------------------

        #-- remove symbols from potentialTradeDict that already has a position
        items_to_be_removed = []
        for symbol in self.potentialTradeDict:
            if symbol in self.symbolWithPositionDict.keys():
                items_to_be_removed.append(symbol)
        
        for symbol in items_to_be_removed:
                del self.potentialTradeDict[symbol] 

        #-- Total symbols (currentPosition + newly shortlisted) < maxSymbolsToTrade
        if len(self.symbolWithPositionDict) + len(self.potentialTradeDict) <= self.maxSymbolsToTrade:
            # trade all symbols in the potentialTradeDict and add them to the symbolInPositionList
            for symbol, signal in self.potentialTradeDict.items():
                # calculate posSize
                posSize = self.getPosSize(symbol) 
            
                if(posSize != 0):
                    tag = "Sig: {:.2f}".format(signal)
                    ticket = self.MarketOrder(symbol, posSize,False,tag)
                    # add to positionDict
                    
                    self.symbolWithPositionDict[symbol] = posSize
                    
            
        else:
            pass
        


    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    # getPosSize

    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    def getPosSize(self, symbol):

        dollarAllocation = self.Portfolio.TotalPortfolioValue//self.maxSymbolsToTrade  

        symbolPrice = self.Securities[symbol].Price
        posSize = math.floor(dollarAllocation/symbolPrice) if symbolPrice>0 else 0

        return posSize
            
        
        
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    OnSecuritiesChanged
       - this event fires whenever we have changes to our universe
       
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    def OnSecuritiesChanged(self, changes):
        # self.Log("OnSecuritiesChanged: " + str(self.Time))
        
        for security in changes.RemovedSecurities:
            if ((security.Symbol in self.symbolDict) and (security.Symbol not in self.handpicked_SymbolList) and (security.Symbol not in self.symbolWithPositionDict)):
                # self.Log("Removing " + security.Symbol.Value + " from symbolDict")
                del self.symbolDict[security.Symbol] 

        for security in changes.AddedSecurities:
            if security.Symbol not in self.symbolDict:
                # self.Log("Adding " + security.Symbol.Value + " to symbolDict")
                self.AddEquity(security.Symbol.Value, Resolution.Minute)
                self.symbolDict[security.Symbol] = SymbolData(self,security.Symbol,self.criteriaDict)



    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    OnData
    
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""    
    def OnData(self, data):
        pass