Overall Statistics |
Total Orders 353 Average Win 1.70% Average Loss -1.48% Compounding Annual Return 19.095% Drawdown 31.900% Expectancy 0.394 Start Equity 100000 End Equity 277424.27 Net Profit 177.424% Sharpe Ratio 0.745 Sortino Ratio 0.754 Probabilistic Sharpe Ratio 26.323% Loss Rate 35% Win Rate 65% Profit-Loss Ratio 1.14 Alpha 0.062 Beta 0.875 Annual Standard Deviation 0.175 Annual Variance 0.031 Information Ratio 0.508 Tracking Error 0.103 Treynor Ratio 0.149 Total Fees $1359.80 Estimated Strategy Capacity $11000000.00 Lowest Capacity Asset KBE TDP0JIUCTNJ9 Portfolio Turnover 4.73% |
from AlgorithmImports import * from collections import defaultdict import json class WellDressedVioletChinchilla(QCAlgorithm): def Initialize(self): self.SetStartDate(2017, 1, 1) self.SetEndDate(2022, 11, 1) self.SetCash(100000) self._brainUniverseData = [] self._etfConstituentsDataBySymbol = defaultdict(list) self._scoreBySector = {} self._numEtfs = 3 self._portfolioValues = {} self._rebalance = False self.AddUniverse(BrainSentimentIndicatorUniverse, "BrainSentimentIndicatorUniverse", Resolution.Daily, self.BrainsentimentSelection) tickers = [ "XLE", "XLF", "XLU", "XLI", "GDX", "XLK", "XLV", "XLY", "XLP", "XLB", "XOP", "IYR", "XHB", "ITB", "VNQ", "GDXJ", "IYE", "OIH", "XME", "XRT", "SMH", "IBB", "KBE", "KRE", "XTL" ] for ticker in tickers: etf_symbol = self.AddEquity(ticker, Resolution.Daily).Symbol self.add_universe(self.universe.etf(etf_symbol, Market.USA, self.UniverseSettings, self.ETFConstituentSelection(etf_symbol))) self.Schedule.On(self.DateRules.MonthStart(self.GetParameter("rebalance-day", 0)), self.TimeRules.Midnight, self.Rebalance) def BrainsentimentSelection(self, altCoarse): self._brainUniverseData = [x for x in altCoarse] return [] def ETFConstituentSelection(self, etf_symbol): def _ETFConstituentSelection(constituents): self._etfConstituentsDataBySymbol[etf_symbol] = constituents return [] return _ETFConstituentSelection def OnData(self, data): self._portfolioValues[self.Time] = self.Portfolio.TotalPortfolioValue if not self._rebalance: return self._rebalance = False for etf_symbol, etfConstituentsData in self._etfConstituentsDataBySymbol.items(): sector_symbols = {c.Symbol for c in etfConstituentsData} etf_weight_by_symbol = {c.Symbol: c.Weight for c in etfConstituentsData} self._scoreBySector[etf_symbol] = sum( brain.Sentiment30Days * etf_weight_by_symbol[brain.Symbol] for brain in self._brainUniverseData if brain.Symbol in sector_symbols ) target_symbols = sorted(self._scoreBySector, key=self._scoreBySector.get, reverse=True)[:self._numEtfs] self.SetHoldings( [PortfolioTarget(kvp.Key, 0) for kvp in self.Portfolio if kvp.Value.Invested and kvp.Key not in target_symbols] ) weight = 1.0 / self._numEtfs self.SetHoldings([PortfolioTarget(symbol, weight) for symbol in target_symbols]) def Rebalance(self): self._rebalance = True