Overall Statistics
Total Orders
68
Average Win
12.01%
Average Loss
-5.11%
Compounding Annual Return
118.180%
Drawdown
45.100%
Expectancy
1.069
Start Equity
100000
End Equity
473992.63
Net Profit
373.993%
Sharpe Ratio
1.834
Sortino Ratio
2.429
Probabilistic Sharpe Ratio
72.594%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
2.35
Alpha
0.886
Beta
-0.674
Annual Standard Deviation
0.487
Annual Variance
0.237
Information Ratio
1.654
Tracking Error
0.547
Treynor Ratio
-1.326
Total Fees
$301.61
Estimated Strategy Capacity
$630000000.00
Lowest Capacity Asset
TSLA UNU3P8Y3WFAD
Portfolio Turnover
7.20%
from AlgorithmImports import *
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from ta.momentum import RSIIndicator
from ta.volatility import BollingerBands
from ta.trend import MACD

class TSLAPredictionStrategy(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2022, 1, 1)
        self.SetEndDate(2023, 12, 31)
        self.SetCash(100000)
        
        # Add TSLA equity
        self.tsla = self.AddEquity("TSLA", Resolution.Daily).Symbol
        
        # Initialize indicators
        self.sma = self.SMA(self.tsla, 10, Resolution.Daily)
        self.rsi = self.RSI(self.tsla, 14, MovingAverageType.Wilders, Resolution.Daily)
        self.momentum = self.MOM(self.tsla, 10, Resolution.Daily)
        self.volatility = self.STD(self.tsla, 10, Resolution.Daily)
        self.macd = self.MACD(self.tsla, 12, 26, 9, MovingAverageType.Wilders, Resolution.Daily)
        self.bollinger = self.BB(self.tsla, 20, 2, MovingAverageType.Simple, Resolution.Daily)
        
        # Schedule trades on a weekly basis
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.AfterMarketOpen(self.tsla, 30), self.PredictAndTrade)
        
        # Initialize model
        self.model = RandomForestClassifier(n_estimators=100, random_state=42)
        self.isModelTrained = False
        
        # Historical data for model training
        self.history = self.History([self.tsla], 365 * 10, Resolution.Daily)
        self.df = self.history.loc[self.tsla]
        
    def OnData(self, slice: Slice):
        pass
    
    def PredictAndTrade(self):
        if not self.isModelTrained:
            self.TrainModel()
        
        # Get latest data for prediction
        features = self.GetFeatures(self.Time)
        
        if features is not None:
            prediction = self.model.predict([features])[0]
            self.Debug(f"Prediction for {self.Time}: {'Bullish' if prediction == 1 else 'Bearish'}")
            
            if prediction == 1:
                self.SetHoldings(self.tsla, 1)
                self.Debug(f"Going long on TSLA at {self.Time}")
            else:
                self.SetHoldings(self.tsla, -1)
                self.Debug(f"Going short on TSLA at {self.Time}")
    
    def TrainModel(self):
        df = self.df.copy()
        
        # Calculate technical indicators
        df['SMA10'] = df['close'].rolling(window=10).mean()
        df['Return'] = df['close'].pct_change()
        df['Volatility'] = df['close'].rolling(window=10).std()
        df['Momentum'] = df['close'].pct_change(10)
        df['RSI'] = RSIIndicator(df['close'], window=14).rsi()
        macd = MACD(df['close'], window_slow=26, window_fast=12, window_sign=9)
        df['MACD'] = macd.macd()
        df['MACD_Signal'] = macd.macd_signal()
        bb = BollingerBands(df['close'], window=20, window_dev=2)
        df['BB_High'] = bb.bollinger_hband()
        df['BB_Low'] = bb.bollinger_lband()
        
        # Shift the indicators to align with the prediction target
        df['SMA10'] = df['SMA10'].shift(-5)
        df['Return'] = df['Return'].shift(-5)
        df['Volatility'] = df['Volatility'].shift(-5)
        df['Momentum'] = df['Momentum'].shift(-5)
        df['RSI'] = df['RSI'].shift(-5)
        df['MACD'] = df['MACD'].shift(-5)
        df['MACD_Signal'] = df['MACD_Signal'].shift(-5)
        df['BB_High'] = df['BB_High'].shift(-5)
        df['BB_Low'] = df['BB_Low'].shift(-5)
        
        # Determine the actual next week's direction
        df['NextWeekChange'] = df['close'].pct_change(5).shift(-5)
        df['Actual'] = np.where(df['NextWeekChange'] > 0, 1, -1)
        
        # Drop NaN values
        df.dropna(inplace=True)
        
        # Prepare the features and target
        features = ['SMA10', 'Return', 'Volatility', 'Momentum', 'RSI', 'MACD', 'MACD_Signal', 'BB_High', 'BB_Low']
        X = df[features]
        y = df['Actual']
        
        # Train the Random Forest Classifier
        self.model.fit(X, y)
        self.isModelTrained = True
        self.Debug("Model trained successfully.")
    
    def GetFeatures(self, time):
        data = self.History([self.tsla], 20, Resolution.Daily).loc[self.tsla]
        
        if len(data) < 20:
            return None
        
        sma10 = data['close'].rolling(window=10).mean().iloc[-1]
        ret = data['close'].pct_change().iloc[-1]
        vol = data['close'].rolling(window=10).std().iloc[-1]
        mom = data['close'].pct_change(10).iloc[-1]
        rsi = RSIIndicator(data['close'], window=14).rsi().iloc[-1]
        macd = MACD(data['close'], window_slow=26, window_fast=12, window_sign=9)
        macd_val = macd.macd().iloc[-1]
        macd_signal = macd.macd_signal().iloc[-1]
        bb = BollingerBands(data['close'], window=20, window_dev=2)
        bb_high = bb.bollinger_hband().iloc[-1]
        bb_low = bb.bollinger_lband().iloc[-1]
        
        return [sma10, ret, vol, mom, rsi, macd_val, macd_signal, bb_high, bb_low]