| Overall Statistics |
|
Total Trades 12 Average Win 0.01% Average Loss -0.01% Compounding Annual Return -1.287% Drawdown 0.700% Expectancy 0.175 Net Profit -0.259% Sharpe Ratio -0.965 Probabilistic Sharpe Ratio 14.522% Loss Rate 50% Win Rate 50% Profit-Loss Ratio 1.35 Alpha 0 Beta 0 Annual Standard Deviation 0.009 Annual Variance 0 Information Ratio -0.965 Tracking Error 0.009 Treynor Ratio 0 Total Fees $12.00 Estimated Strategy Capacity $4000000000.00 Lowest Capacity Asset MU R735QTJ8XC9X |
import numpy as np
from datetime import datetime
import pandas as pd
class AppendingInvestedToCoasre(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2018, 6, 20)
self.SetEndDate(2018, 9, 1)
self.coarse_amount = 5
self.SetCash(25000)
self.AddUniverse(self.CoarseSelectionFunction)
self.UniverseSettings.Resolution = Resolution.Daily
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
self.Data= {}
self.stocks = []
def CoarseSelectionFunction(self, coarse):
sortedByDollarVolume = sorted(coarse, key=lambda c: c.DollarVolume, reverse=True)[:20]
coarse_stocks = [x.Symbol for x in sortedByDollarVolume if x.Price > 15 and x.DollarVolume >= 900000 and x.HasFundamentalData == True][:self.coarse_amount]
invested = [ x.Symbol for x in self.Portfolio.Values if x.Invested ]
self.stocks = np.unique(invested + coarse_stocks)
self.number_of_stocks_returned_from_coarse = len(self.stocks)
self.Plot('Symbols', 'coarse_stocks', len(coarse_stocks))
self.Plot('Symbols', 'invested', len(invested))
self.Plot('Symbols', 'stocks', len(self.stocks))
return self.stocks #this list appears to have what I want, but onData does not?
def OnSecuritiesChanged(self, changes):
for security in changes.AddedSecurities:
symbol = security.Symbol
if symbol not in self.Data:
self.Data[symbol] = SymbolData(self, symbol)
for security in changes.RemovedSecurities:
symbol = security.Symbol
if symbol in self.Data:
symbolData = self.Data.pop(symbol, None)
self.SubscriptionManager.RemoveConsolidator(symbol, symbolData.consolidator)
self.SubscriptionManager.RemoveConsolidator(symbol, symbolData.consolidatorMinute)
# =============== ON DATA ============================ #
def OnData(self, data):
selected = []
symbols_in_onData = []
symbol_values_in_onData = []
for symbol in self.Data.keys():
symbol_values_in_onData.append(symbol.Value)
symbols_in_onData.append(symbol)
symbolData = self.Data[symbol]
b1 = symbolData.Bars[0].Close > symbolData.Bars[1].Close
b2 = symbolData.Bars[1].Close > symbolData.Bars[2].Close
if b1 and b2:
selected.append(symbol)
# for sec in self.Portfolio.Keys: #holding percentage lowered to remove this as a factor
# if sec not in selected:
# self.SetHoldings(sec, 0)
invested = [ x.Symbol for x in self.Portfolio.Values if x.Invested ]
invested_symbols_in_onData = [ x for x in invested if x in symbols_in_onData]
self.Debug("====New Day======")
self.Debug(f"We had {len(symbols_in_onData)} symbols looped through onData, we are invested in {len(invested)} securities, {len(invested_symbols_in_onData)} invested symbols were found onData ")
self.Debug(f"{self.number_of_stocks_returned_from_coarse} stocks were returned from coasre, {len(symbols_in_onData)} stocks were in onData")
#I expect 5 securities from coarse + X number of securities I am invested in, i.e. 5+ 2 invested = 7 symbols looped through
for sec in selected:
self.SetHoldings(sec, 0.01)
#============= SYMBOL DATA CLASS ========================== #
class SymbolData:
def __init__(self, algorithm, symbol):
self.algorithm = algorithm
self.symbol = symbol
#self.emaOne = algorithm.EMA(symbol, 1, Resolution.Minute)
self.ema3 = algorithm.EMA(symbol, 3, Resolution.Daily)
self.ema4 = algorithm.EMA(symbol, 4, Resolution.Daily)
self.ema50 = algorithm.EMA(symbol, 50, Resolution.Daily)
self.ema200 = algorithm.EMA(symbol, 200, Resolution.Daily)
self.ema200D = algorithm.EMA(symbol, 200, Resolution.Daily)
self.ema200Window = RollingWindow[float](20)
self.bb = algorithm.BB(symbol, 20, 2, MovingAverageType.Simple, Resolution.Daily)
self.bbWindow = RollingWindow[float](5)
self.bb17 = algorithm.BB(symbol, 20, 1.5, MovingAverageType.Simple, Resolution.Daily)
self.bb17Window = RollingWindow[float](5)
self.bb17LowerBandWindow = RollingWindow[float](5)
self.momp = algorithm.MOMP(symbol, 30, Resolution.Daily)
self.mompWindow = RollingWindow[float](200)
self.rsi = algorithm.RSI(symbol, 14 , Resolution.Daily)
self.rsiWindow = RollingWindow[float](20)
self.macd = {} #do I need?
self.macd = algorithm.MACD(symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Daily)
self.macdWindow = RollingWindow[float](5)
self.macdHistogramWindow = RollingWindow[float](5)
#====== V-MACD =============
self.vwap12 = algorithm.VWAP(symbol, 12, Resolution.Daily) #12 period VWAP
self.vwap26 = algorithm.VWAP(symbol, 26, Resolution.Daily) #26 perios VWAP
self.vmacd = IndicatorExtensions.Minus(self.vwap12, self.vwap26) #vwap26 - vwap12
self.vmacdSignal = IndicatorExtensions.EMA(self.vmacd, 9)
self.vmacdHistogram = IndicatorExtensions.Minus(self.vmacd, self.vmacdSignal) #swap
self.vmacdHistogramWindow = RollingWindow[float](5)
self.close_window = RollingWindow[float](22)
self.Bars = RollingWindow[IBaseDataBar](22) # Rolling window for data bars
self.consolidator = TradeBarConsolidator(timedelta(days=1))
self.consolidator.DataConsolidated += self.OnDataConsolidated
algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator)
self.BarsWeek = RollingWindow[IBaseDataBar](22) # Rolling window for data bars
self.consolidatorWeek = TradeBarConsolidator(timedelta(days=1))
self.consolidatorWeek.DataConsolidated += self.OnDataConsolidatedWeek
algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidatorWeek)
self.BarsMinute = RollingWindow[IBaseDataBar](22) # Rolling window for data bars
self.consolidatorMinute = TradeBarConsolidator(timedelta(days=2))
self.consolidatorMinute.DataConsolidated += self.OnDataConsolidatedMinute
algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidatorMinute)
#=====History Calls========
history = algorithm.History(self.symbol, 25, Resolution.Daily).loc[self.symbol]
for time, row in history.iterrows():
tradebar = TradeBar(time, self.symbol, row.open, row.high, row.low, row.close, row.volume)
self.consolidatorMinute.Update(tradebar)
history = algorithm.History(self.symbol, 200, Resolution.Daily).loc[self.symbol]
for time, row in history.iterrows():
tradebar = TradeBar(time, self.symbol, row.open, row.high, row.low, row.close, row.volume)
self.consolidator.Update(tradebar)
self.consolidatorWeek.Update(tradebar)
self.vwap12.Update(tradebar)
self.vwap26.Update(tradebar)
# Warm up indicators
history = algorithm.History([symbol], 201, Resolution.Daily)
for time, row in history.loc[symbol].iterrows():
#self.emaOne.Update(time, row["close"])
self.ema200.Update(time, row["close"])
self.momp.Update(time, row["close"])
self.ema3.Update(time, row["close"])
self.ema4.Update(time, row["close"])
self.bb.Update(time, row["close"])
self.bb17.Update(time, row["close"])
self.rsi.Update(time, row["close"])
self.macd.Update(time, row["close"])
self.close_window.Add(row["close"]) #Per anwser it needs the close only
#Warm the Rolling Windows
if self.ema200.IsReady:
self.ema200Window.Add(self.ema200.Current.Value)
if self.rsi.IsReady:
self.rsiWindow.Add(self.rsi.Current.Value)
if self.bb.IsReady:
self.bbWindow.Add(self.bb.Current.Value)
if self.bb17.IsReady:
self.bb17Window.Add(self.bb17.Current.Value)
self.bb17LowerBandWindow.Add(self.bb17.LowerBand.Current.Value)
if self.macd.IsReady:
self.macdWindow.Add(self.macd.Current.Value)
self.macdHistogramWindow.Add(self.macd.Histogram.Current.Value)
self.vmacdHistogramWindow.Add(self.vmacdHistogram.Current.Value)
if self.momp.IsReady:
self.mompWindow.Add(self.momp.Current.Value)
history = algorithm.History([symbol], 200, Resolution.Daily)
for time, row in history.loc[symbol].iterrows():
self.ema200D.Update(time, row["close"])
# Consolidators
def OnDataConsolidated(self, sender, bar):
self.Bars.Add(bar)
def OnDataConsolidatedMinute(self, sender, bar):
self.BarsMinute.Add(bar)
def OnDataConsolidatedWeek(self, sender, bar):
self.BarsWeek.Add(bar)
@property
def IsReady(self):
return self.Bars.IsReady and self.BarsWeek.IsReady and self.rsi.IsReady and self.ema200.IsReady and self.macd.IsReady #and self.macdWindow.IsReady