| 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