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