Overall Statistics
Total Trades
61
Average Win
4.58%
Average Loss
-1.63%
Compounding Annual Return
0.212%
Drawdown
32.200%
Expectancy
0.016
Net Profit
0.638%
Sharpe Ratio
0.086
Probabilistic Sharpe Ratio
2.824%
Loss Rate
73%
Win Rate
27%
Profit-Loss Ratio
2.81
Alpha
0.054
Beta
-0.21
Annual Standard Deviation
0.153
Annual Variance
0.023
Information Ratio
-0.675
Tracking Error
0.266
Treynor Ratio
-0.063
Total Fees
$191.44
Estimated Strategy Capacity
$1300000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
#region imports
from AlgorithmImports import *
#endregion
from itertools import groupby
from collections import deque

class AdaptableSkyBlueHornet(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 1, 1)
        self.SetEndDate(2022, 1, 1)
        self.SetCash(100000)
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.AddRiskManagement(MaximumDrawdownPercentPerSecurity(0.05))
        
    #    self.sma = self.SMA(self.spy, 30, Resolution.Daily)
        
        # History warm up for shortcut helper SMA indicator
    #    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)
        
        # Custom SMA indicator
        self.sma = CustomSimpleMovingAverage("CustomSMA", 30)
        self.RegisterIndicator(self.spy, self.sma, Resolution.Daily)

    
    def OnData(self, data):
        if not self.sma.IsReady:
            return

        
        # Save high, low, and current price
        hist = self.History(self.spy, timedelta(90), Resolution.Daily)
        low = min(hist["low"])
        high = max(hist["high"])
        
        price = self.Securities[self.spy].Price
        
        # Go short if near high and downtrending
        #if price >= high*0.95 and self.sma.Current.Value > price:
        if self.sma.Current.Value > price:
            if not self.Portfolio[self.spy].IsShort:
                self.SetHoldings(self.spy, -1)
        
        # Go long if near low and uptrending
        #elif price <= low*1.05 and self.sma.Current.Value < price:
        elif self.sma.Current.Value < price:  
            if not self.Portfolio[self.spy].IsLong:
                self.SetHoldings(self.spy, 1)
        
        # Otherwise, go flat
        else:
            return
            #self.Liquidate()
        
        self.Plot("Benchmark", "90d-High", high)
        self.Plot("Benchmark", "90d-Low", low)
        self.Plot("Benchmark", "SMA", self.sma.Current.Value)


class CustomSimpleMovingAverage(PythonIndicator):
    
    def __init__(self, name, period):
        self.Name = name
        self.Time = datetime.min
        self.Value = 0
        self.queue = deque(maxlen=period)

    def Update(self, input):
        self.queue.appendleft(input.Close)
        self.Time = input.EndTime
        count = len(self.queue)
        self.Value = sum(self.queue) / count
        # returns true if ready
        return (count == self.queue.maxlen)