| Overall Statistics |
|
Total Trades 3 Average Win 0% Average Loss -0.39% Compounding Annual Return 7.732% Drawdown 1.200% Expectancy -1 Net Profit 0.177% Sharpe Ratio 0.862 Probabilistic Sharpe Ratio 49.038% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.39 Beta 0.729 Annual Standard Deviation 0.083 Annual Variance 0.007 Information Ratio -8.743 Tracking Error 0.064 Treynor Ratio 0.098 Total Fees $7.76 |
import statsmodels.api as sm
import pandas as pd
from dateutil.relativedelta import relativedelta
from QuantConnect.Indicators import SimpleMovingAverage
from functools import partial
class OptimizedNadionRadiator(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2020, 1, 6) # Set Start Date
self.SetEndDate(2020, 1, 14)
self.SetCash(100000) # Set Strategy Cash
symbols = [ Symbol.Create("SPY", SecurityType.Equity, Market.USA) ]
self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )
self.UniverseSettings.Resolution = Resolution.Minute
self.AddAlpha(MyAlphaModel())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
class MyAlphaModel(AlphaModel):
symbol = None
sma = None
model = None
def Update(self, algorithm, slice):
# Only emit insights if the exchange is on its last minute of the day (proxy for daily close)
exchange = algorithm.Securities[self.symbol].Exchange
if not (exchange.DateTimeIsOpen(slice.Time) and not exchange.DateTimeIsOpen(slice.Time + relativedelta(minutes=1))):
return []
close = slice[self.symbol].Close
self.sma.Update(slice.Time, slice[self.symbol].Close)
normalized_sma = (close - self.sma.Current.Value) / close
normalized_sma = pd.DataFrame({"const": [1], "normalized_SMA": [normalized_sma]})
prediction = self.model.predict(normalized_sma).values[0]
if prediction == 0:
return []
direction = InsightDirection.Up if prediction > 0 else InsightDirection.Down
return [Insight.Price(self.symbol, timedelta(days=1), direction)]
def OnSecuritiesChanged(self, algorithm, changes):
for security in changes.AddedSecurities:
self.symbol = security.Symbol
self.sma = SimpleMovingAverage(5)
history = algorithm.History(self.symbol, 50, Resolution.Daily).loc[self.symbol][['close']]
for idx, row in history.iterrows():
self.sma.Update(idx, row.close)
if self.sma.IsReady:
history.loc[idx, "SMA"] = self.sma.Current.Value
history['normalized_SMA'] = (history.close - history.SMA) / history.close
history['return'] = history.close.pct_change()
history.dropna(inplace=True)
X = sm.add_constant(history.normalized_SMA)
y = history['return'].values
self.model = sm.OLS(y, X).fit()