| 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.512 Tracking Error 0.165 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
import pytz
class AKCAP_ORB(QCAlgorithm):
def Initialize(self):
# # # # # User input section # # # # #
# Start date of backtest
self.SetStartDate(2022, 1, 5)
#self.SetEndDate(2022, 1, 10)
# Strategy cash
#self.SetCash(25000)
# Warmup for RSI and EMA
#self.SetWarmUp(14)
# Website
self.website1 = "https://discord.com/api/webhooks/941445552695033910/y_7A5Z2kfkKmcTMN0alHMoxCd911czXFVN7AqpgxyBAHMe93rNhdcuQBuEDPpcq7hgeh"
self.website2 = "https://discord.com/api/webhooks/933719556382412810/vycGSAR_anNQWhCwNfgd5KtP_IIbdYqnj06yjH2lStJ3EgGrvJJ4WsWES4celiGbqelz"
# Variable: % of account already invested in stocks (assume y)
self.y_percent = 100
# Variable: % of cash to allocate to each long/short order (assume x)
self.x_percent = 50
# Variable: % difference between average cost of stock vs most recent close (assume k)
self.k_percent = 0.4
# Variable: cent above bid (long)/below bid ( short) most recent close price to submit long/short limit order (assume j)
self.j_cents = 0.03
# Variable: Take_profit Multiplier
self.multiplier = 1.75
# Variable: StopMultiplier
self.stop_multiplier = 2
# Variable: Close by percent stop loss
self.close_by_pct = True
# average volume
self.avgVolume = 5000000
# ATR period
self.ATR_period = 14
#Lookup equity history
self.Day_history = 30
#Stock min price
self.stock_min = 80
#stock max price
self.stock_max = 500
# Universe resolution
self.UniverseSettings.Resolution = Resolution.Minute
# Universe selection, coarse and fine
self.AddUniverse(self.Coarse, self.Fine)
# RSI dictionary
self.rsi_dictionary = {}
# EMA dictionary
self.ema_dictionary = {}
# ATR dictionary
self.atr_dictionary = {}
# Highest high dictionary
self.highest_high_dictionary = {}
# Lowest low dictionary
self.lowest_low_dictionary = {}
# Highest ATR dictionary
self.highest_atr_dictionary = {}
# Previous high dictionary
self.previous_high_dictionary = {}
# Previous low dictionary
self.previous_low_dictionary = {}
# Add SPY to schedule events
self.spy = self.AddEquity("SPY", Resolution.Minute).Symbol
# Schedule start collection of highest ATR value, highest high and lowest low
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen("SPY", 0),
self.start_collecting_data)
# Schedule end collection of data
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen("SPY", 30),
self.end_collecting_data)
# Schedule start trading logic
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen("SPY", 30),
self.start_trading_logic)
# Schedule end trading logic
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen("SPY", 380),
self.end_trading_logic)
# Schedule liquidation of all assets and orders at end of day
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.BeforeMarketClose("SPY", 5),
self.liquidate_portfolio)
# Binary variable to schedule collection of data
self.collect_data = False
# Binary variable to schedule trading logic
self.trading_logic = False
# Start collecting data function
def start_collecting_data(self):
# Set binary variable to True
self.collect_data = True
# End collecting data function
def end_collecting_data(self):
# Set binary variable to True
self.collect_data = False
# Start trading logic function
def start_trading_logic(self):
# Set trading logic variable to True
self.trading_logic = True
# End trading logic function
def end_trading_logic(self):
# Set trading logic variable to False
self.trading_logic = False
# Liquidate holdings and orders function
def liquidate_portfolio(self):
# Liquidate portfolio
self.Liquidate()
# Send webhook
#self.Notify.Web(self.website, "All positions closed at end of day.")
# Loop through highest high dictionary
for symbol in self.highest_high_dictionary:
# Reset highest high dictionary
self.highest_high_dictionary[symbol] = 0
# Reset lowest low dictionary
self.lowest_low_dictionary[symbol] = 0
# Reset highest atr dictionary
self.highest_atr_dictionary[symbol] = 0
# Reset previous high dictionary
self.previous_high_dictionary[symbol] = 0
# Reset previous low dictionary
self.previous_low_dictionary[symbol] = 0
# Coarse selection
def Coarse(self, coarse):
# Return stocks between $5 and $50
return [x.Symbol for x in coarse if x.Price > self.stock_min and x.Price < self.stock_max and x.HasFundamentalData]
# Fine selection
def Fine(self, fine):
# Final list after sorting
final_list = []
# Get stocks in NASDAQ market
fine_list = [x.Symbol for x in fine if x.CompanyReference.CountryId == "USA"]
# History call for 90 days of data
history = self.History(fine_list, self.Day_history, Resolution.Daily)
# Loop through fine_list
for symbol in fine_list:
#if not symbol in history.index:
# continue
# Loc symbol history
symbol_history = history.loc[symbol]
# Get average volume data
avg_volume = symbol_history["volume"].mean()
# If average volume is greater than 1,000,000
if avg_volume > self.avgVolume:
# Add to final list
final_list.append(symbol)
# Return final list
return final_list
# On securities changed
def OnSecuritiesChanged(self, changes):
# History call
history = self.History([x.Symbol for x in changes.AddedSecurities], 500, Resolution.Minute)
# Loop through added securities
for security in changes.AddedSecurities:
# If security is SPY
if security.Symbol.Value == "SPY":
if security.Symbol.Value == "CARR":
continue
# All other securities
else:
# Add ATR indicator
self.atr_dictionary[security.Symbol] = self.ATR(security.Symbol, self.ATR_period,
MovingAverageType.Exponential, Resolution.Minute)
# Add RSI indicator
self.rsi_dictionary[security.Symbol] = self.RSI(security.Symbol, 14, MovingAverageType.Wilders,
Resolution.Minute)
# Add EMA indicator
self.ema_dictionary[security.Symbol] = self.EMA(security.Symbol, 1800, Resolution.Hour)
# Loc history data for stock
stock_history = history.loc[security.Symbol]
# Loop through history of stock
for time, row in stock_history.iterrows():
# Create tradebar with history data
bar = TradeBar(time, security.Symbol, row.open, row.high, row.low, row.close, row.volume)
# Update atr indicator of stock
self.atr_dictionary[security.Symbol].Update(bar)
# Update atr indicator of stock
self.rsi_dictionary[security.Symbol].Update(IndicatorDataPoint(bar.EndTime, bar.Close))
# Update atr indicator of stock
self.ema_dictionary[security.Symbol].Update(IndicatorDataPoint(bar.EndTime, bar.Close))
# Add to highest high dictionary
self.highest_high_dictionary[security.Symbol] = 0
# Add to lowest low dictionary
self.lowest_low_dictionary[security.Symbol] = 0
# Add to highest ATR dictionary
self.highest_atr_dictionary[security.Symbol] = 0
# Add to previous high dictionary
self.previous_high_dictionary[security.Symbol] = 0
# Add to previous low dictionary
self.previous_low_dictionary[security.Symbol] = 0
# Loop trough removed securities
for security in changes.RemovedSecurities:
# Remove atr indicator of stock from atr dictionary
self.rsi_dictionary.pop(security.Symbol, None)
# Remove atr indicator of stock from atr dictionary
self.ema_dictionary.pop(security.Symbol, None)
# Remove atr indicator of stock from atr dictionary
self.atr_dictionary.pop(security.Symbol, None)
# Remove from highest high dictionary
self.highest_high_dictionary.pop(security.Symbol, None)
# Remove from lowest low dictionary
self.lowest_low_dictionary.pop(security.Symbol, None)
# Remove from highest ATR dictionary
self.highest_atr_dictionary.pop(security.Symbol, None)
# Remove from previous high dictionary
self.previous_high_dictionary.pop(security.Symbol, None)
# Remove from previous high dictionary
self.previous_low_dictionary.pop(security.Symbol, None)
def OnData(self, data):
#if self.IsWarmingUp:
#send start message
#string3 = str("Connected ")
#content_warm = json.dumps({"content": string3 + "AK CAP ORB scanner restart"})
#self.Notify.Web(self.website1, content_warm)
#self.Notify.Web(self.website2, content_warm)
#return
# Check if collecting values variable set to True
if self.collect_data == True:
# Loop through highest high dictionary
for symbol in self.highest_high_dictionary:
# Get current high
current_high = self.Securities[symbol].High
# Check if greater than value stored
if current_high > self.highest_high_dictionary[symbol]:
# Replace
self.highest_high_dictionary[symbol] = current_high
# Get current low
current_low = self.Securities[symbol].Low
# Check if lowest low stored is 0
if self.lowest_low_dictionary[symbol] == 0:
# Replace with current low
self.lowest_low_dictionary[symbol] = current_low
# If not
else:
# Check if current low is lower than lowest low stored
if current_low < self.lowest_low_dictionary[symbol]:
# Replace with current low
self.lowest_low_dictionary[symbol] = current_low
# Get current ATR
current_ATR = self.atr_dictionary[symbol].Current.Value
# Compare with value stored
if current_ATR > self.highest_atr_dictionary[symbol]:
# Replace
self.highest_atr_dictionary[symbol] = current_ATR
# If trading logic is true
if self.trading_logic == True:
# Loop through highest high dictionary
for symbol in self.highest_high_dictionary:
# Get previous high price
previous_high = self.previous_high_dictionary[symbol]
# Get most recent high price
high = self.Securities[symbol].Close
# Update previous high price
self.previous_high_dictionary[symbol] = high
# If previous high is 0
if previous_high == 0:
# Do nothing
continue
# If previous low is not 0
else:
# get close
close = self.Securities[symbol].Close
# get current rsi
current_rsi = self.rsi_dictionary[symbol].Current.Value
current_ema = self.ema_dictionary[symbol].Current.Value
ORB_HIGH = self.highest_high_dictionary[symbol]
ORB_LOW = self.lowest_low_dictionary[symbol]
#content_long = json.dumps({"content": "symbol.Value " + " ORB Breakout LONG"})
#content_short = json.dumps({"content": "symbol.Value " + " ORB Breakout SHORT"})
# # # # # Long position logic # # # # #
# If high is higher than highest high
if close > ORB_HIGH:
#if close > ORB_HIGH and current_rsi > 68 and close > current_ema:
#if close > ORB_HIGH:
#if previous_high < ORB_HIGH:
# Get cash available
# Send webhook
symbolnamelong = symbol.Value
self.Notify.Web(self.website1, {"content": "symbolnamelong " + " ORB Breakout LONG"})
self.Notify.Web(self.website2, {"content": "symbolnamelong " + " ORB Breakout LONG"})
# # # # # Short position logic # # # # #
# If high is lower than lowest low
if close < ORB_LOW:
#if close < ORB_LOW and current_rsi < 33 and close < current_ema
#if close < ORB_LOW:
#if previous_high > ORB_LOW:
# Get cash available
# Submit short limit order
#self.LimitOrder(symbol, -int(quantity), limit_price, "ORB SHORT LIMIT")
symbolnameshort = symbol.Value
# Send webhook
self.Notify.Web(self.website1, {"content": "symbolnameshort" + " ORB Breakout SHORT"})
self.Notify.Web(self.website2, {"content": "symbolnameshort" + " ORB Breakout SHORT"})