Overall Statistics
Total Orders
595
Average Win
0.29%
Average Loss
-0.26%
Compounding Annual Return
9.223%
Drawdown
17.500%
Expectancy
0.630
Start Equity
100000
End Equity
160133.87
Net Profit
60.134%
Sharpe Ratio
0.506
Sortino Ratio
0.521
Probabilistic Sharpe Ratio
25.188%
Loss Rate
23%
Win Rate
77%
Profit-Loss Ratio
1.11
Alpha
-0.005
Beta
0.49
Annual Standard Deviation
0.085
Annual Variance
0.007
Information Ratio
-0.627
Tracking Error
0.089
Treynor Ratio
0.088
Total Fees
$595.00
Estimated Strategy Capacity
$2000000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
1.84%
# region imports
from AlgorithmImports import *
from hmmlearn import hmm
import joblib
# endregion

class HmmlearnExampleAlgorithm(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2019, 1, 1)
        self.SetEndDate(2024,5,1)
        self.SetCash(100000)
        self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol
        self._bias=int(self.GetParameter("bias"))

        training_length = 252*2
        self.training_data = RollingWindow[float](training_length)
        history = self.History[TradeBar](self.symbol, training_length, Resolution.Daily)
        for trade_bar in history:
            self.training_data.Add(trade_bar.Close)

        if self.ObjectStore.ContainsKey("model.hmm"):
            file_name = self.ObjectStore.GetFilePath("model.hmm")
            self.model = joblib.load(file_name)
        
        else:
            self.model = hmm.GaussianHMM(n_components=2, covariance_type="full", n_iter=100)

        self.Train(self.my_training_method)
        self.Train(self.DateRules.Every(DayOfWeek.Sunday), self.TimeRules.At(8,0), self.my_training_method)
        
    def get_features(self):
        training_df = np.array(list(self.training_data)[::-1])
        daily_pct_change = (np.roll(training_df, 1) - training_df) / training_df

        return daily_pct_change[1:].reshape(-1, 1)

    def my_training_method(self):
        features = self.get_features()
        self.model.fit(features)

    def OnData(self, slice: Slice) -> None:
        if self.symbol in slice.Bars:
            self.training_data.Add(slice.Bars[self.symbol].Close)

        new_feature = self.get_features()
        prediction = self.model.predict(new_feature)
        prediction = float(prediction[-1])

        if prediction == 1:
            self.SetHoldings(self.symbol, 0.5+self._bias*.10)
        else:            
            #self.Liquidate(self.symbol)
            self.SetHoldings(self.symbol, 0.5-self._bias*.10)

    def OnEndOfAlgorithm(self):
        #model_key = "model.hmm"
        #file_name = self.ObjectStore.GetFilePath(model_key)
        #joblib.dump(self.model, file_name)
        pass