Overall Statistics |
Total Trades 230 Average Win 0.01% Average Loss -0.01% Compounding Annual Return 50.104% Drawdown 1.600% Expectancy -0.300 Net Profit 7.381% Sharpe Ratio 5.928 Probabilistic Sharpe Ratio 98.096% Loss Rate 61% Win Rate 39% Profit-Loss Ratio 0.78 Alpha 0.054 Beta 1.014 Annual Standard Deviation 0.074 Annual Variance 0.006 Information Ratio 1.33 Tracking Error 0.044 Treynor Ratio 0.434 Total Fees $241.08 Estimated Strategy Capacity $8700000.00 |
from datetime import timedelta from QuantConnect.Data.UniverseSelection import * from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel class SectorBalancedPortfolioConstruction(QCAlgorithm): def Initialize(self): self.SetStartDate(2016, 12, 28) self.SetEndDate(2017, 3, 1) self.SetCash(100000) self.UniverseSettings.Resolution = Resolution.Hour self.SetUniverseSelection(MyUniverseSelectionModel()) self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(1), 0.025, None)) self.SetPortfolioConstruction(MySectorWeightingPortfolioConstructionModel(Resolution.Daily)) self.SetExecution(ImmediateExecutionModel()) class MyUniverseSelectionModel(FundamentalUniverseSelectionModel): def __init__(self): super().__init__(True, None, None) def SelectCoarse(self, algorithm, coarse): filtered = [x for x in coarse if x.HasFundamentalData and x.Price > 0] sortedByDollarVolume = sorted(filtered, key=lambda x: x.DollarVolume, reverse=True) return [x.Symbol for x in sortedByDollarVolume][:100] def SelectFine(self, algorithm, fine): filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Technology] self.technology = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:3] filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.FinancialServices] self.financialServices = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:2] filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.ConsumerDefensive] self.consumerDefensive = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:1] return [x.Symbol for x in self.technology + self.financialServices + self.consumerDefensive] class MySectorWeightingPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel): def __init__(self, rebalance = Resolution.Daily): super().__init__(rebalance) self.symbolBySectorCode = dict() def OnSecuritiesChanged(self, algorithm, changes): for security in changes.AddedSecurities: #1. When new assets are added to the universe, save the Morningstar sector code # for each security to the variable sectorCode sectorCode = security.Fundamentals.AssetClassification.MorningstarSectorCode # 2. If the sectorCode is not in the self.symbolBySectorCode dictionary, create a new list # and append the symbol to the list, keyed by sectorCode in the self.symbolBySectorCode dictionary if sectorCode not in self.symbolBySectorCode: self.symbolBySectorCode[sectorCode] = list() self.symbolBySectorCode[sectorCode].append(security.Symbol) for security in changes.RemovedSecurities: #3. For securities that are removed, save their Morningstar sector code to sectorCode sectorCode = security.Fundamentals.AssetClassification.MorningstarSectorCode #4. If the sectorCode is in the self.symbolBySectorCode dictionary if sectorCode in self.symbolBySectorCode: symbol = security.Symbol # If the symbol is in the dictionary's sectorCode list; if symbol in self.symbolBySectorCode[sectorCode]: # Then remove the corresponding symbol from the dictionary self.symbolBySectorCode[sectorCode].remove(symbol) # We use the super() function to avoid using the base class name explicity super().OnSecuritiesChanged(algorithm, changes)