| Overall Statistics |
|
Total Trades 60 Average Win 0.21% Average Loss -0.17% Compounding Annual Return 8.762% Drawdown 1.400% Expectancy 0.344 Net Profit 1.763% Sharpe Ratio 2.313 Probabilistic Sharpe Ratio 77.778% Loss Rate 40% Win Rate 60% Profit-Loss Ratio 1.24 Alpha 0.056 Beta 0.053 Annual Standard Deviation 0.026 Annual Variance 0.001 Information Ratio -0.232 Tracking Error 0.137 Treynor Ratio 1.153 Total Fees $60.00 Estimated Strategy Capacity $830000.00 Lowest Capacity Asset TAN V44Y4YYPI2XX Portfolio Turnover 19.57% |
#region imports
from AlgorithmImports import *
#endregion
class NadionResistanceShield(QCAlgorithm):
#class DataConsolidationAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2023, 1, 1) # Set Start Date
#self.SetEndDate(2023, 1, 1)
self.SetCash(50000) # Set Strategy Cash
self.tickers = ["SPY", "NUE", "MSFT", "AMZN", "GOOG", "NVDA", "TAN"]
self.symbolDataBySymbol = {}
self.trade = True
self.vwaps = {}
self.stds = {}
# Before the open
for symbol in self.tickers:
self.AddEquity(symbol, Resolution.Minute)
self.Debug(f"Registering {symbol}")
'''For the below 3 EMA's, you can convert them to 4H bars using the colidator method'''
macd = self.MACD(symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Daily, Field.Close)
ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
#sma7 = self.SMA(symbol, 7, Resolution.Minute, Field.Close)
ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
ema7 = self.EMA(symbol, 7, Resolution.Hour, Field.Close)
#ema7 = self.EMA(symbol, 7, Resolution.Minute, Field.Close)
ema9 = self.EMA(symbol, 9, Resolution.Hour, Field.Close)
rsi = self.RSI(symbol, 14, Resolution.Daily)
wilr_up = self.WILR(symbol, 10, Resolution.Daily)
wilr = self.WILR(symbol, 14, Resolution.Daily)
self.vwaps[symbol] = self.VWAP(symbol, 14, Resolution.Daily)
self.stds[symbol] = self.STD(symbol, 14, Resolution.Daily)
'''Consolidator method'''
smaConsolidate = ExponentialMovingAverage(20, MovingAverageType.Simple)
# create the 4 hour data consolidator
fourHourConsolidator = TradeBarConsolidator(timedelta(hours=4))
self.SubscriptionManager.AddConsolidator(symbol, fourHourConsolidator)
# register the 4 hour consolidated bar data to automatically update the indicator
self.RegisterIndicator(symbol, smaConsolidate, fourHourConsolidator)
symbolData = SymbolData(symbol, ema10, sma200, sma20, sma50, sma7, ema20, ema7, ema9, rsi, wilr, smaConsolidate)
self.symbolDataBySymbol[symbol] = symbolData
self.SetWarmUp(30, Resolution.Daily)
self.spy = self.AddEquity("SPY", Resolution.Daily)
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen("SPY"),
self.tradeStart)
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.BeforeMarketClose("SPY"),
self.tradeEnd)
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(10, 0), self.Trade)
#self.Schedule.On(self.DateRules.EveryDay("SPY"), self.AfterMarketOpen(10, 0), self.SellSignals)
#self.Schedule.On(self.DateRules.EveryDay("SPY"),self.TimeRules.Every(timedelta(minutes=10)),self.sellSignals)
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(12, 0), self.Exit)
#self.AddRiskManagement(TrailingStopRiskManagementModel(0.03))
self.SetWarmUp(timedelta(days=50))
def tradeStart(self):
self.trade = True
def tradeEnd(self):
self.trade = False
def Trade(self):
if self.trade == False:
return
for symbol in self.tickers:
# Get the daily data for the symbol
history = self.History([symbol], 1, Resolution.Daily)
if not history.empty:
daily_data = history.loc[symbol]
# Get the open and close prices for the previous day
previous_open = daily_data["open"].iloc[0]
previous_close = daily_data["close"].iloc[0]
# Get the current price
current_price = self.Securities[symbol].Price
# Calculate the price gap and percentage change
price_gap = current_price - previous_close
percentage_change = price_gap / previous_close
# Check if the price has gapped up by more than 1%
if percentage_change > 0.02:
self.Log("{} gap up detected: {}%".format(symbol, percentage_change * 100))
# Enter a long position
self.SetHoldings(symbol, .25)
def buySignals(self):
if self.trade == False:
return
for symbol, symbolData in self.symbolDataBySymbol.items():
if not self.Portfolio[symbol].Invested and (self.Securities[symbol].Close > symbolData.ema7.Current.Value) and (symbolData.sma20.Current.Value > symbolData.sma50.Current.Value):
self.SetHoldings(symbol, .1, False, "Buy Signal")
# def sellSignals(self):
# if self.trade == False:
# return
# for symbol, symbolData in self.symbolDataBySymbol.items():
# if self.Portfolio[symbol].Invested and (self.Securities[symbol].Close < symbolData.ema7.Current.Value):
# self.Liquidate(symbol, "Sell Signal")
def Exit(self):
for symbol in self.tickers:
# Exit the position
self.Liquidate(symbol)
def OnData(self, data):
if self.IsWarmingUp:# or not all(std.IsReady for std in self.stds.values()):
return
for symbol in self.tickers:
price = self.Securities[symbol].Price
vwap = self.vwaps[symbol].Current.Value
std = self.stds[symbol].Current.Value
ub1 = vwap + std
ub2 = vwap + 2*std
lb1 = vwap - std
lb2 = vwap - 2*std
self.Plot(symbol, 'price', price)
self.Plot(symbol, 'vwap', vwap)
self.Plot(symbol, 'ub2', ub2)
self.Plot(symbol, 'ub1', ub1)
self.Plot(symbol, 'lb1', lb1)
self.Plot(symbol, 'lb2', lb2)
class SymbolData:
def __init__(self, symbol, ema10, sma200, sma20, sma50, sma7, ema20, ema7, ema9, rsi, wilr, smaConsolidate):
self.Symbol = symbol
self.ema10 = ema10
self.sma200 = sma200
self.sma20 = sma20
self.sma50 = sma50
self.sma7 = sma7
self.ema20 = ema20
self.ema7 = ema7
self.ema9 = ema9
self.rsi = rsi
self.wilr = wilr
#self.emaConsolidate = emaConsolidate
self.smaConsolidate = smaConsolidate
#region imports
from AlgorithmImports import *
#endregion
class NadionResistanceShield(QCAlgorithm):
#class DataConsolidationAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2023, 1, 1) # Set Start Date
#self.SetEndDate(2023, 1, 1)
self.SetCash(50000) # Set Strategy Cash
self.tickers = ["SPY", "NUE", "MSFT", "AMZN", "GOOG", "NVDA", "TAN"]
self.symbolDataBySymbol = {}
self.trade = True
self.vwaps = {}
self.stds = {}
# Before the open
for symbol in self.tickers:
self.AddEquity(symbol, Resolution.Minute)
self.Debug(f"Registering {symbol}")
'''For the below 3 EMA's, you can convert them to 4H bars using the colidator method'''
macd = self.MACD(symbol, 12, 26, 9, MovingAverageType.Exponential, Resolution.Daily, Field.Close)
ema10 = self.EMA(symbol, 10, Resolution.Hour, Field.Close)
sma200 = self.SMA(symbol, 200, Resolution.Daily, Field.Close)
sma20 = self.SMA(symbol, 20, Resolution.Daily, Field.Close)
sma50 = self.SMA(symbol, 50, Resolution.Daily, Field.Close)
sma7 = self.SMA(symbol, 7, Resolution.Hour, Field.Close)
#sma7 = self.SMA(symbol, 7, Resolution.Minute, Field.Close)
ema20 = self.EMA(symbol, 20, Resolution.Hour, Field.Close)
ema7 = self.EMA(symbol, 7, Resolution.Hour, Field.Close)
#ema7 = self.EMA(symbol, 7, Resolution.Minute, Field.Close)
ema9 = self.EMA(symbol, 9, Resolution.Hour, Field.Close)
rsi = self.RSI(symbol, 14, Resolution.Daily)
wilr_up = self.WILR(symbol, 10, Resolution.Daily)
wilr = self.WILR(symbol, 14, Resolution.Daily)
self.vwaps[symbol] = self.VWAP(symbol, 14, Resolution.Daily)
self.stds[symbol] = self.STD(symbol, 14, Resolution.Daily)
'''Consolidator method'''
smaConsolidate = ExponentialMovingAverage(20, MovingAverageType.Simple)
# create the 4 hour data consolidator
fourHourConsolidator = TradeBarConsolidator(timedelta(hours=4))
self.SubscriptionManager.AddConsolidator(symbol, fourHourConsolidator)
# register the 4 hour consolidated bar data to automatically update the indicator
self.RegisterIndicator(symbol, smaConsolidate, fourHourConsolidator)
symbolData = SymbolData(symbol, ema10, sma200, sma20, sma50, sma7, ema20, ema7, ema9, rsi, wilr, smaConsolidate)
self.symbolDataBySymbol[symbol] = symbolData
self.SetWarmUp(30, Resolution.Daily)
self.spy = self.AddEquity("SPY", Resolution.Daily)
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen("SPY"),
self.tradeStart)
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.BeforeMarketClose("SPY"),
self.tradeEnd)
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(10, 0), self.Trade)
#self.Schedule.On(self.DateRules.EveryDay("SPY"), self.AfterMarketOpen(10, 0), self.SellSignals)
self.Schedule.On(self.DateRules.EveryDay("SPY"),self.TimeRules.Every(timedelta(minutes=10)),self.sellSignals)
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(12, 0), self.Exit)
#self.AddRiskManagement(TrailingStopRiskManagementModel(0.03))
self.SetWarmUp(timedelta(days=50))
def tradeStart(self):
self.trade = True
def tradeEnd(self):
self.trade = False
def Trade(self):
if self.trade == False:
return
for symbol in self.tickers:
# Get the daily data for the symbol
history = self.History([symbol], 1, Resolution.Daily)
if not history.empty:
daily_data = history.loc[symbol]
# Get the open and close prices for the previous day
previous_open = daily_data["open"].iloc[0]
previous_close = daily_data["close"].iloc[0]
# Get the current price
current_price = self.Securities[symbol].Price
# Calculate the price gap and percentage change
price_gap = current_price - previous_close
percentage_change = price_gap / previous_close
# Check if the price has gapped up by more than 1%
if percentage_change > 0.02:
self.Log("{} gap up detected: {}%".format(symbol, percentage_change * 100))
# Enter a long position
self.SetHoldings(symbol, .25)
def buySignals(self):
if self.trade == False:
return
for symbol, symbolData in self.symbolDataBySymbol.items():
if not self.Portfolio[symbol].Invested and (self.Securities[symbol].Close > symbolData.ema7.Current.Value) and (symbolData.sma20.Current.Value > symbolData.sma50.Current.Value):
self.SetHoldings(symbol, .1, False, "Buy Signal")
# def sellSignals(self):
# if self.trade == False:
# return
# for symbol, symbolData in self.symbolDataBySymbol.items():
# if self.Portfolio[symbol].Invested and (self.Securities[symbol].Close < symbolData.ema7.Current.Value):
# self.Liquidate(symbol, "Sell Signal")
def sellSignals(self):
if self.trade == False:
return
invested_symbols = [x.Key for x in self.Portfolio if x.Value.Invested]
for symbol in invested_symbols:
if self.vwaps[symbol].Current.Value < self.Securities[symbol].Price and self.Securities[symbol].Price > (2 * self.stds[symbol].Current.Value):
self.Log("{} sell signal detected.".format(symbol))
self.Liquidate(symbol)
else:
self.Debug("{} has a VWAP of {} and current price is {}.".format(symbol, self.vwaps[symbol].Current.Value, self.Securities[symbol].Price))
def Exit(self):
for symbol in self.tickers:
# Exit the position
self.Liquidate(symbol)
def OnData(self, data):
if self.IsWarmingUp or not all(std.IsReady for std in self.stds.values()):
return
for symbol in self.tickers:
price = self.Securities[symbol].Price
vwap = self.vwaps[symbol].Current.Value
std = self.stds[symbol].Current.Value
ub1 = vwap + std
ub2 = vwap + 2*std
lb1 = vwap - std
lb2 = vwap - 2*std
self.Plot(symbol, 'price', price)
self.Plot(symbol, 'vwap', vwap)
self.Plot(symbol, 'ub2', ub2)
self.Plot(symbol, 'ub1', ub1)
self.Plot(symbol, 'lb1', lb1)
self.Plot(symbol, 'lb2', lb2)
class SymbolData:
def __init__(self, symbol, ema10, sma200, sma20, sma50, sma7, ema20, ema7, ema9, rsi, wilr, smaConsolidate):
self.Symbol = symbol
self.ema10 = ema10
self.sma200 = sma200
self.sma20 = sma20
self.sma50 = sma50
self.sma7 = sma7
self.ema20 = ema20
self.ema7 = ema7
self.ema9 = ema9
self.rsi = rsi
self.wilr = wilr
#self.emaConsolidate = emaConsolidate
self.smaConsolidate = smaConsolidate