Overall Statistics
Total Orders
536
Average Win
2.02%
Average Loss
-0.74%
Compounding Annual Return
5.883%
Drawdown
36.800%
Expectancy
0.280
Start Equity
100000
End Equity
168174.60
Net Profit
68.175%
Sharpe Ratio
0.216
Sortino Ratio
0.209
Probabilistic Sharpe Ratio
0.918%
Loss Rate
66%
Win Rate
34%
Profit-Loss Ratio
2.74
Alpha
-0.004
Beta
0.485
Annual Standard Deviation
0.15
Annual Variance
0.023
Information Ratio
-0.281
Tracking Error
0.152
Treynor Ratio
0.067
Total Fees
$1167.90
Estimated Strategy Capacity
$1100000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
8.64%
#region imports
from AlgorithmImports import *
from tensorflow.keras.models import Sequential, load_model
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras.optimizers import Adam
#endregion
class KerasExampleAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2015, 4, 1)  # Set Start Date
        self.SetEndDate(2024, 5, 1)
        self.SetCash(100000)  # Set Strategy Cash
        self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.SetBenchmark("SPY")

        model_key = "model"
        if self.ObjectStore.ContainsKey(model_key):
            file_name = self.ObjectStore.GetFilePath(model_key)
            self.model = load_model(file_name)
        
        else:
            self.model = Sequential([Dense(10, input_shape=(5,5), activation='relu'),
                            Dense(10, activation='relu'),
                            Dense(5, activation='relu'),
                            Dense(5, activation='relu'),
                            Flatten(),
                            Dense(1)])
            self.model.compile(loss='mse',
                    optimizer=Adam(),
                    metrics=['mae', 'mse'])

        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)

        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) -> Tuple[float, float]:
        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)
            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) -> None:
        features, labels = self.get_features_and_labels()
        self.model.fit(features, labels, epochs=5)

    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()
        features = features[-1].reshape(1, 5, 5)
        prediction = float(self.model.predict(features)[-1])

        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)
        #self.model.save(file_name)