Overall Statistics |
Total Trades 95 Average Win 1.70% Average Loss -1.87% Compounding Annual Return -3.827% Drawdown 15.900% Expectancy -0.033 Net Profit -6.893% Sharpe Ratio -0.077 Probabilistic Sharpe Ratio 3.988% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 0.91 Alpha -0.006 Beta -0.391 Annual Standard Deviation 0.168 Annual Variance 0.028 Information Ratio -0.112 Tracking Error 0.281 Treynor Ratio 0.033 Total Fees $207.01 Estimated Strategy Capacity $1200000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 24.05% |
# region imports from AlgorithmImports import * # endregion class HipsterFluorescentPinkMule(QCAlgorithm): def Initialize(self): self.SetStartDate(2021, 9, 1) # Set Start Date self.SetEndDate(2023, 7, 1) self.SetCash(100000) # Set Strategy Cash self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol self.dataset_symbol = self.AddData(RegalyticsRegulatoryArticles, "REG").Symbol self.lookback_period = timedelta(days=90) self.Train(self.DateRules.Every(DayOfWeek.Sunday), self.TimeRules.At(0,0), self.train_model) self.train_model() #self.SetBenchmark(self.symbol) def train_model(self): spy_history = self.History(self.symbol, self.lookback_period).loc[self.symbol] daily_returns = spy_history['open'].pct_change()[1:] reg_history = self.History[RegalyticsRegulatoryArticles](self.dataset_symbol, self.lookback_period) returns_by_alert_type = {} for articles in reg_history: for article in articles: future_spy_returns = daily_returns.loc[daily_returns.index > article.Time] # Is this time the same time we get in backtests? if len(future_spy_returns) < 2: continue if article.AlertType not in returns_by_alert_type: returns_by_alert_type[article.AlertType] = [] returns_by_alert_type[article.AlertType].append(future_spy_returns.iloc[1]) self.expected_return_by_alert_type = { alert_type: sum(future_returns)/len(future_returns) for alert_type, future_returns in returns_by_alert_type.items() } def OnData(self, slice: Slice) -> None: # Parse articles if not slice.ContainsKey(self.dataset_symbol): return articles = slice[self.dataset_symbol] expected_returns = [] alert_types = set() for article in articles: alert_types.add(article.AlertType) for alert_type in alert_types: if alert_type in self.expected_return_by_alert_type: expected_returns.append(self.expected_return_by_alert_type[alert_type]) if len(expected_returns) == 0: return expected_return = sum(expected_returns) / len(expected_returns) if expected_return > 0 and not self.Portfolio[self.symbol].IsLong: self.SetHoldings(self.symbol, 1) elif expected_return < 0 and not self.Portfolio[self.symbol].IsShort: self.SetHoldings(self.symbol, -1)