Overall Statistics
Total Trades
23
Average Win
2.82%
Average Loss
-2.87%
Compounding Annual Return
9.558%
Drawdown
9.400%
Expectancy
0.081
Net Profit
9.586%
Sharpe Ratio
0.47
Probabilistic Sharpe Ratio
25.307%
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
0.98
Alpha
0.122
Beta
-0.243
Annual Standard Deviation
0.172
Annual Variance
0.03
Information Ratio
-0.228
Tracking Error
0.38
Treynor Ratio
-0.333
Total Fees
$41.81
Estimated Strategy Capacity
$900000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
# region imports
from AlgorithmImports import *
# endregion

class SimpleSPYTrend(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 1, 1)
        self.SetEndDate(2021, 1, 1)
        self.SetCash(100000)
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol

        self.sma = self.SMA(self.spy, 30, Resolution.Daily) #Note: cannot be higher res than symbol's data
        # Pre-load price history for SMA indicator to satisfy warm-up period
        closing_prices = self.History(self.spy, 30, Resolution.Daily)["close"]
        for time, price in closing_prices.loc[self.spy].items():
            self.sma.Update(time, price)

    def OnData(self, data: Slice):
        if not self.sma.IsReady: # allow for indicator warm-up period
            return
        
        # Get data for 52-wk high and low --Note: inefficient, use RollingWindow or Min and Max inidcators
        hist = self.History(self.spy, timedelta(365), Resolution.Daily)
        low = min(hist["low"])
        high = max(hist["high"])

        # Check if SPY price is near 52-wk high or low for trade decisions
        price = self.Securities[self.spy].Price
        
        if price * 1.05 >= high and self.sma.Current.Value < price:
            if not self.Portfolio[self.spy].IsLong:
                self.SetHoldings(self.spy, 1)

        elif price * 0.95 <= low and self.sma.Current.Value > price:
            if not self.Portfolio[self.spy].IsShort:
                self.SetHoldings(self.spy, -1)

        else:
            self.Liquidate()

        self.Plot("Benchmark", "52w-High", high)
        self.Plot("Benchmark", "52w-Low", low)
        self.Plot("Benchmark", "SMA", self.sma.Current.Value)