| Overall Statistics |
|
Total Trades 92 Average Win 0.00% Average Loss 0.00% Compounding Annual Return 0.003% Drawdown 0.000% Expectancy 0.026 Net Profit 0.000% Sharpe Ratio -2.727 Probabilistic Sharpe Ratio 31.343% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 0.71 Alpha -0.001 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -26.171 Tracking Error 0.095 Treynor Ratio -0.51 Total Fees $92.00 |
class ResistanceTachyonCoreWave(QCAlgorithm):
def Initialize(self):
# Set the start and end date
self.SetStartDate(2019, 3, 8)
self.SetEndDate(2019, 3, 13)
# Set the cash amount
self.SetCash(100000000)
# Call coarse and fine universe
self.UniverseSettings.Resolution = Resolution.Minute
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
# Initialize symbol data dictionary
self.symbol_data_by_symbol = {}
# Initialize 1 minute EMA dictionaries
self.ema_short_by_symbol = {}
self.ema_long_by_symbol = {}
self.ema_longer_by_symbol = {}
# Initialize 5 minute EMA dictionaries
self.ema_nine_five = {}
self.ema_eighteen_five = {}
self.ema_thirtysix_five = {}
# Initialize stop market order dictionaries
self.highestPrice = {}
self.stopMarketTicket = {}
self.stopMarketOrderFillTime = {}
# Checks if the data has passed through an adequate number of times
self.passed_once = {}
self.minutes_stayed_in = {}
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(15, 55), self.BeforeMarketClose)
self.breakout_in_last_mins = {}
self.daily_open = {}
self.done_open = {}
self.ema_short_by_symbol = {}
self.low_less_than = {}
def OnSecuritiesChanged(self, changes):
self.passed_once = {}
for symbol in changes.RemovedSecurities:
data = self.symbol_data_by_symbol.pop(symbol.Symbol, None)
if data:
data.dispose()
# For each symbol in the added securites for the day
for added in changes.AddedSecurities:
# Set each symbol equal to a variable
symbol = added.Symbol
# Call the SymbolData function and add it to the dictionary for each symbol
self.symbol_data_by_symbol[symbol] = SymbolData(symbol, self)
self.ema_short_by_symbol[symbol] = RollingWindow[float](2)
# Put in filler values for the stop market dictionaries
self.highestPrice[symbol] = 0
self.stopMarketTicket[symbol] = None
# Create EMAs for each of the five minute dictionaries
self.ema_nine_five[symbol] = ExponentialMovingAverage(9)
self.ema_eighteen_five[symbol] = ExponentialMovingAverage(18)
self.ema_thirtysix_five[symbol] = ExponentialMovingAverage(36)
# Register each of these to a five minute auto update consolidator
self.RegisterIndicator(symbol, self.ema_nine_five[symbol], timedelta(minutes=5))
self.RegisterIndicator(symbol, self.ema_eighteen_five[symbol], timedelta(minutes=5))
self.RegisterIndicator(symbol, self.ema_eighteen_five[symbol], timedelta(minutes=5))
self.breakout_happened_in_last_mins = {}
self.breakout_in_last_mins[symbol] = []
self.low_less_than[symbol] = []
# When data is received
def OnData(self, data):
# For each symbol that we have in our algorithm
for symbol, symbol_data in self.symbol_data_by_symbol.items():
# Check if the data just pumped in contains the current symbol
if data.ContainsKey(symbol) and data[symbol] is not None:
# Set the current EMAs to a variable
ema_short = symbol_data.ema_short.Current.Value
ema_long = symbol_data.ema_long.Current.Value
ema_longer = symbol_data.ema_longer.Current.Value
self.ema_short_by_symbol[symbol].Add(float(ema_short))
# Get the current value for the Low and Close
low_ = data[symbol].Low
# If EMA9 > EMA18 > EMA36
ema_greater = ema_short > ema_long and ema_long > ema_longer
# If, on the 5 minute bar, EMA9 > EMA18 > EMA36
ema_fives = self.ema_nine_five[symbol].Current.Value > self.ema_eighteen_five[symbol].Current.Value and self.ema_eighteen_five[symbol].Current.Value > self.ema_thirtysix_five[symbol].Current.Value
low_below_fives = low_ < self.ema_nine_five[symbol].Current.Value
# If ALL of these previous conditions are true
if ema_fives:
self.breakout_in_last_mins[symbol].append("Y")
else:
self.breakout_in_last_mins[symbol].append("N")
if low_below_fives:
self.low_less_than[symbol].append("Y")
else:
self.low_less_than[symbol].append("N")
if len(self.breakout_in_last_mins[symbol]) > 10:
self.breakout_in_last_mins[symbol].pop(0)
if len(self.low_less_than[symbol]) > 5:
self.low_less_than[symbol].pop(0)
if len(self.breakout_in_last_mins[symbol]) > 9:
# If the slopes of the EMAs are increasing in the last 1 bar
ema_slope_inc = ema_short > self.ema_short_by_symbol[symbol][1]
if ema_slope_inc and ema_slope_inc and "Y" in self.breakout_in_last_mins[symbol] and "Y" in self.low_less_than[symbol]:
# If the symbol is not invested currently
if not self.Portfolio[symbol].Invested:
# Order 50 shares, and place a stop market for the same amount
self.MarketOrder(symbol, 20)
self.stopMarketTicket[symbol] = self.StopMarketOrder(symbol, -20, data[symbol].Close * .98)
self.minutes_stayed_in[symbol] = 0
# If the symbol is already invested
else:
# Check if the current price is greater than the last high
if data[symbol].Close > self.highestPrice[symbol]:
# Save the new high, then update the stop price
self.highestPrice[symbol] = data[symbol].Close
updateFields = UpdateOrderFields()
#updateFields.StopPrice = data[symbol].Close * .95
updateFields.StopPrice = data[symbol].Close * .98
#updateFields.StopPrice = ema_short
self.stopMarketTicket[symbol].Update(updateFields)
if self.Portfolio[symbol].Invested:
self.minutes_stayed_in[symbol] += 1
'''
if self.minutes_stayed_in[symbol] == 5 and self.Portfolio[symbol].Invested:
self.MarketOrder(symbol, 200)
self.stopMarketTicket[symbol] = self.StopMarketOrder(symbol, -220, ema_short)
self.minutes_stayed_in[symbol] = -100000
'''
# On each order event
def OnOrderEvent(self, orderEvent):
# If the order has been filled
if orderEvent.Status != OrderStatus.Filled:
return
# If the price is below the trailing stop, sell the stock
if self.stopMarketTicket[orderEvent.Symbol] is not None and self.stopMarketTicket[orderEvent.Symbol].OrderId == orderEvent.OrderId:
self.stopMarketOrderFillTime[orderEvent.Symbol] = self.Time
# Coarse Universe Selection
def CoarseSelectionFunction(self, coarse):
# Sort descending by daily dollar volume
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
# Filter for stocks in our price range
pricefilter = [x for x in sortedByDollarVolume if x.Price > 1 and x.Price < 700]
# Return the symbol objects of the top entries from our sorted collection
return [ x.Symbol for x in pricefilter[:20] ]
# Fine Universe Selection
def FineSelectionFunction(self, fine):
# Retrieve 10 days of historical data for each symbol
selectedSymbols = []
symbols = [x.Symbol for x in fine]
history = self.History(symbols, 10, Resolution.Daily)
# Iterate through symbols
for symbol in symbols:
if str(symbol) in history.index:
# Find hsitory for specific symbol
symbolhistory = history.loc[str(symbol)]
# Create SMA and EMA for symbol and register it with algorithm
symbolSMA = SimpleMovingAverage(10)
#symbolEMA = ExponentialMovingAverage(9)
# Iterate through historical data
for tuple in symbolhistory.itertuples():
# Update SMA and EMA with data time and volume
symbolSMA.Update(tuple.Index, tuple.volume)
#symbolEMA.Update(tuple.Index, tuple.close)
# If the SMA and EMA pass a certain threshold, add to our selected symbols
if float(str(symbolSMA)) > float(3500000):
selectedSymbols.append(symbol)
# Return selected symbols
self.Debug(self.Time)
return selectedSymbols
def BeforeMarketClose(self):
self.Liquidate()
# Class to create data for our symbols
class SymbolData:
# Initialize
def __init__(self, symbol, algorithm):
# Define variables
self.symbol = symbol
self.algorithm = algorithm
# Initialze our EMAs and SMAs
self.ema_short = ExponentialMovingAverage(9)
self.ema_long = ExponentialMovingAverage(18)
self.ema_longer = ExponentialMovingAverage(36)
self.sma_volume = SimpleMovingAverage(3)
# Setup consolidator
self.consolidator = TradeBarConsolidator(1)
self.consolidator.DataConsolidated += self.consolidation_handler
algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator)
# Dispose if removed
def dispose(self):
self.algorithm.SubscriptionManager.RemoveConsolidator(self.symbol, self.consolidator)
# On data consolidated
def consolidation_handler(self, sender, consolidated):
# Set variables for time, close, and volume
time = consolidated.EndTime
close = consolidated.Close
volume = consolidated.Volume
# Update our EMAs and SMAs
self.ema_short.Update(time, close)
self.ema_long.Update(time, close)
self.ema_longer.Update(time, close)
self.sma_volume.Update(time, volume)