Overall Statistics |
Total Trades 628 Average Win 1.12% Average Loss -0.92% Compounding Annual Return 58.667% Drawdown 19.700% Expectancy 0.170 Net Profit 58.667% Sharpe Ratio 1.691 Probabilistic Sharpe Ratio 66.076% Loss Rate 47% Win Rate 53% Profit-Loss Ratio 1.21 Alpha 0.529 Beta 0 Annual Standard Deviation 0.313 Annual Variance 0.098 Information Ratio 0.601 Tracking Error 0.341 Treynor Ratio 1178.414 Total Fees $5654.10 Estimated Strategy Capacity $720000000.00 Lowest Capacity Asset SPCE X91R7VLCNM91 |
from AlgorithmImports import * from QuantConnect.DataSource import * class BrainMLRankingDataAlgorithm(QCAlgorithm): num_longs_shorts = 1 symbol_data_by_symbol = {} def Initialize(self): self.SetStartDate(2020, 7, 1) self.SetEndDate(2021, 6, 30) self.SetCash(1000000) self.UniverseSettings.Resolution = Resolution.Daily self.AddUniverse(self.Universe.DollarVolume.Top(5)) def OnData(self, data): # Update Symbol Data objects with the latest Brain Rank data for symbol, symbol_data in self.symbol_data_by_symbol.items(): if data.ContainsKey(symbol_data.ranking_symbol) and data[symbol_data.ranking_symbol] is not None: rank = data[symbol_data.ranking_symbol].Rank symbol_data.update(rank) # Select the Symbol Data objects that are ready to be traded ready_symbol_datas = [] for symbol, symbol_data in self.symbol_data_by_symbol.items(): if symbol_data.IsReady and data.ContainsKey(symbol) and data[symbol] is not None: ready_symbol_datas.append((symbol, symbol_data)) if len(ready_symbol_datas) < 2 * self.num_longs_shorts: return # Sort the SymbolData objects by their Brain Rank sorted_by_brain_rank = sorted(ready_symbol_datas, key=lambda x: x[1].brain_rank) # Place orders to form a long-short portfolio weight = 0.5 / self.num_longs_shorts for i, (symbol, symbol_data) in enumerate(sorted_by_brain_rank): if i < self.num_longs_shorts: self.SetHoldings(symbol, -weight) elif i >= len(sorted_by_brain_rank) - self.num_longs_shorts: self.SetHoldings(symbol, weight) elif self.Portfolio[symbol].Invested: self.Liquidate(symbol) def OnSecuritiesChanged(self, changes): for security in changes.AddedSecurities: symbol = security.Symbol self.symbol_data_by_symbol[symbol] = SymbolData(self, symbol) for security in changes.RemovedSecurities: symbol = security.Symbol self.Liquidate(symbol) symbol_data = self.symbol_data_by_symbol.pop(symbol, None) if symbol_data: symbol_data.dispose() class SymbolData: brain_rank = None def __init__(self, algorithm, symbol): self.algorithm = algorithm self.ranking_symbol = algorithm.AddData(BrainStockRanking2Day, symbol).Symbol # Warm up Brain rank history = algorithm.History(self.ranking_symbol, 3, Resolution.Daily) if history.empty or 'rank' not in history.columns: return self.brain_rank = history.loc[self.ranking_symbol]['rank'].values[-1] def update(self, rank): self.brain_rank = rank @property def IsReady(self): return self.brain_rank is not None def dispose(self): self.algorithm.RemoveSecurity(self.ranking_symbol)