| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -1.661 Tracking Error 0.128 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 |
from clr import AddReference
AddReference("System.Core")
AddReference("System.Collections")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
from System import *
from System.Collections.Generic import List
from QuantConnect import *
from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect.Data.UniverseSelection import *
from datetime import datetime, timedelta
import datetime
class ConsolidatorHelp(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 12, 1) # Set Start Date
self.SetEndDate(datetime.datetime.now())
self.SetCash(600000) # Set Strategy Cash
self.SetWarmup(20)
self.SetBenchmark("SPY")
self.UniverseSettings.Resolution = Resolution.Minute
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
self.UniverseSettings.Leverage = 2
self._changes = None
self.MinData = {}
self.dayMinData = {}
self.Data = {} # dictionary to hold rolling window for each symbol
self.window_hr = {}
self.windowmin = {}
# Set params for tracking stop losses
# -----------------------------------------------
self.activateStopCoef = 1 # activate trail when price rises 'x * ATR'
self.initialStopCoef = 3.5 # exit when price dips 'x * ATR'
self.trailStopCoef = 11 # exit when price dips 'x * ATR'(trailing)
self.trailActivationPrice = 0
self.trailActivationPriceSells = 0
self.trailStopActivated = False
self.trailStopActivatedSells = False
self.trailingStopLoss = 0
self.initialStopLoss = 0
self.trailingStopLossSells = 0
self.initialStopLossSells = 0
self.ADXtresh = 20
##___________FILTERS_________________##
def CoarseSelectionFunction(self, coarse ):
top = [x for x in coarse if x.HasFundamentalData
and 500 > x.Price > 40
and x.Volume > 500000]
self.Debug("len of coarse = " + str(len(top)))
return [x.Symbol for x in top]
def FineSelectionFunction(self, fine ):
top = [x for x in fine if x.ValuationRatios.PERatio > 20 and
x.ValuationRatios.TrailingDividendYield < .02 and
not x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.BasicMaterials and
not x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Energy]
top = sorted(top, key=lambda x: x.ValuationRatios.PERatio, reverse=True)
self.Debug("len of fine = " + str(len(top)))
return [x.Symbol for x in top][:5]
def OnData(self, data):
# Make sure indicators and rolling windows are ready
if not all([symbol.IsReady for symbol in self.dayMinData.values()]):
return
if not all([symbol.IsReady for symbol in self.MinData.values()]):
return
'''
for symbol, symbolData in self.dayMinData.items():
if not symbolData.IsReady:
return
for symbol, symbolData in self.MinData.items():
if not symbolData.IsReady:
return
for symbol in self.dayMinData.items():
if not (self.ema.IsReady and self.emaWindow.IsReady and \
self.rsi.IsReady and self.rsiWindow.IsReady and \
self.BB1UpperWindow.IsReady and self.BB1LowerWindow.IsReady and self.window_hr.IsReady):
return
self.Debug("Are WE GETTING DATA???")'''
#---------------------------------------------------------------_--_#
self.windowmin.Add(data[symbol])
self.window_hr.Add(data[symbol])
for symbol, value in self.dayMinData.items():
if data.ContainsKey(symbol) and \
data[symbol] != None:
self.Debug("AM I GETTING DATA???")
self.Debug(str(symbol))
for symbol, value in self.MinData.items():
if (value.windowmin[0].EndTime.hour < 15 or (value.windowmin[0].EndTime.hour == 15 and value.windowmin[0].EndTime.minute < 30)) and \
data.ContainsKey(symbol) and not self.Portfolio[symbol].Invested and \
value.windowmin[0].EndTime == self.Time and \
data[symbol] != None:
self.windowmin.Add(data[symbol])
self.window_hr.Add(data[symbol])
self.Debug("I am GETTING DATA")
self.Debug(str(symbol))
self.Debug("Windows ready one")
currBar = self.window_hr[0].Close
close_of_previous_bar = self.window_hr[1].Close
self.Log(f"Latest `window` close for {symbol}: {close_of_previous_bar}")
currMinCloseBar = self.windowmin[0].Close
close_of_previous_Min_bar = self.windowmin[1].Close
currema = self.emaWindow[0] # Current ema had index zero.
pastema = self.emaWindow[self.emaWindow.Count-1] # Oldest ema has index of window count minus 1.
self.Log("ema: {0} -> {1} ... {2} -> {3}".format(pastema.Time, pastema.Value, currema.Time, currema.Value))
currrsi = self.rsiWindow[0] # Current rsi had index zero.
pastrsi = self.rsiWindow[self.rsiWindow.Count-1] # Oldest rsi has index of window count minus 1.
currBBUpW = self.BB1UpperWindow[0] # Current bbup had index zero.
pastBBUpW = self.BB1UpperWindow[self.BB1UpperWindow.Count-1] # Oldest bbup has index of window count minus 1.
currBBlW = self.BB1LowerWindow[0] # Current bbdown had index zero.
pastBBlW = self.BB1LowerWindow[self.BB1LowerWindow.Count-1] # Oldest bbdown has index of window count minus 1.
self.diplus = self.ADX_hr.PositiveDirectionalIndex.Current.Value
self.diminus = self.ADX_hr.NegativeDirectionalIndex.Current.Value
if not (self.Portfolio.Invested and currema.Value > pastema.Value and self.diplus > self.ADXtresh):
if currrsi.Value < 30 and \
currMinCloseBar > currBBUpW:
self.SetHoldings(symbol, 0.5)
self.SetInitialStopsBuys()
if not (self.Portfolio.Invested and currema.Value < pastema.Value and self.diminus > self.ADXtresh):
if currrsi.Value > 70 and \
currMinCloseBar < currBBlW:
self.SetHoldings(symbol, -0.5)
self.SetInitialStopsSells()
# Add and remove stocks whenever we have changes to our universe
def OnSecuritiesChanged(self, changes):
self._changes = changes
for security in changes.AddedSecurities:
symbol = security.Symbol
# For 5 minute quotes
if symbol not in self.MinData:
self.MinData[symbol] = SymbolData(self, symbol)
# For daily quotes
if symbol not in self.dayMinData:
self.dayMinData[symbol] = DaySymbolData(self, symbol)
'''for security in changes.RemovedSecurities:
symbol = security.Symbol
if symbol in self.MinData: #self.Data:
symbolData = self.MinData.pop(symbol, None)
self.SubscriptionManager.RemoveConsolidator(symbol, symbolData.fiveMinutesConsolidator)
if symbol in self.DayMinData: #self.Data:
symbolData = self.DayMinData.pop(symbol, None)
self.SubscriptionManager.RemoveConsolidator(symbol, symbolData.HourConsolidator)'''
##__________5 min Quotes ______##
class SymbolData:
def __init__(self, algorithm, symbol):
self.algorithm = algorithm
self.symbol = symbol
self.windowmin = RollingWindow[QuoteBar](20)
fiveMinutesConsolidator = QuoteBarConsolidator(timedelta(minutes=5))
fiveMinutesConsolidator.DataConsolidated += self.fiveMinutesBarHandler
algorithm.SubscriptionManager.AddConsolidator(symbol, fiveMinutesConsolidator)# Register consolidator to get automatically updated with minute data
## Create nd Add Indicators to rolling window
self.ema = ExponentialMovingAverage(symbol, 20)
self.ema.Updated += self.emaUpdated
algorithm.RegisterIndicator(symbol, self.ema, fiveMinutesConsolidator)
self.emaWindow = RollingWindow[IndicatorDataPoint](21)
self.rsi = RelativeStrengthIndex(symbol, 14)
self.rsi.Updated += self.RsiUpdated
algorithm.RegisterIndicator(symbol, self.rsi, fiveMinutesConsolidator)
self.rsiWindow = RollingWindow[IndicatorDataPoint](21)
self.macd3 = MovingAverageConvergenceDivergence(3, 6, MovingAverageType.Exponential)
algorithm.RegisterIndicator(symbol, self.macd3, fiveMinutesConsolidator)
algorithm.SubscriptionManager.AddConsolidator(symbol, fiveMinutesConsolidator)
# -------------BB bands_________________#
self.BB1 = BollingerBands(20, 2)
self.BB1UpperWindow=RollingWindow[float](20)
self.BB1LowerWindow=RollingWindow[float](20)
self.BB1.Updated+=self.BB1Updated
algorithm.RegisterIndicator(symbol, self.BB1, fiveMinutesConsolidator)
# Update Indicator Windows
def emaUpdated(self, sender, updated):
'''Adds updated values to rolling window'''
if self.ema.IsReady:
self.emaWindow.Add(updated)
def RsiUpdated(self, sender, updated):
if self.rsi.IsReady:
self.rsiWindow.Add(updated)# Add updated indicator data to rolling window
def BB1Updated(self, sender, updated):
self.BB1UpperWindow.Add(sender.UpperBand.Current.Value)
self.BB1LowerWindow.Add(sender.LowerBand.Current.Value)
# Lock and load
@property
def IsReady(self):
if self.ema.IsReady and self.emaWindow.IsReady and \
self.rsi.IsReady and self.rsiWindow.IsReady and \
self.BB1UpperWindow.IsReady and self.BB1LowerWindow.IsReady:
return
# Make sure I can get stock values in Window.
def fiveMinutesBarHandler(self, sender, bar):
self.windowmin.Add(bar)
'''
self.algorithm.Debug(f"Data Consolidatoed for {self.symbol} \
at {bar.EndTime} with bar: {bar} and sma {self.sma} and trix {self.trix} and \
kelt {self.kelt.LowerBand}")
'''
##__________60 Mins Quotes ______##
class DaySymbolData:
def __init__(self, algorithm, symbol):
self.algorithm = algorithm
self.symbol = symbol
########## INDICATORS #################################
self.window_hr = RollingWindow[QuoteBar](20)
########### CONSOLIDATORS and WINDOWS ###########################
HourConsolidator = QuoteBarConsolidator(timedelta(hours=1)) #BarPeriod = TimeSpan.FromMinutes(10)
HourConsolidator.DataConsolidated += self.HourBarHandler
algorithm.SubscriptionManager.AddConsolidator(symbol, HourConsolidator)# Register consolidator to get automatically updated with minute data
##-------- OTHER INDICATORS ----------##
self.ATR_init = AverageTrueRange(symbol, 5)
self.ATR_trail = AverageTrueRange(symbol, 10)
self.ATR_activate = AverageTrueRange(symbol, 15)
self.ADX_hr = AverageDirectionalIndex(symbol, 10)
# Lock and load
@property
def IsReady(self):
return self.window_hr.IsReady
# Make sure I can get stock values in Window.
def HourBarHandler(self, sender, bar):
self.window_hr.Add(bar)
#self.algorithm.Debug(f"Data Consolidated for {self.symbol} \
#at {bar.EndTime} with bar: {bar} ")
# ========================================================================
# Set initial stop and activation level. Called after new position opened.
# ========================================================================
def SetInitialStopsBuys(self):
currBar = self.window_hr[0].Close
self.atrValue_init = self.ATR_init.Current.Value
self.atrValue_activate = self.ATR_activate.Current.Value
self.trailStopActivated = False
self.initialStopLoss = currBar - (self.atrValue_init * self.initialStopCoef)
self.trailActivationPrice = currBar + (self.atrValue_activate * self.activateStopCoef)
#self.PlotCharts() # Plot charts for debugging
def SetInitialStopsSells(self):
currBar = self.window_hr[0].Close
self.atrValue_initsells = self.ATR_init.Current.Value
self.atrValue_activatesells = self.ATR_activate.Current.Value
self.trailStopActivatedSells = False
self.initialStopLossSells = currBar + (self.atrValue_initsells * self.initialStopCoef)
self.trailActivationPriceSells = currBar - (self.atrValue_activatesells * self.activateStopCoef)