Overall Statistics
Total Orders
395
Average Win
3.10%
Average Loss
-1.68%
Compounding Annual Return
10.453%
Drawdown
25.500%
Expectancy
0.441
Start Equity
1000000
End Equity
3645497.21
Net Profit
264.550%
Sharpe Ratio
0.539
Sortino Ratio
0.594
Probabilistic Sharpe Ratio
4.691%
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
1.84
Alpha
0.065
Beta
0.037
Annual Standard Deviation
0.125
Annual Variance
0.016
Information Ratio
-0.011
Tracking Error
0.207
Treynor Ratio
1.798
Total Fees
$32515.75
Estimated Strategy Capacity
$40000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
8.30%
#region imports
from AlgorithmImports import *
from statsmodels.tsa.regime_switching.markov_regression import MarkovRegression
#endregion

class HMMDemo(QCAlgorithm):
    
    def initialize(self):
        self.set_start_date(2008, 1, 1)
        self.set_end_date(2021, 1, 1)
    
        #2. Required: Alpha Streams Models:
        self.set_brokerage_model(BrokerageName.ALPHA_STREAMS)
    
        #3. Required: Significant AUM Capacity
        self.set_cash(1000000)
    
        #4. Required: Benchmark to SPY
        self.set_benchmark("SPY")
    
        self.assets = ["SPY", "TLT"]    # "TLT" as fix income in out-of-market period (high volatility)
        
        # Add Equity ------------------------------------------------ 
        for ticker in self.assets:
            self.add_equity(ticker, Resolution.MINUTE).symbol
        
        # Set Scheduled Event Method For Kalman Filter updating.
        self.schedule.on(self.date_rules.every_day(), 
            self.time_rules.before_market_close("SPY", 5), 
            self.every_day_before_market_close)
            
            
    def every_day_before_market_close(self):
        qb = self
        
        # Get history
        history = qb.history(["SPY"], 252*3, Resolution.DAILY)
            
        # Get the close price daily return.
        close = history['close'].unstack(level=0)
        
        # Call pct_change to obtain the daily return
        returns = close.pct_change().iloc[1:]
                
        # Initialize the HMM, then fit by the standard deviation data.
        model = MarkovRegression(returns, k_regimes=2, switching_variance=True).fit()
            
        # Obtain the market regime
        regime = model.smoothed_marginal_probabilities.values.argmax(axis=1)[-1]
    
        # ==============================
        
        if regime == 0:
            self.set_holdings([PortfolioTarget("TLT", 0.), PortfolioTarget("SPY", 1.)])            
        else:
            self.set_holdings([PortfolioTarget("TLT", 1.), PortfolioTarget("SPY", 0.)])