| Overall Statistics |
|
Total Trades 3 Average Win 17.08% Average Loss 0% Compounding Annual Return 9.560% Drawdown 33.800% Expectancy 0 Net Profit 321.050% Sharpe Ratio 0.633 Probabilistic Sharpe Ratio 4.504% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.095 Beta -0.071 Annual Standard Deviation 0.14 Annual Variance 0.02 Information Ratio 0.008 Tracking Error 0.235 Treynor Ratio -1.256 Total Fees $3.00 |
from System.Drawing import Color
class SMA_multi_timescale(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2005, 1, 1) # the starting date for our backtest
#self.SetEndDate(2020, 6, 1) # the ending date for our backtest (if no date, then it will test up until today)
self.start_value = 5000
self.cash = self.start_value
self.SetCash(self.cash) # the starting amount of our portfolio
self.EQY = "SPY" # define the stock ticker
self.EQY2 = "SH"
self.AddEquity(self.EQY, Resolution.Daily) # add a stock to the list of those we want to trade, and how often to pull data
self.AddEquity(self.EQY2, Resolution.Daily)
self.starting_price = None
period0 = 10
period1 = 20
period2 = 50
period3 = 20
# all 3 time periods needs to have 3 indicators
# create a consolidator for weekly data
self.Consolidate(self.EQY, Calendar.Weekly, self.OnWeeklyBar)
# create a consolidator for monthly data
self.Consolidate(self.EQY, Calendar.Monthly, self.OnMonthlyBar)
# set up an SMA20 indicator
#var sma = SMA(Symbol symbol, int period, Resolution resolution = null, Func`2[Data.IBaseData,Decimal] selector = null)
self.mom = self.MOM(self.EQY, period0)
self.sma_daily0 = self.SMA(self.EQY, period0, Resolution.Daily)
self.sma_daily1 = self.SMA(self.EQY, period1, Resolution.Daily)
self.sma_daily2 = self.SMA(self.EQY, period2, Resolution.Daily)
self.sma_daily3 = self.SMA(self.EQY, period3, Resolution.Daily)
self.sma_weekly1 = SimpleMovingAverage(period1)
self.sma_weekly2 = SimpleMovingAverage(period2)
self.sma_weekly3 = SimpleMovingAverage(period3)
self.sma_monthly1 = SimpleMovingAverage(period1)
self.sma_monthly2 = SimpleMovingAverage(period2)
self.sma_monthly3 = SimpleMovingAverage(period3)
# need to give the indicators data before running the algorithm
self.SetWarmUp(period3*7*31)
#set up a chart to display our buy and sell dates
self.stockPlot = Chart('Equity Daily')
self.SPY_candles = Series(self.EQY, SeriesType.Candle)
self.stockPlot.AddSeries(self.SPY_candles)
self.AddChart(self.stockPlot)
# set up a chart to display our buy and sell dates
self.stockPlot = Chart('Equity Weekly')
self.SPY_weekly_candles = Series(self.EQY, SeriesType.Candle)
self.stockPlot.AddSeries(self.SPY_weekly_candles)
self.stockPlot.AddSeries(Series('Buy', SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Triangle))
self.stockPlot.AddSeries(Series('Sell', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.TriangleDown))
self.AddChart(self.stockPlot)
# set up a chart to display our buy and sell dates
self.stockPlot = Chart('Equity Monthly')
self.SPY_monthly_candles = Series(self.EQY, SeriesType.Candle)
self.stockPlot.AddSeries(self.SPY_monthly_candles)
self.AddChart(self.stockPlot)
# this is for plotting the relative change of each stock and our portfolio value
# def OnEndOfDay(self):
# current_portfolio = self.Portfolio.TotalPortfolioValue
# change_portfolio = (current_portfolio - self.start_value )/ self.start_value
# self.Plot("Percent Change","Portfolio Change", change_portfolio)
# # # if we haven't gotten the starting price, then get it
# if self.starting_price == None:
# self.starting_price = self.Securities[self.EQY].Price
# start_price = self.starting_price
# price = self.Securities[self.EQY].Price
# change_in_price = (price - start_price)/ start_price
# self.Plot("Percent Change", self.EQY + " Change", change_in_price)
def OnData(self, data): # this function is where trades happen. it executes based on the freqeuncy of data in the self.AddEquity function above
if self.IsWarmingUp: return
price = self.Securities[self.EQY].Price
# # if the indicators aren't ready, don't do anything
if (not self.sma_monthly3.IsReady): return
daily_low_price = self.Securities[self.EQY].Low
daily_high_price = self.Securities[self.EQY].High
weekly_low_price = self.weeklyBar.Low
weekly_high_price = self.weeklyBar.High
monthly_low_price = self.monthlyBar.Low
monthly_high_price = self.monthlyBar.High
# # extract the current value of each indicator
sma_daily0 = self.sma_daily0.Current.Value
sma_daily1 = self.sma_daily1.Current.Value
sma_daily2 = self.sma_daily2.Current.Value
sma_daily3 = self.sma_daily3.Current.Value
sma_weekly1 = self.sma_weekly1.Current.Value
sma_weekly2 = self.sma_weekly2.Current.Value
sma_weekly3 = self.sma_weekly3.Current.Value
sma_monthly1 = self.sma_monthly1.Current.Value
sma_monthly2 = self.sma_monthly2.Current.Value
sma_monthly3 = self.sma_monthly3.Current.Value
mom_daily0 = self.mom.Current.Value
# Entry points
# daily logic
up_mom = mom_daily0 > 0
daily_entry0 = daily_low_price > sma_daily0
daily_entry1 = daily_low_price > sma_daily1
daily_entry2 = daily_low_price > sma_daily2
daily_entry3 = daily_low_price > sma_daily3
# Sanity check
# weekly logic
weekly_entry1 = weekly_low_price > sma_weekly1
weekly_entry2 = weekly_low_price > sma_weekly2
weekly_entry3 = weekly_low_price > sma_weekly3
# Sanity check
# monthly logic
monthly_entry1 = monthly_low_price > sma_monthly1
monthly_entry2 = monthly_low_price > sma_monthly2
monthly_entry3 = monthly_low_price > sma_monthly3
# Exit points
# daily logic
daily_exit1 = daily_high_price < sma_daily1
daily_exit2 = daily_high_price < sma_daily2
daily_exit3 = daily_high_price < sma_daily3
# Sanity check
# weekly logic
weekly_exit1 = weekly_high_price < sma_weekly1
weekly_exit2 = weekly_high_price < sma_weekly2
weekly_exit3 = weekly_high_price < sma_weekly3
# Sanity check
# monthly logic
monthly_exit1 = monthly_high_price < sma_monthly1
monthly_exit2 = monthly_high_price < sma_monthly2
monthly_exit3 = monthly_high_price < sma_monthly3
# entry point logic
if not self.Portfolio.Invested:
if monthly_entry1: #and monthly_entry2 and monthly_entry3:
if weekly_entry1: #and weekly_entry2 and weekly_entry3:
if daily_entry1: #and daily_entry2 and daily_entry3:
# entry
self.SetHoldings(self.EQY, 1) # if the price is above the 20-day moving average, buy the stock
self.Plot("Equity Weekly", 'Buy', self.Securities[self.EQY].Price)
# exit point logic
if self.Portfolio.Invested:
if monthly_exit1:
if weekly_exit1:
if daily_exit1:
# exit
self.SetHoldings(self.EQY, 0) # otherwise exit the position
self.Plot("Equity Weekly", 'Sell', self.Securities[self.EQY].Price)
# # for going short
# if self.Portfolio.Invested:
# if up_mom:
# self.SetHoldings(self.EQY2, 0)
# self.Plot("Equity Weekly", 'Buy', self.Securities[self.EQY].Price)
# if not self.Portfolio.Invested:
# if monthly_exit1:
# self.SetHoldings(self.EQY2, 1)
# self.Plot("Equity Weekly", 'Sell', self.Securities[self.EQY].Price)
# plotting stuff
# self.Plot("Equity Daily",self.EQY,self.Securities[self.EQY].Price)
# self.Plot("Equity Daily","SMA1",sma_daily1)
# self.Plot("Equity Daily","SMA2",sma_daily1)
# self.Plot("Equity Daily","SMA3",sma_daily1)
# self.SPY_candles.AddPoint(self.Time + timedelta(minutes=1), self.Securities[self.EQY].Open)
# self.SPY_candles.AddPoint(self.Time + timedelta(minutes=2), self.Securities[self.EQY].High)
# self.SPY_candles.AddPoint(self.Time + timedelta(minutes=3), self.Securities[self.EQY].Low)
# self.SPY_candles.AddPoint(self.Time + timedelta(minutes=4), self.Securities[self.EQY].Close)
#self.Log(self.Securities[self.EQY].Price)
def OnWeeklyBar(self, weeklyBar):
# self.Log(weeklyBar)
self.weeklyBar = weeklyBar
self.sma_weekly1.Update(self.weeklyBar.Time, self.weeklyBar.Close)
sma_weekly1 = self.sma_weekly1.Current.Value
self.sma_weekly2.Update(self.weeklyBar.Time, self.weeklyBar.Close)
sma_weekly2 = self.sma_weekly2.Current.Value
self.sma_weekly3.Update(self.weeklyBar.Time, self.weeklyBar.Close)
sma_weekly3 = self.sma_weekly3.Current.Value
# plotting stuff
self.Plot("Equity Weekly","SMA1",sma_weekly1)
self.Plot("Equity Weekly","Weekly High",self.weeklyBar.High)
self.Plot("Equity Weekly","Weekly Low",self.weeklyBar.Low)
#self.Plot("Equity Weekly","SMA2",sma_weekly2)
#self.Plot("Equity Weekly","SMA3",sma_weekly3)
#self.SPY_weekly_candles.AddPoint(self.Time, self.weeklyBar.Open)
#self.SPY_weekly_candles.AddPoint(self.Time, self.weeklyBar.High)
#self.SPY_weekly_candles.AddPoint(self.Time, self.weeklyBar.Low)
#self.SPY_weekly_candles.AddPoint(self.Time, self.weeklyBar.Close)
current_portfolio = self.Portfolio.TotalPortfolioValue
change_portfolio = (current_portfolio - self.start_value )/ self.start_value
self.Plot("Percent Change","Portfolio Change", change_portfolio)
# # if we haven't gotten the starting price, then get it
if self.IsWarmingUp: return
if self.starting_price == None:
self.starting_price = self.Securities[self.EQY].Price
start_price = self.starting_price
price = self.Securities[self.EQY].Price
change_in_price = (price - start_price)/ start_price
self.Plot("Percent Change", self.EQY + " Change", change_in_price)
def OnMonthlyBar(self, monthlyBar):
# self.Log(weeklyBar)
self.monthlyBar = monthlyBar
self.sma_monthly1.Update(self.monthlyBar.Time, self.monthlyBar.Close)
sma_monthly1 = self.sma_monthly1.Current.Value
self.sma_monthly2.Update(self.monthlyBar.Time, self.monthlyBar.Close)
sma_monthly2 = self.sma_monthly2.Current.Value
self.sma_monthly3.Update(self.monthlyBar.Time, self.monthlyBar.Close)
sma_monthly3 = self.sma_monthly3.Current.Value
# self.Plot("Equity Monthly","SMA1",sma_monthly1)
# self.Plot("Equity Monthly","Monthly High",self.monthlyBar.High)
# self.Plot("Equity Monthly","Monthly Low",self.monthlyBar.Low)
#self.Plot("Equity Monthly","SMA2",sma_monthly2)
#self.Plot("Equity Monthly","SMA3",sma_monthly3)
#self.SPY_monthly_candles.AddPoint(self.Time, self.monthlyBar.Open)
#self.SPY_monthly_candles.AddPoint(self.Time, self.monthlyBar.High)
#self.SPY_monthly_candles.AddPoint(self.Time, self.monthlyBar.Low)
#self.SPY_monthly_candles.AddPoint(self.Time, self.monthlyBar.Close)