| Overall Statistics |
|
Total Trades 395 Average Win 0.11% Average Loss -0.11% Compounding Annual Return 1.744% Drawdown 3.700% Expectancy -0.063 Net Profit 0.185% Sharpe Ratio 0.172 Probabilistic Sharpe Ratio 38.487% Loss Rate 53% Win Rate 47% Profit-Loss Ratio 0.98 Alpha 0.515 Beta -1.017 Annual Standard Deviation 0.14 Annual Variance 0.02 Information Ratio -2.714 Tracking Error 0.169 Treynor Ratio -0.024 Total Fees $395.00 |
class VerticalOptimizedThrustAssembly(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019, 10, 12) # Set Start Date
self.SetEndDate(2019, 11, 19)
self.SetCash(100000) # Set Strategy Cash
self.UniverseSettings.Resolution = Resolution.Daily
self.AddUniverse(self.CoarseSelectionFunction)
self.symbolDataBySymbol = {}
def CoarseSelectionFunction(self, coarse):
sortedCoarse = sorted(coarse, key=lambda c:c.DollarVolume, reverse=True)
liquidSymbols = [c.Symbol for c in sortedCoarse][:500]
symbols = [s for s in liquidSymbols if s not in self.symbolDataBySymbol]
history = self.History(symbols, 252, Resolution.Daily)
if not history.empty:
history = history.close.unstack(0)
for symbol in symbols:
if str(symbol) not in history:
continue
df = history[symbol].dropna()
if not df.empty:
self.symbolDataBySymbol[symbol] = SymbolData(self, symbol, df)
for x in coarse:
symbol = x.Symbol
if symbol in self.symbolDataBySymbol:
self.symbolDataBySymbol[symbol].Update(x.EndTime, x.AdjustedPrice)
selectedSymbols = [symbol for symbol, symbolData in self.symbolDataBySymbol.items() if symbolData.HasNewMax]
return selectedSymbols
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
symbol = security.Symbol
self.MarketOrder(symbol, 100)
for security in changes.RemovedSecurities:
symbol = security.Symbol
self.Liquidate(symbol)
class SymbolData:
def __init__(self, algorithm, symbol, history):
self.symbol = symbol
self.max = Maximum(252)
self.maxWindow = RollingWindow[IndicatorDataPoint](2)
self.max.Updated += self.OnMax
for time, close in history.iteritems():
self.Update(time, close)
def OnMax(self, sender, updated):
if self.max.IsReady:
self.maxWindow.Add(updated)
def Update(self, time, close):
self.max.Update(time, close)
@property
def HasNewMax(self):
if self.maxWindow.IsReady:
return self.maxWindow[0] > self.maxWindow[1]
else:
return False