Overall Statistics
Total Trades
1504
Average Win
0.06%
Average Loss
-0.13%
Compounding Annual Return
-36.066%
Drawdown
47.100%
Expectancy
-0.604
Net Profit
-23.679%
Sharpe Ratio
-0.173
Probabilistic Sharpe Ratio
13.510%
Loss Rate
72%
Win Rate
28%
Profit-Loss Ratio
0.42
Alpha
0
Beta
0
Annual Standard Deviation
0.625
Annual Variance
0.391
Information Ratio
-0.173
Tracking Error
0.625
Treynor Ratio
0
Total Fees
$1504.00
Estimated Strategy Capacity
$64000.00
Lowest Capacity Asset
DATS XQYP146WRSDH
#region imports
from AlgorithmImports import *
#endregion
class TrialHighalgorithm(QCAlgorithm):
        
        class SymbolData(object):
    
            def __init__(self, symbol, algorithm):
                self.Symbol = symbol
                self.algorithm = algorithm # reference to the algorithm object so we can make a history call
                
                # this is the buy property that we will use in OnData to filter the symbols that meet our criteria
                self.buy = False
                self.sell = False
                self.symbolSma = SimpleMovingAverage(252) 
                
                # init windows, most recent value is self.highs[0], second most recent is self.highs[1], etc...
                self.lows = RollingWindow[float](252)
                self.highs = RollingWindow[float](252)
                self.opens = RollingWindow[float](252)
                self.closes = RollingWindow[float](252)
                try:
                    history = algorithm.History(symbol, 252, Resolution.Daily)
                    for index, row in history.loc[symbol].iterrows():
                        self.update(index, row["low"], row["high"], row["open"], row["close"])
                except:
                    pass 
            # update windows, sma
            def update(self, time, low, high, opn, close):
                self.lows.Add(low)
                self.highs.Add(high)
                self.opens.Add(opn)
                self.closes.Add(close)
                self.symbolSma.Update(time, close)
                
                # add [0] just so that list is not empty during initializing phase
                self.buy = (max((list(self.highs) + [0])[1:]) < self.highs[0]) & (self.closes[0] > self.opens[0])
                #self.sell = (min((list(self.lows) + [0])[1:]) > self.lows[0]) & (self.closes[0] < self.opens[0]) 
                self.sell=(min(list(self.lows))==self.lows[0])
        def Initialize(self):
            self.SetStartDate(2022, 1, 1)
            #self.SetEndDate(2020, 11, 11)
            self.SetCash(10000) 
            self.numberOfSymbols = 200
            
            self.res = Resolution.Daily
            
            self.averages = {}
            self.symbols = []
            self.sma = {}
            self.universe = {}
            self.selectedSymbols = []
            self.selectedSymbolss = []
            
            self.SPY = self.AddEquity('SPY', self.res).Symbol
            
            self.SetTimeZone(TimeZones.HongKong)
            self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
            
            self.AddUniverse(self.CoarseSelectionFunction)
            self.UniverseSettings.Resolution = self.res

        def CoarseSelectionFunction(self, coarse):

            filtered = [ x for x in coarse if (x.HasFundamentalData) and (x.Price > 1) and ( x.Volume > 500000) and (x.DollarVolume > 100000) ]
            filtered.sort(key=lambda x: x.DollarVolume, reverse=True)
            
            symbols = [ x.Symbol for x in filtered[:self.numberOfSymbols] ]
            
            for symbol in symbols:
                if symbol not in self.universe:
                    self.universe[symbol] = TrialHighalgorithm.SymbolData(symbol, self)
                    self.sma[symbol] =  self.universe[symbol].symbolSma
                
            return list(self.universe.keys())


        # this is called daily because our resolution is Resolution.Daily
        def OnData(self, data):
    
            # update all the securities in our universe using the latest hihg, open, close data
            for symbol in self.universe.keys():
                
                # make sure we have data, because sometimes we dont
                if self.Securities.ContainsKey(symbol) and self.Securities[symbol] != None:
                    
                    time = self.Time
                    low = self.Securities[symbol].Low
                    high = self.Securities[symbol].High
                    opn = self.Securities[symbol].Open
                    close = self.Securities[symbol].Close
                    
                    # update function
                    self.universe[symbol].update(time, low, high, opn, close)
            
            # now select all the symbols that meet the buy criteria (this is the 'buy' property of our symboldata object)
            self.selectedSymbols = [x for x in self.universe.keys() if self.universe[x].buy ]
            
           # for x in self.selectedSymbols:
            #    self.SetHoldings(x, 0.01)
            self.selectedSymbolss = [x for x in self.universe.keys() if self.universe[x].sell ]
            
            for x in self.selectedSymbolss:
                self.SetHoldings(x, -0.01)