Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
""" ML-based algorithm with regime features """ from AlgorithmImports import * import numpy as np import pandas as pd pd.set_option('mode.use_inf_as_na', True) from sklearn.ensemble import GradientBoostingClassifier class MLRegimes(QCAlgorithm): def Initialize(self): self.SetStartDate(2023, 1, 1) #self.SetEndDate(2022, 1, 1) self.SetCash(100000) self.lookbacks = [1, 4, 13, 26, 52] # Different lookbacks used for indicators self.training_len = 52 * 10 # Total weeks of data used for training self.period = 5 # Trading frequency in days self.resolution = Resolution.Daily self.tickers = ["NVDA","XOM","AMZN","GOOGL","JPM","NEE","PFE","LUV","HD","DIS"] [self.AddEquity(t, self.resolution) for t in self.tickers] self.vix = self.AddData(CBOE, "VIX", Resolution.Daily).Symbol self.tlt = self.AddData(CBOE, "TLT", Resolution.Daily).Symbol #self.gld = self.AddData(CBOE, "GLD", Resolution.Daily).Symbol #self.dbc = self.AddData(CBOE, "DBC", Resolution.Daily).Symbol #self.qqq = self.AddData(CBOE, "QQQ", Resolution.Daily).Symbol self.SetBenchmark(self.tickers[0]) self.model = GradientBoostingClassifier(n_iter_no_change=3) every_week = self.DateRules.WeekStart(self.tickers[0]) self.Train(every_week, self.TimeRules.At(9, 0), self.train) at_market_open = self.TimeRules.AfterMarketOpen(self.tickers[0], 0) self.Schedule.On(every_week, at_market_open, self.trade) def train(self): features, log_returns = self.get_data(self.training_len) target = log_returns > 0 # Up/Down target self.model.fit(features, target, sample_weight=abs(log_returns)) self.Debug(f"{self.Time} Training - Pts.: {target.value_counts()}\n") def trade(self): self.Transactions.CancelOpenOrders() n_points = max(self.lookbacks) + 1 x_pred = self.get_data(n_points, include_y=False).groupby("symbol").last() proba_up = self.model.predict_proba(x_pred)[:, 1] # Selecting probability of 1 x_pred_symbols = x_pred.index.get_level_values("symbol") positions = pd.Series(proba_up, index=x_pred_symbols) if positions.sum() > 1: positions /= positions.sum() # Capping positions at 100% (no leverage) for sym, pos in positions.items(): self.SetHoldings(sym, pos) self.Debug(f"{self.Time} Trading\n{sym}\nPos: {pos:.1%}") self.Plot("Positions", sym, pos) def get_data(self, n_points, include_y=True): data = self.History(self.tickers, n_points * self.period, self.resolution) x = pd.DataFrame() for l in self.lookbacks: roll_high = data["high"].rolling(l*self.period).max() roll_low = data["low"].rolling(l*self.period).min() x[f"range_{l}"] = (data["close"] - roll_low) / (roll_high - roll_low) vix_data = self.History(self.vix, n_points * self.period, self.resolution) tlt_data = self.History(self.tlt, n_points * self.period, self.resolution) # Getting historical data for TLT #comment out both of the TLT lines if you want this to run successfully x = x.join(vix_data.droplevel("symbol")["close"].rename("vix")) x = x.join(tlt_data.droplevel("symbol")["close"].rename("tlt")) #Possbily add this as 50-day moving average of TLT x.dropna(inplace=True) if include_y: y = data["close"].groupby("symbol").pct_change(self.period) y = y.apply(np.log1p).shift(-self.period).reindex(index=x.index).dropna() return x.loc[y.index], y else: return x