Overall Statistics
Total Trades
12498
Average Win
0.00%
Average Loss
0.00%
Compounding Annual Return
31.232%
Drawdown
1.000%
Expectancy
0.109
Net Profit
1.879%
Sharpe Ratio
6.637
Probabilistic Sharpe Ratio
91.156%
Loss Rate
60%
Win Rate
40%
Profit-Loss Ratio
1.74
Alpha
0.044
Beta
0.754
Annual Standard Deviation
0.036
Annual Variance
0.001
Information Ratio
-0.724
Tracking Error
0.026
Treynor Ratio
0.313
Total Fees
$14197.95
Estimated Strategy Capacity
$1100000.00
Lowest Capacity Asset
PUK RVX7NPOIEE05

from datetime import timedelta
from QuantConnect.Data.UniverseSelection import * 
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel

BONDS = ['TLH', 'IEF']

class SectorBalancedPortfolioConstruction(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2017, 9, 19) 
        self.SetEndDate(2017, 10, 15) 
        self.SetCash(10000000) 
        bondSymbol = [self.AddEquity(bond, Resolution.Hour).Symbol for bond in BONDS]
        self.UniverseSettings.Resolution = Resolution.Hour
        self.SetUniverseSelection(MyUniverseSelectionModel())
        self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(1), 0.025, None))
        self.SetPortfolioConstruction(MySectorWeightingPortfolioConstructionModel(bondSymbol))
        self.SetExecution(ImmediateExecutionModel())
        

class MyUniverseSelectionModel(FundamentalUniverseSelectionModel):

    def __init__(self):
        super().__init__(True, None)

    def SelectCoarse(self, algorithm, coarse):
        filtered = [x for x in coarse if x.HasFundamentalData and x.Price > 10]
        sortedByDollarVolume = sorted(filtered, key=lambda x: x.DollarVolume, reverse=True)
        return [x.Symbol for x in sortedByDollarVolume][:1000]

    def SelectFine(self, algorithm, fine):
        for f in fine:
            try:
                f.AssetClassification
            except:
                algorithm.Quit(f"Error with {f.Symbol}")
                return []
        
        filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Technology]
        self.technology = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:50]
        filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.FinancialServices]
        self.financialServices = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:50]
        filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.ConsumerDefensive]
        self.consumerDefensive = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:50]
        return [x.Symbol for x in self.technology + self.financialServices + self.consumerDefensive]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Industrials]
        #self.industrial = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Energy]
        #self.energy = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.BasicMaterials]
        #self.basicmaterial = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.CommunicationServices]
        #self.communication = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Utilities]
        #self.utility = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.Healthcare]
        #self.health = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.ConsumerCyclical]
        #self.consumerCyclical = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]
        #filtered = [f for f in fine if f.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.RealEstate]
        #self.realestate = sorted(filtered, key=lambda f: f.MarketCap, reverse=True)[:5]

      
        
        
class MySectorWeightingPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel):

    def __init__(self, bondSymbol, rebalance = Resolution.Daily):
        super().__init__()
        self.bondSymbol = bondSymbol
        self.symbolBySectorCode = {"Bonds":self.bondSymbol}
        self.result = dict()

    def DetermineTargetPercent(self, activeInsights):
        #1. Set the self.sectorBuyingPower before by dividing one by the length of self.symbolBySectorCode
        self.sectorBuyingPower = 1/len(self.symbolBySectorCode)
            
        for sector, symbols in self.symbolBySectorCode.items():
            #2. Search for the active insights in this sector. Save the variable self.insightsInSector
            self.insightsInSector = [insight for insight in activeInsights if insight.Symbol in symbols]
        
            #3. Divide the self.sectorBuyingPower by the length of self.insightsInSector to calculate the variable percent
            # The percent is the weight we'll assign the direction of the insight
            self.percent = self.sectorBuyingPower / len(self.insightsInSector)
        
            #4. For each insight in self.insightsInSector, assign each insight an allocation. 
            # The allocation is calculated by multiplying the insight direction by the self.percent 
            for insight in self.insightsInSector:
                self.result[insight] = insight.Direction * self.percent
        
        return self.result


    def OnSecuritiesChanged(self, algorithm, changes):
        for security in changes.AddedSecurities:
            if security.Symbol in self.bondSymbol: continue
            sectorCode = security.Fundamentals.AssetClassification.MorningstarSectorCode
            if sectorCode not in self.symbolBySectorCode:
                self.symbolBySectorCode[sectorCode] = list()
            self.symbolBySectorCode[sectorCode].append(security.Symbol) 

        for security in changes.RemovedSecurities:
            symbol = security.Symbol
            for sectorCode in self.symbolBySectorCode.keys():
                if symbol in self.symbolBySectorCode[sectorCode]:
                    self.symbolBySectorCode[sectorCode].remove(symbol)

        super().OnSecuritiesChanged(algorithm, changes)