Overall Statistics
Total Orders
1128
Average Win
0.84%
Average Loss
-0.03%
Compounding Annual Return
86.924%
Drawdown
34.700%
Expectancy
29.673
Start Equity
100000
End Equity
349806.01
Net Profit
249.806%
Sharpe Ratio
1.407
Sortino Ratio
1.816
Probabilistic Sharpe Ratio
59.734%
Loss Rate
4%
Win Rate
96%
Profit-Loss Ratio
30.85
Alpha
0.309
Beta
2.945
Annual Standard Deviation
0.477
Annual Variance
0.228
Information Ratio
1.321
Tracking Error
0.415
Treynor Ratio
0.228
Total Fees
$92.19
Estimated Strategy Capacity
$180000000.00
Lowest Capacity Asset
GOOCV VP83T1ZUHROL
Portfolio Turnover
1.26%
Drawdown Recovery
156
from AlgorithmImports import *
import numpy as np

class RedDayMarkovPortfolioAlgorithm(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2023, 1, 1)
        self.SetEndDate(2025, 1, 1)
        self.SetCash(100000)

        # List of 30 symbols (replace with your preferred tickers)
        tickers = ["AAPL", "MSFT", "GOOG", "AMZN", "META", "NVDA", "TSLA", "NFLX", "ADBE", "INTC",
                   "CSCO", "ORCL", "IBM", "PYPL", "QCOM", "AVGO", "TXN", "AMD", "CRM", "SHOP",
                   "SQ", "UBER", "LYFT", "BABA", "JD", "SNOW", "PLTR", "TWTR", "ZM", "DOCU"]

        self.symbols = [self.AddEquity(t, Resolution.Daily).Symbol for t in tickers]

        # Data structures for each symbol
        self.history = {s: [] for s in self.symbols}
        self.transition_matrix = {s: np.zeros((2, 2)) for s in self.symbols}
        self.last_state = {s: None for s in self.symbols}

    def OnData(self, data):
        for symbol in self.symbols:
            if not data.Bars.ContainsKey(symbol):
                continue

            price = data[symbol].Close
            self.history[symbol].append(price)

            if len(self.history[symbol]) < 2:
                continue

            # Red day (1 if down, 0 if up)
            today_red = int(self.history[symbol][-1] < self.history[symbol][-2])

            # Update transition matrix if we have a previous day
            if self.last_state[symbol] is not None:
                self.transition_matrix[symbol][self.last_state[symbol]][today_red] += 1

                # Normalize to probabilities
                row_sums = self.transition_matrix[symbol].sum(axis=1)
                prob_matrix = np.divide(self.transition_matrix[symbol], row_sums[:, None],
                                        out=np.zeros_like(self.transition_matrix[symbol]),
                                        where=row_sums[:, None] != 0)

                prob_red_tomorrow = prob_matrix[today_red][1]
                self.Debug(f"{symbol.Value} - Red day probability tomorrow: {prob_red_tomorrow:.2%}")

                # Simple trading signal
                if prob_red_tomorrow > 0.6:
                    self.SetHoldings(symbol, 0)  # Avoid holding
                elif prob_red_tomorrow < 0.4:
                    self.SetHoldings(symbol, 1)  # Go long

            # Update last state
            self.last_state[symbol] = today_red