| Overall Statistics |
|
Total Trades 360 Average Win 1.65% Average Loss -2.55% Compounding Annual Return 6.332% Drawdown 40.500% Expectancy 0.272 Net Profit 97.112% Sharpe Ratio 0.42 Probabilistic Sharpe Ratio 1.975% Loss Rate 23% Win Rate 77% Profit-Loss Ratio 0.65 Alpha 0.068 Beta -0.057 Annual Standard Deviation 0.146 Annual Variance 0.021 Information Ratio -0.296 Tracking Error 0.213 Treynor Ratio -1.084 Total Fees $1524.64 |
# Take the original SPY pullback strategy and add multiple entries
class SPYMeanReversionAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2009,1, 1) #Set Start Date
self.SetEndDate(2020,1,20) #Set End Date
self.SetCash(10000) #Set Strategy Cash
self.spy = self.AddEquity("SPY", Resolution.Daily)
self.spy = self.AddEquity("GLD", Resolution.Daily)
self.upro = self.AddEquity("UPRO", Resolution.Daily)
self.shy = self.AddEquity("SHY", Resolution.Daily)
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
self.rsi2 = self.RSI("SPY", 2, MovingAverageType.Simple, Resolution.Daily);
self.rsi20 = self.RSI("SPY", 20, MovingAverageType.Simple, Resolution.Daily);
self.sma200 = self.SMA("SPY", 200, Resolution.Daily);
self.SetWarmUp(200)
# dictionary to hold our target position sizes {position count: % allocation}
self.targets = {0:0, 1:0.25, 2:0.5, 3:0.65, 4:0.85, 5:1}
# counter which tracks where in the sequence of sizes we are, start at zero for no position
self.counter = 0
def OnData(self, data):
if self.IsWarmingUp:
return
if not self.sma200.IsReady: return
if not self.rsi2.IsReady: return
if not self.rsi20.IsReady: return
if data.ContainsKey("SPY") == False: return
if data[self.spy.Symbol].Low>self.sma200.Current.Value and self.rsi2.Current.Value<20:
# if we add 1 to our current position count and it is greater than our 100% allocation, then we do nothing
if self.counter + 1 not in self.targets: return
# since this is a new buy signal, we look at our current position counter and go up to the next allocation amount
self.counter += 1
#self.SetHoldings("SHY", 0)
self.SetHoldings("UPRO", self.targets[self.counter])
if data[self.spy.Symbol].High>self.sma200.Current.Value and self.rsi2.Current.Value>75 or data[self.spy.Symbol].High<self.sma200.Current.Value and self.rsi2.Current.Value>70:
self.SetHoldings("UPRO", 0)
#self.SetHoldings("SHY", 1)
# Reset the positions counter to zero for the next trade, else you will only get 5 entries forever.
self.counter = 0