Overall Statistics
Total Orders
406
Average Win
0.76%
Average Loss
-0.45%
Compounding Annual Return
40.943%
Drawdown
50.700%
Expectancy
1.353
Start Equity
100000
End Equity
566039.35
Net Profit
466.039%
Sharpe Ratio
1.02
Sortino Ratio
1.274
Probabilistic Sharpe Ratio
50.212%
Loss Rate
13%
Win Rate
87%
Profit-Loss Ratio
1.70
Alpha
0.157
Beta
1.622
Annual Standard Deviation
0.274
Annual Variance
0.075
Information Ratio
1.173
Tracking Error
0.174
Treynor Ratio
0.172
Total Fees
$418.51
Estimated Strategy Capacity
$0
Lowest Capacity Asset
NVDA RHM8UTD8DT2D
Portfolio Turnover
0.27%
Drawdown Recovery
514
#region imports
from AlgorithmImports import *
#endregion

class AIBasketStrategy(QCAlgorithm):

    def Initialize(self):
        # 1. Setup: Last 5 Years
        self.SetStartDate(2020, 12, 12)  
        self.SetEndDate(2026, 1, 1)    
        self.SetCash(100000) 

        # 2. Define the "AI Basket"
        # We manually select the leaders to ensure purity of the theme
        self.tickers = [
            "NVDA", # GPU King
            "AMD",  # GPU Challenger
            "TSM",  # The Foundry (makes the chips)
            "AVGO", # Broadcom (Custom AI chips & Networking)
            "MSFT", # OpenAI / Cloud
            "GOOGL",# Gemini / DeepMind
            "META", # LLaMA / Meta AI
            "PLTR"  # AI Data Foundry
        ]
        
        self.symbols = []
        for ticker in self.tickers:
            # Add equity and set resolution to Daily (sufficient for rebalancing)
            symbol = self.AddEquity(ticker, Resolution.Daily).Symbol
            self.symbols.append(symbol)

        # 3. Schedule Rebalancing (First trading day of every month)
        # This keeps the portfolio strictly equal-weighted
        self.Schedule.On(
            self.DateRules.MonthStart("NVDA"),
            self.TimeRules.AfterMarketOpen("NVDA", 30),
            self.Rebalance
        )
        
        # 4. Realistic Settings
        self.SetSecurityInitializer(lambda x: x.SetFeeModel(ConstantFeeModel(1.0)))
        self.SetBenchmark("SPY") # Compare against S&P 500

    def Rebalance(self):
        # Calculate target weight (100% / 8 stocks = 12.5% each)
        # We check if stock has data to avoid errors (e.g. if one was delisted or halted)
        valid_symbols = [s for s in self.symbols if self.Securities[s].Price > 0]
        
        if len(valid_symbols) == 0: return
        
        weight = 1.0 / len(valid_symbols)
        
        # Execute Trades
        for symbol in valid_symbols:
            self.SetHoldings(symbol, weight)
            
    def OnData(self, data):
        # We don't need trade logic here because the Scheduler handles it.
        pass