| 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 -0.906 Tracking Error 0.21 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
class DancingTanHorse(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019,1,1) # Set Start Date
self.SetEndDate(2021,1,1)
self.SetCash(100000)
self.UniverseSettings.Resolution = Resolution.Daily
#self.AddUniverse(self.CoarseSelection)
self.longSymbols = []
self.shortSymbols = []
self.entryPrices = {}
self.stopMarketTicket = {}
self.indicators = {}
stockPlot = Chart("Long Positions")
stockPlot.AddSeries(Series("Longs", SeriesType.Bar, 0))
self.AddChart(stockPlot)
stockPlot = Chart("Short Positions")
stockPlot.AddSeries(Series("Shorts", SeriesType.Bar, 0))
self.AddChart(stockPlot)
self.AddEquity("SPY", Resolution.Daily)
self.SetBenchmark("SPY")
self.Schedule.On(self.DateRules.EveryDay("SPY"), \
self.TimeRules.At(10, 00), \
self.EveryMarketOpen)
self.maxPositions = 5
self.numOfCoarse = 6 * self.maxPositions
self.stopLoss = 0.10
# def CoarseSelection(self, coarse):
# selectedByDollarVolume = sorted([x for x in coarse if x.Price > 1 and x.HasFundamentalData], key = lambda x: x.DollarVolume, reverse = True)
# universe = [x for x in selectedByDollarVolume]
# squeeze = {}
# for cf in universe:
# symbol = cf.Symbol
# if symbol not in self.indicators:
# self.indicators[symbol] = SymbolData(algorithm, symbol)
# # Updates the SymbolData object with current EOD price
# indicators = self.indicators[symbol]
# #indicators.update(cf.EndTime, cf.AdjustedPrice)
# if self.indicators[symbol].is_ready() and \
# self.indicators[symbol].bollinger.UpperBand.Current.Value < self.indicators[symbol].keltner.UpperBand.Current.Value and \
# self.indicators[symbol].bollinger.LowerBand.Current.Value > self.indicators[symbol].keltner.LowerBand.Current.Value:
# squeeze.append(symbol)
# # Sorts the values of the dict: we want those with least difference between the bollinger bands
# squeeze.sort(key=lambda x: x.Scale, reverse=False)
# for x in squeeze[:self.numOfCoarse]:
# self.Log('symbol: ' + str(x.symbol.Value) + ' scale: ' + str(x.scale))
# # we need to return only the symbol objects
# return [ x.symbol for x in values[:self.numOfCoarse]]
#this event fires whenever we have changes to our universe
def OnSecuritiesChanged(self, changes):
pass
def EveryMarketOpen(self):
pass
class SymbolData:
def __init__(self, algorithm, symbol):
self.algorithm = algorithm
self.symbol = symbol
self.bollinger = BollingerBands(20, 2, MovingAverageType.Simple)
self.keltner = KeltnerChannels(20, 1.5, MovingAverageType.Simple)
history = algorithm.History(symbol, 20, Resolution.Daily)
for bar in history.itertuples():
tradeBar = TradeBar(bar.time - timedelta(1), symbol, bar.open, bar.high, bar.low, bar.close, bar.volume, timedelta(1))
self.bollinger.Update(bar.time, bar.close)
self.keltner.Update(tradeBar)
def Scale(self):
return (self.bollinger.UpperBand.Current.Value - self.bollinger.LowerBand.Current.Value)
def is_ready(self):
return self.bollinger.IsReady and self.keltner.IsReady# ctrl + / to comment
# class DancingTanHorse(QCAlgorithm):
# def Initialize(self):
# self.SetStartDate(2019,1,1) # Set Start Date
# self.SetEndDate(2021,1,1)
# self.SetCash(100000)
# self.UniverseSettings.Resolution = Resolution.Daily
# self.AddUniverse(self.CoarseSelection)
# self.longSymbols = []
# self.shortSymbols = []
# self.entryPrices = {}
# self.stopMarketTicket = {}
# self.indicators = {}
# stockPlot = Chart("Long Positions")
# stockPlot.AddSeries(Series("Longs", SeriesType.Bar, 0))
# self.AddChart(stockPlot)
# stockPlot = Chart("Short Positions")
# stockPlot.AddSeries(Series("Shorts", SeriesType.Bar, 0))
# self.AddChart(stockPlot)
# self.AddEquity("SPY", Resolution.Daily)
# self.SetBenchmark("SPY")
# self.Schedule.On(self.DateRules.EveryDay("SPY"), \
# self.TimeRules.At(10, 00), \
# self.EveryMarketOpen)
# self.maxPositions = 5
# self.numOfCoarse = 6 * self.maxPositions
# self.stopLoss = 0.10
# def CoarseSelection(self, coarse):
# selectedByDollarVolume = sorted([x for x in coarse if x.Price > 1 and x.HasFundamentalData],
# key = lambda x: x.DollarVolume, reverse = True)
# universe = [x for x in selectedByDollarVolume]
# selectedSqueeze = []
# for coarse in universe:
# symbol = coarse.Symbol
# if symbol not in self.indicators:
# # 1. Call history to get an array of 20 days of history data
# history = self.History(symbol, 21, Resolution.Daily)
# #2. Adjust SelectionData to pass in the history result
# self.indicators[symbol] = SymbolData(history)
# self.indicators[symbol].update(self.Time, coarse.AdjustedPrice)
# if self.indicators[symbol].is_ready() and \
# self.indicators[symbol].bollinger.UpperBand.Current.Value < self.indicators[symbol].keltner.UpperBand.Current.Value and \
# self.indicators[symbol].bollinger.LowerBand.Current.Value > self.indicators[symbol].keltner.LowerBand.Current.Value:
# selectedSqueeze.append(symbol)
# #to sort by distance between bollinger bands look at the EmaCrossUniverseSelectionAlgorithm.py
# def EveryMarketOpen(self):
# pass
# def OnOrderEvent(self, orderEvent):
# pass
# def OnData(self, data):
# '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
# Arguments:
# data: Slice object keyed by symbol containing the stock data
# '''
# pass
# # if not self.Portfolio.Invested:
# # self.SetHoldings("SPY", 1)
# class SymbolData():
# #3. Update the constructor to accept a history array
# def __init__(self, history):
# self.bollinger = BollingerBands(20, 2, MovingAverageType.Simple)
# self.keltner = KeltnerChannels(20, 1.5, MovingAverageType.Simple)
# self.volatility = 0
# #4. Loop over the history data and update the indicatorsc
# for bar in history.itertuples():
# tradeBar = TradeBar(bar.Index[1], bar.Index[0], bar.open, bar.high, bar.low, bar.close, bar.volume, timedelta(1))
# self.bollinger.Update(bar.Index[1], bar.close)
# self.keltner.Update(tradeBar)
# def is_ready(self):
# return self.bollinger.IsReady and self.keltner.IsReady
# def update(self, time, value):
# return self.bollinger.Update(time, value)
# @property
# def ScaledDelta(self):
# return (self.bollinger.UpperBand.Current.Value - self.bollinger.LowerBand.Current.Value)
# # Your New Python File