Overall Statistics
Total Orders
79
Average Win
1.99%
Average Loss
-1.63%
Compounding Annual Return
6.202%
Drawdown
14.400%
Expectancy
0.200
Start Equity
100000
End Equity
111475.49
Net Profit
11.475%
Sharpe Ratio
0.011
Sortino Ratio
0.012
Probabilistic Sharpe Ratio
18.914%
Loss Rate
46%
Win Rate
54%
Profit-Loss Ratio
1.22
Alpha
-0.044
Beta
0.564
Annual Standard Deviation
0.101
Annual Variance
0.01
Information Ratio
-0.892
Tracking Error
0.089
Treynor Ratio
0.002
Total Fees
$94.22
Estimated Strategy Capacity
$650000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
10.28%
# region imports
from AlgorithmImports import *
from hmmlearn import hmm
import joblib
# endregion

class HmmlearnExampleAlgorithm(QCAlgorithm):
    
    def initialize(self):
        self.set_start_date(2022, 7, 4)
        self.set_cash(100000)
        self.symbol = self.add_equity("SPY", Resolution.DAILY).symbol

        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.object_store.contains_key("model.hmm"):
            file_name = self.object_store.get_file_path("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.date_rules.every(DayOfWeek.SUNDAY), self.time_rules.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 on_data(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.set_holdings(self.symbol, 1)
        else:            
            self.liquidate(self.symbol)

    def on_end_of_algorithm(self):
        model_key = "model.hmm"
        file_name = self.object_store.get_file_path(model_key)
        joblib.dump(self.model, file_name)