Overall Statistics
Total Orders
1794
Average Win
0.13%
Average Loss
-0.12%
Compounding Annual Return
37.728%
Drawdown
12.800%
Expectancy
0.496
Start Equity
100000
End Equity
174213.85
Net Profit
74.214%
Sharpe Ratio
1.596
Sortino Ratio
1.963
Probabilistic Sharpe Ratio
89.183%
Loss Rate
28%
Win Rate
72%
Profit-Loss Ratio
1.07
Alpha
0.053
Beta
1.097
Annual Standard Deviation
0.128
Annual Variance
0.016
Information Ratio
1.261
Tracking Error
0.052
Treynor Ratio
0.187
Total Fees
$2044.56
Estimated Strategy Capacity
$4000000.00
Lowest Capacity Asset
AADR UOFRJAZTL0TH
Portfolio Turnover
5.95%
from AlgorithmImports import *
from hmmlearn import hmm

class HMMRegimeDetection(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2023, 1, 1)
        self.add_universe(lambda fundamental: [f.symbol for f in sorted(fundamental, key=lambda x: x.market_cap, reverse=True)[:10]])
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(timedelta(minutes=5)))
        self.settings.rebalance_portfolio_on_insight_changes = False
        self.set_warm_up(timedelta(3))

    def on_securities_changed(self, changes):
        for added in changes.added_securities:
            added.roc = RateOfChange(1)
            added.roc.window.size = self.get_parameter("roc_window", 150)
            added.model = hmm.GaussianHMM(n_components=2, n_iter=100, random_state=100)
            added.model_month = -1
            added.consolidator = TradeBarConsolidator(timedelta(minutes=self.get_parameter("bar_size", 5)))
            added.consolidator.data_consolidated += self.on_consolidated
            self.subscription_manager.add_consolidator(added.symbol, added.consolidator)

    def on_consolidated(self, _, bar):
        security = self.securities[bar.symbol]
        security.roc.update(bar.end_time, bar.price)
        if security.roc.window.is_ready:
            if security.model_month != bar.end_time.month:
                security.model.fit(np.array([point.value for point in security.roc.window])[::-1].reshape(-1, 1))
                security.model_month = bar.end_time.month
            post_prob = security.model.predict_proba(np.array([security.roc.current.value]).reshape(1, -1)).flatten()
            direction = InsightDirection.UP if post_prob[-1] > post_prob [0] else InsightDirection.DOWN
            self.emit_insights(Insight.price(bar.symbol, timedelta(minutes=self.get_parameter("bar_size", 5)), direction))