Overall Statistics |
Total Orders 959 Average Win 2.10% Average Loss -0.15% Compounding Annual Return 0.146% Drawdown 42.700% Expectancy 0.161 Start Equity 100000 End Equity 100782.67 Net Profit 0.783% Sharpe Ratio -0.054 Sortino Ratio -0.071 Probabilistic Sharpe Ratio 0.556% Loss Rate 92% Win Rate 8% Profit-Loss Ratio 13.85 Alpha -0.001 Beta -0.08 Annual Standard Deviation 0.165 Annual Variance 0.027 Information Ratio -0.436 Tracking Error 0.247 Treynor Ratio 0.111 Total Fees $1043.14 Estimated Strategy Capacity $980000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 4.58% |
# region imports from AlgorithmImports import * import torch from torch import nn import joblib # endregion class PyTorchExampleAlgorithm(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 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[float](training_length) history = self.History[TradeBar](self.symbol, training_length, Resolution.Daily) for trade_bar in history: self.training_data.Add(trade_bar.Close) if self.ObjectStore.ContainsKey("model"): file_name = self.ObjectStore.GetFilePath("model") self.model = joblib.load(file_name) else: device = 'cuda' if torch.cuda.is_available() else 'cpu' self.model = NeuralNetwork().to(device) 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): close_prices = list(self.training_data)[::-1] features = [] labels = [] for i in range(len(close_prices)-n_steps): features.append(close_prices[i:i+n_steps]) labels.append(close_prices[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() # Set the loss and optimization functions # In this example, use the mean squared error as the loss function and stochastic gradient descent as the optimizer loss_fn = nn.MSELoss() learning_rate = 0.001 optimizer = torch.optim.SGD(self.model.parameters(), lr=learning_rate) # Create a for-loop to train for preset number of epoch epochs = 10 for t in range(epochs): # Create a for-loop to fit the model per batch for batch, (feature, label) in enumerate(zip(features, labels)): # Compute prediction and loss pred = self.model(feature) real = torch.from_numpy(np.array(label).flatten()).float() loss = loss_fn(pred, real) # Perform backpropagation optimizer.zero_grad() loss.backward() optimizer.step() def OnData(self, slice: Slice) -> None: if self.symbol in slice.Bars: self.training_data.Add(slice.Bars[self.symbol].Close) features, __ = self.get_features_and_labels() prediction = self.model(features[-1].reshape(1, -1)) prediction = float(prediction.detach().numpy()[-1]) if prediction > slice[self.symbol].Price: self.SetHoldings(self.symbol, 1) elif prediction < slice[self.symbol].Price: 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 class NeuralNetwork(nn.Module): # Model Structure def __init__(self): super(NeuralNetwork, self).__init__() self.flatten = nn.Flatten() self.linear_relu_stack = nn.Sequential( nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 5), # input size, output size of the layer nn.ReLU(), # Relu non-linear transformation nn.Linear(5, 5), nn.ReLU(), nn.Linear(5, 1), # Output size = 1 for regression ) # Feed-forward training/prediction def forward(self, x): x = torch.from_numpy(x).float() # Convert to tensor in type float result = self.linear_relu_stack(x) return result