| 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)