Overall Statistics
Total Trades
500
Average Win
2.31%
Average Loss
-7.12%
Compounding Annual Return
52.124%
Drawdown
64.300%
Expectancy
0.043
Net Profit
75.216%
Sharpe Ratio
1.037
Probabilistic Sharpe Ratio
39.401%
Loss Rate
21%
Win Rate
79%
Profit-Loss Ratio
0.32
Alpha
0.668
Beta
-0.362
Annual Standard Deviation
0.644
Annual Variance
0.414
Information Ratio
0.99
Tracking Error
0.674
Treynor Ratio
-1.843
Total Fees
$2207.08
Estimated Strategy Capacity
$870000.00
Lowest Capacity Asset
HILS XV2E35288YG5
#region imports
from AlgorithmImports import *
#endregion
import datetime #import timedelta, time

import math
from QuantConnect.Data.UniverseSelection import * 
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel

FAST = 10; SLOW = 2000; THRESOLD = 30;
FASTER = 1; SLOWER = 60;


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

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
class SymbolData(object):
    
    def __init__(self, algorithm, symbol, criteriaDict):
        
        self.symbol = symbol
        self.symbolValue = symbol.Value
        self.macd = MovingAverageConvergenceDivergence( FAST, SLOW, MovingAverageType.Simple)
        self.sma = MovingAverageConvergenceDivergence( FASTER, SLOWER, MovingAverageType.Simple)
        self.smav = SimpleMovingAverage(30)
        self.is_uptrend = False
        
        self.algorithm = algorithm
        self.criteriaDict = criteriaDict
        
        self.highestTrailStopPrice = -1
        self.tradeLock = False
        self.current = None
        self.smaDictionary = {}
        self.selectedSymbols = {}
        self.avg = {}
        self.BuyIn = {}
    def update(self, time, value):
        if self.smav.Update(time, value):
            smav = self.smav.Current.Value
               
            self.is_uptrend = smav > 500000

            
        
     
        

class ErrorSubmission_TrailStop(QCAlgorithm):
     
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    Iniitalization
    
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""    
    def Initialize(self):
        
        #-- Date Range
        self.SetStartDate(2021, 3, 1) # Set Start Date
        self.SetEndDate(2022, 7, 4) # Set End Date
        #-- Starting Equity
        self.SetCash(10000)  # Set Strategy Cash # check if will be replaced
        self.UniverseSettings.Resolution = Resolution.Minute
        self.AddUniverse(self.CoarseFilterSelection, self.FineFilterSelection)

        #---------- Universe Selection -------------
        
       
        
        self.handpicked_SymbolList = [ 
                    
                    #Symbol.Create("AGRX", SecurityType.Equity, Market.USA),
                    #Symbol.Create("AGRI", SecurityType.Equity, Market.USA),
                    #Symbol.Create("COSM", SecurityType.Equity, Market.USA),
                    #Symbol.Create("HCDI", SecurityType.Equity, Market.USA),
                    #Symbol.Create("HILS", SecurityType.Equity, Market.USA),
                    #Symbol.Create("KAVL", SecurityType.Equity, Market.USA),
                    #Symbol.Create("LLL", SecurityType.Equity, Market.USA),
                    #Symbol.Create("MITQ", SecurityType.Equity, Market.USA),
                     ]

      

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

        #-- Criteria Settings
        self.criteriaDict = {
        }
        self.averages = {}
        self.smavolume = {}


        #---------- 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, Market.USA)#, True, 1, True)
                self.symbolDict[symbol] = SymbolData(self, symbol, self.criteriaDict)

        

        #-----------On Ordered Events-----------
        
        #symbolData = self.symbolDict[symbol]
        #---------- Schedule to run calculation -------------
        #self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.Every(TimeSpan.FromMinutes(10)), self.runAlgo)

        #-----------Trading Volume Oscillator---------
        
        self.vo ={}
        self.SetWarmUp(SLOW, Resolution.Minute)
        self.sm = {}
        self.smavol = {}
        self.BuyIn = {}
        
     
  
        
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    OnData
    
    """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""    
    def OnSecuritiesChanged(self, changes):
        # self.Log("OnSecuritiesChanged: " + str(self.Time))
        self.Log(f'New Securities Added: {[security.Symbol.Value for security in changes.AddedSecurities]}')
        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)
                self.averages[security.Symbol] = SymbolData(self,security.Symbol,self.criteriaDict)
                
                #self.smavolume[security.Symbol] = self.SMA(security.Symbol, 30, Resolution.Daily)
    def OnData(self, data):
        if self.IsWarmingUp: return
        
        for symbol in self.symbolDict:
            symbolData = self.symbolDict[symbol]
            
            

            if data.Bars.ContainsKey(symbol):
                symbolData.macd.Update(data[symbol].EndTime, data[symbol].Volume)
                symbolData.sma.Update(data[symbol].EndTime, data[symbol].Price)
                symbolData.smav.Update(data[symbol].EndTime, data[symbol].Volume)

                if symbolData.smav.IsReady and symbolData.macd.Slow.Current.Value > 0:
                    self.vo[symbol] = symbolData.macd.Fast.Current.Value / symbolData.macd.Slow.Current.Value
                    self.sm[symbol] = symbolData.sma.Fast.Current.Value / symbolData.sma.Slow.Current.Value
                    self.smavol[symbol] = symbolData.smav.Current.Value
                else:
                    self.vo[symbol] = -1
                    self.sm[symbol] = -1
            else:
                self.vo[symbol] = -1
                self.sm[symbol] = -1
            # Updates the SymbolData object with current EOD price
            
        rising = []            
        selected = []

        for symbol in self.symbolDict:
            symbolData.CurrentPrice = self.Securities[symbol].Price
            if symbol not in selected and self.vo[symbol] > THRESOLD and self.sm[symbol] > 1.05 and self.smavol[symbol] > 500000:
                selected.append(symbol)
                self.BuyIn[symbol] = symbolData.CurrentPrice
        #if len(selected) == 0: 
            #self.Liquidate() 

        #for symbol in rising:
           #symbolData = self.symbolDict[symbol]
            #symbolData.CurrentPrice = self.Securities[symbol].Price
            #if (self.BuyIn[symbol] * 1.5) < symbolData.CurrentPrice:
             #   selected.append(symbol)
                #self.Debug("2nd")
                #self.Debug(symbol)    
    
        #else:
        for symbol in selected:
            symbolData = self.symbolDict[symbol]
            symbolData.CurrentPrice = self.Securities[symbol].Price
            if not symbolData.tradeLock and not self.Portfolio[symbol].Invested:
                symbolData.BuyIn = symbolData.CurrentPrice 
                symbolData.current = self.Time
                cash = self.Portfolio.Cash
                available = (cash *.25)
                purchase = math.floor(available / symbolData.CurrentPrice)
                
                self.MarketOrder(symbol, -purchase)
                self.Debug(symbol)
                self.Debug("Volume")
                self.Debug(purchase)
                self.Debug(symbolData.macd.Fast.Current.Value)
                self.Debug(symbolData.macd.Slow.Current.Value)
                self.Debug("Price")
                self.Debug(symbolData.sma.Fast.Current.Value)
                self.Debug(symbolData.sma.Slow.Current.Value)
                self.Debug("Average")
                self.Debug(symbolData.smav.Current.Value)

                self.AddEquity(symbol.Value, Resolution.Minute)
                self.symbolWithPositionDict[symbol] = SymbolData(self,symbol,self.criteriaDict)
            else:
                if self.Securities[symbol].Price > symbolData.highestTrailStopPrice:
                
                    symbolData.highestTrailStopPrice = self.Securities[symbol].Price


                #for symbol in selected:
                    #self.Debug("buy")
                    #self.Debug(symbol)
                    #self.Debug(self.vo[symbol])
                        #spynum = self.CalculateOrderQuantity(sec, 1)
                        #self.stopMarketTicket = self.StopMarketOrder(sec, spynum, 0.95 * self.Securities[sec].Close)
      
        for symbol in list(self.symbolWithPositionDict):
            symbolData = self.symbolDict[symbol]
            if self.Securities[symbol].Price < symbolData.BuyIn * .92 or self.Securities[symbol].Price > symbolData.BuyIn * 1.2 or (self.Time - symbolData.current).days == 14: # self.Securities[symbol].Price < symbolData.highestTrailStopPrice * .9 
                self.SetHoldings(symbol, 0)
                symbolData.tradeLock = True
                #self.handpicked_SymbolList.pop(symbol)

                #self.Debug("sell")
                #self.Debug(symbol)
                #self.Debug(self.vo[symbol])

        
        
#lass LiquidValueUniverseSelectionModel(FundamentalUniverseSelectionModel):
    
    #def __init__(self):
        #super().__init__(True, None)
        #self.lastMonth = -1   
        
        #self.volumeBySymbol = {}
        #self.criteriaDict = {}
        
        

        
    def CoarseFilterSelection(self, coarse):
     
        # update once per month
        #if self.lastMonth == algorithm.Time.month:
                #return Universe.Unchanged
        #self.lastMonth = algorithm.Time.month
        
        # sort by dollar volume and if they have fundamental Data, in decending order
        filtered = [ x for x in coarse]# if x.Price < 30]

        
        return [x.Symbol for x in filtered]
        

    def FineFilterSelection(self, fine):
        sortedByShares = sorted(fine, key = lambda f: f.CompanyProfile.SharesOutstanding, reverse = True)
        universe = [f for f in sortedByShares if f.CompanyProfile.SharesOutstanding < 15000000 and f.MarketCap < 2000000000]
        '''
        fine = [x for x in universe if x.EarningReports.FileDate + timedelta(days=0) > self.Time > x.EarningReports.FileDate + timedelta(days=3) 
                            and x.EarningReports.FileDate != datetime.time()]
        
        
        ## Iterate through symbols
        for symbol in fine:

            history = self.History(symbol, 20, Resolution.Daily)
            ## Find hsitory for specific symbol
            symbolVolumeHistory = history.loc[str(symbol)]

            ## Create SMA for symbol and register it with algorithm
            symbolSMA = SimpleMovingAverage(20)

            ## Iterate through historical data
            for tuple in symbolVolumeHistory.itertuples():
                ## Update SMA with data time and volume
                symbolSMA.Update(tuple.Index, tuple.volume)
                self.Debug(f'Updating {symbol.Value} SMA...')

            ## Add SMA to dictionary so you can access it later
            self.smaDictionary[symbol] = symbolSMA

        ## Perform SMA filtering conditions and select/return the symbols you want to add to your universe
        ## Fine Selection will use only these ones
        
        selectedSymbols = [x for x in fine if self.smaDictionary[symbol].symbolSMA > 50000]
        
        '''
        return [x.Symbol for x in universe]