Overall Statistics
Total Orders
1059
Average Win
1.02%
Average Loss
-0.76%
Compounding Annual Return
2.798%
Drawdown
31.800%
Expectancy
0.058
Start Equity
100000
End Equity
129403.64
Net Profit
29.404%
Sharpe Ratio
0.075
Sortino Ratio
0.079
Probabilistic Sharpe Ratio
0.170%
Loss Rate
55%
Win Rate
45%
Profit-Loss Ratio
1.35
Alpha
-0.038
Beta
0.676
Annual Standard Deviation
0.152
Annual Variance
0.023
Information Ratio
-0.503
Tracking Error
0.124
Treynor Ratio
0.017
Total Fees
$3338.86
Estimated Strategy Capacity
$860000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
45.05%
# region imports
from AlgorithmImports import *
from sklearn.svm import SVR
from sklearn.model_selection import GridSearchCV
import joblib
# endregion

class ScikitLearnExampleAlgorithm(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2015, 1, 1)
        self.SetEndDate(2024, 5, 1)
        self.SetCash(100000)
        self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol

        training_length = 252*2
        self.training_data = RollingWindow[TradeBar](training_length)
        history = self.History[TradeBar](self.symbol, training_length, Resolution.Daily)
        for trade_bar in history:
            self.training_data.Add(trade_bar)

        if self.ObjectStore.ContainsKey("model"):
            file_name = self.ObjectStore.GetFilePath("model")
            self.model = joblib.load(file_name)

        else:
            param_grid = {'C': [.05, .1, .5, 1, 5, 10], 
                          'epsilon': [0.001, 0.005, 0.01, 0.05, 0.1], 
                          'gamma': ['auto', 'scale']}
            self.model = GridSearchCV(SVR(), param_grid, scoring='neg_mean_squared_error', cv=5)

        self.Train(self.my_training_method)
        self.Train(self.DateRules.Every(DayOfWeek.Sunday), self.TimeRules.At(8,0), self.my_training_method)
        
    def get_features_and_labels(self, n_steps=5):
        training_df = self.PandasConverter.GetDataFrame[TradeBar](list(self.training_data)[::-1])
        daily_pct_change = training_df.pct_change().dropna()

        features = []
        labels = []
        for i in range(len(daily_pct_change)-n_steps):
            features.append(daily_pct_change.iloc[i:i+n_steps].values.flatten())
            labels.append(daily_pct_change['close'].iloc[i+n_steps])
        features = np.array(features)
        labels = np.array(labels)

        return features, labels

    def my_training_method(self):
        features, labels = self.get_features_and_labels()
        if isinstance(self.model, GridSearchCV):
            self.model = self.model.fit(features, labels).best_estimator_
        else:
            self.model = self.model.fit(features, labels)

    def OnData(self, slice: Slice) -> None:
        if self.symbol in slice.Bars:
            self.training_data.Add(slice.Bars[self.symbol])

        features, _ = self.get_features_and_labels()
        prediction = self.model.predict(features[-1].reshape(1, -1))
        prediction = float(prediction)

        if prediction > 0:
            self.SetHoldings(self.symbol, 1)
        elif prediction < 0:            
            self.SetHoldings(self.symbol, -1)

    def OnEndOfAlgorithm(self):
        #model_key = "model"
        #file_name = self.ObjectStore.GetFilePath(model_key)
        #joblib.dump(self.model, file_name)
        #self.ObjectStore.Save(model_key)
        pass