Overall Statistics |
Total Orders 82 Average Win 2.75% Average Loss -2.19% Compounding Annual Return -4.102% Drawdown 25.200% Expectancy -0.119 Start Equity 100000 End Equity 88191.82 Net Profit -11.808% Sharpe Ratio -0.238 Sortino Ratio -0.175 Probabilistic Sharpe Ratio 0.776% Loss Rate 61% Win Rate 39% Profit-Loss Ratio 1.26 Alpha -0.019 Beta -0.173 Annual Standard Deviation 0.126 Annual Variance 0.016 Information Ratio -0.353 Tracking Error 0.272 Treynor Ratio 0.173 Total Fees $119.40 Estimated Strategy Capacity $940000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 7.48% |
#region imports from AlgorithmImports import * #endregion from collections import deque class AdaptableSkyBlueHornet(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 1, 1) self.SetEndDate(2023, 1, 1) self.SetCash(100000) self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol # 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(365), Resolution.Daily) low = min(hist["low"]) high = max(hist["high"]) price = self.Securities[self.spy].Price # Go long if near high and uptrending if price * 1.05 >= high and self.sma.Current.Value < price: if not self.Portfolio[self.spy].IsLong: self.SetHoldings(self.spy, 1) # Go short if near low and downtrending elif price * 0.95 <= low and self.sma.Current.Value > price: if not self.Portfolio[self.spy].IsShort: self.SetHoldings(self.spy, -1) # Otherwise, go flat else: self.Liquidate() self.Plot("Benchmark", "52w-High", high) self.Plot("Benchmark", "52w-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)