| 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)