Overall Statistics
Total Trades
2282
Average Win
0.25%
Average Loss
-0.16%
Compounding Annual Return
6.597%
Drawdown
13.100%
Expectancy
0.331
Net Profit
91.671%
Sharpe Ratio
0.896
Probabilistic Sharpe Ratio
35.493%
Loss Rate
47%
Win Rate
53%
Profit-Loss Ratio
1.53
Alpha
0.057
Beta
-0.023
Annual Standard Deviation
0.061
Annual Variance
0.004
Information Ratio
-0.342
Tracking Error
0.151
Treynor Ratio
-2.383
Total Fees
$11102587.01
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from datetime import timedelta
from QuantConnect.Data.UniverseSelection import * 
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel

from pypfopt.hierarchical_risk_parity import HRPOpt
import pandas as pd


class smartBeta(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2010, 1, 1)    # Set Start Date
        self.SetCash(3e8)             # Set Strategy Cash
        self.SetBrokerageModel(BrokerageName.AlphaStreams)
        self.spy = self.AddEquity("SPY", Resolution.Daily) 
        self.SetBenchmark(self.spy.Symbol)  
        
        self.lastMonth_ = -1
        
        self.UniverseSettings.Resolution = Resolution.Daily
        self.SetUniverseSelection(SP500SectorsETFUniverse())
        
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen('SPY'), self.Rebalance)
        
        self.SetExecution(ImmediateExecutionModel())

        self.SetRiskManagement(TrailingStopRiskManagementModel(0.02))
    
    def Rebalance(self):
        """
        
        """
        if self.lastMonth_ == self.Time.month:
            return
        
        else:
            self.lastMonth_ = self.Time.month
            
        # 1) Create a dictionary keyed by the symbols in the insights with an pandas.Series as value to create a data frame
        df = self.History(self.Securities.Keys, 252, Resolution.Daily)# Get train/test data
        returns = df.unstack(level=1).close.transpose().pct_change().dropna()
        
        port = self.getHRP(returns)
        weights = port.values
        symbols = port.index.values
        selected = zip(symbols, weights)
        
        for symbol, weight in selected:
            self.SetHoldings(symbol, weight)
            
    def getHRP(self, x):
        # Construct a hierarchical portfolio based on the synthetic returns
        hrp = HRPOpt(x)
        weights = hrp.hrp_portfolio()
        return pd.Series(weights)