---
title: "PyTorch"
description: "Learn how to create, train, and evaluate machine learning models in the research environment in QuantConnect with PyTorch library."
canonical: https://www.quantconnect.com/docs/v2/research-environment/machine-learning/popular-libraries/pytorch
markdown: https://www.quantconnect.com/docs/v2/research-environment/machine-learning/popular-libraries/pytorch.md
language: python
source: https://github.com/QuantConnect/Documentation/tree/master/04%20Research%20Environment/08%20Machine%20Learning/03%20Popular%20Libraries/05%20PyTorch
modified: 2026-10-28
index: https://www.quantconnect.com/llms.txt
---

# PyTorch

[Documentation](https://www.quantconnect.com/docs/v2.md) > [Research Environment](https://www.quantconnect.com/docs/v2/research-environment.md) > Machine Learning > [Popular Libraries](https://www.quantconnect.com/docs/v2/research-environment/machine-learning/popular-libraries.md) > PyTorch

> Code examples are shown in Python. Append `?lang=csharp` to this URL for the C# version of this page.

## Introduction

This page explains how how to build, train, test, and store `PyTorch` models.

## Import Libraries

Import the `torch`, `sklearn`, and `joblib` libraries by the following:

```python
import torch
from torch import nn
from sklearn.model_selection import train_test_split
import joblib
```

You need the `sklearn` library to prepare the data and the `joblib` library to store models.

## Get Historical Data

[Get some historical market data](https://www.quantconnect.com/docs/v2/research-environment/datasets/us-equity.md#04-Get-Historical-Data) to train and test the model. For example, to get data for the SPY ETF during 2020 and 2021, run:

```python
qb = QuantBook()
symbol = qb.add_equity("SPY", Resolution.DAILY).symbol
history = qb.history(symbol, datetime(2020, 1, 1), datetime(2022, 1, 1)).loc[symbol]
```

## Prepare Data

You need some [historical data](https://www.quantconnect.com/docs/v2/research-environment/machine-learning/popular-libraries/pytorch.md#03-Get-Historical-Data) to prepare the data for the model. If you have historical data, manipulate it to train and test the model. In this example, use the following features and labels:

| Data Category | Description |
| --- | --- |
| Features | The last 5 closing prices |
| Labels | The following day's closing price |

The following image shows the time difference between the features and labels:

![Features and labels for training](https://cdn.quantconnect.com/i/tu/ml-keras-function.png)

Follow these steps to prepare the data:

1. Perform fractional differencing on the historical data.
   ```python
   df = (history['close'] * 0.5 + history['close'].diff() * 0.5)[1:]
   ```
   Fractional differencing helps make the data stationary yet retains the variance information.
2. Loop through the `df` DataFrame and collect the features and labels.
   ```python
   n_steps = 5
   features = []
   labels = []
   for i in range(len(df)-n_steps):
       features.append(df.iloc[i:i+n_steps].values)
       labels.append(df.iloc[i+n_steps])
   ```
3. Convert the lists of features and labels into `numpy` arrays.
   ```python
   features = np.array(features)
   labels = np.array(labels)
   ```
4. Standardize the features and labels
   ```python
   X = (features - features.mean()) / features.std()
   y = (labels - labels.mean()) / labels.std()
   ```
5. Split the data into training and testing periods.
   ```python
   X_train, X_test, y_train, y_test = train_test_split(X, y)
   ```

## Train Models

You need to [prepare the historical data](https://www.quantconnect.com/docs/v2/research-environment/machine-learning/popular-libraries/pytorch.md#04-Prepare-Data) for training before you train the model. If you have prepared the data, build and train the model. In this example, create a deep neural network with 2 hidden layers. Follow these steps to create the model:

1. Define a subclass of `nn.Module` to be the model.
   In this example, use the ReLU activation function for each layer.
   ```python
   class NeuralNetwork(nn.Module):
       # Model Structure
       def __init__(self):
           super(NeuralNetwork, self).__init__()
           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, 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
   ```
2. Create an instance of the model and set its configuration to train on the GPU if it's available.
   ```python
   device = 'cuda' if torch.cuda.is_available() else 'cpu'
   model = NeuralNetwork().to(device)
   ```
3. 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.
   ```python
   loss_fn = nn.MSELoss()
   learning_rate = 0.001
   optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
   ```
4. Train the model.
   In this example, train the model through 5 epochs.
   ```python
   epochs = 5
   for t in range(epochs):
       print(f"Epoch {t+1}\n-------------------------------")

       # Since we're using SGD, we'll be using the size of data as batch number.
       for batch, (X, y) in enumerate(zip(X_train, y_train)):
           # Compute prediction and loss
           pred = model(X)
           real = torch.from_numpy(np.array(y).flatten()).float()
           loss = loss_fn(pred, real)

           # Backpropagation
           optimizer.zero_grad()
           loss.backward()
           optimizer.step()

           if batch % 100 == 0:
               loss, current = loss.item(), batch
               print(f"loss: {loss:.5f}  [{current:5d}/{len(X_train):5d}]")
   ```
   ![Pytorch model training summary](https://cdn.quantconnect.com/i/tu/pytorch-train.png)

## Test Models

You need to [build and train the model](https://www.quantconnect.com/docs/v2/research-environment/machine-learning/popular-libraries/pytorch.md#05-Train-Models) before you test its performance. If you have trained the model, test it on the out-of-sample data. Follow these steps to test the model:

1. Predict with the testing data.
   ```python
   predict = model(X_test)
   y_predict = predict.detach().numpy()   # Convert tensor to numpy ndarray
   ```
2. Plot the actual and predicted values of the testing period.
   ```python
   df = pd.DataFrame({'Real': y_test.flatten(), 'Predicted': y_predict.flatten()})
   df.plot(title='Model Performance: predicted vs actual standardized fractional return', figsize=(15, 10))
   plt.show()
   ```
   ![Pytorch model performance](https://cdn.quantconnect.com/i/tu/pytorch-plot.png)
3. Calculate the R-square value.
   ```python
   r2 = 1 - np.sum(np.square(y_test.flatten() - y_predict.flatten())) / np.sum(np.square(y_test.flatten() - y_test.mean()))
   print(f"The explained variance by the model (r-square): {r2*100:.2f}%")
   ```
   ![Pytorch model r-square](https://cdn.quantconnect.com/i/tu/pytorch-rsquare-2.png)

## Store Models

You can save and load `PyTorch` models using the Object Store.

### Save Models

Don't use the `torch.save` method to save models because the tensor data will be lost and corrupt the save. Follow these steps to save models in the Object Store:

1. Set the key name of the model to be stored in the Object Store.
   ```python
   model_key = "model"
   ```
2. Call the `get_file_path` method with the key.
   ```python
   file_name = qb.object_store.get_file_path(model_key)
   ```
   This method returns the file path where the model will be stored.
3. Call the `dump` method with the model and file path.
   ```python
   joblib.dump(model, file_name)
   ```
   If you dump the model using the `joblib` module before you save the model, you don't need to retrain the model.

### Load Models

You must save a model into the Object Store before you can load it from the Object Store. If you saved a model, follow these steps to load it:

1. Call the `contains_key` method.
   ```python
   qb.object_store.contains_key(model_key)
   ```
   This method returns a boolean that represents if the `model_key` is in the Object Store. If the Object Store does not contain the `model_key`, save the model using the `model_key` before you proceed.
2. Call the `get_file_path` method with the key.
   ```python
   file_name = qb.object_store.get_file_path(model_key)
   ```
   This method returns the path where the model is stored.
3. Call the `load` method with the file path.
   ```python
   loaded_model = joblib.load(file_name)
   ```
   This method returns the saved model.

## Examples

The following examples demonstrate some common practices for using the Pytorch library.

### Example 1: Predict Next Return

The following research notebook uses `Pytorch` machine learning model to predict the next day's return by the previous 5 days' daily fractional differencing.

```python
# Import the Pytorch library and others.
import torch
from torch import nn
from sklearn.model_selection import train_test_split
import joblib

# Instantiate the QuantBook for researching.
qb = QuantBook()
# Request the daily SPY history with the date range to be studied.
symbol = qb.add_equity("SPY", Resolution.DAILY).symbol
history = qb.history(symbol, datetime(2020, 1, 1), datetime(2022, 1, 1)).loc[symbol]

# Perform fractional differencing on the historical data.
df = (history['close'] * 0.5 + history['close'].diff() * 0.5)[1:]
# We use the previous 5 day fractional differencing as the features to be studied.
# Get the 1-day forward differencing as the labels for the machine to learn.
n_steps = 5
features = []
labels = []
for i in range(len(df)-n_steps):
    features.append(df.iloc[i:i+n_steps].values)
    labels.append(df.iloc[i+n_steps])

# Clean the data and normalize for fast convergence.
features = np.array(features)
labels = np.array(labels)
X = (features - features.mean()) / features.std()
y = (labels - labels.mean()) / labels.std()

# Split the data as a training set and test set for validation. In this example, we use 70% of the data points to train the model and test with the rest.
X_train, X_test, y_train, y_test = train_test_split(X, y)

# Define a subclass of nn.Module to be the model. In this example, use the ReLU activation function for each layer.
class NeuralNetwork(nn.Module):
    # Model Structure
    def __init__(self):
        super(NeuralNetwork, self).__init__()
        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, 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
# Create an instance of the model and set its configuration to train on the GPU if it's available.
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = NeuralNetwork().to(device)
# 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(model.parameters(), lr=learning_rate)
# Train the model. In this example, train the model through 5 epochs.
epochs = 5
for t in range(epochs):
    print(f"Epoch {t+1}\n-------------------------------")

    # Since we're using SGD, we'll be using the size of data as batch number.
    for batch, (X, y) in enumerate(zip(X_train, y_train)):
        # Compute prediction and loss
        pred = model(X)
        real = torch.from_numpy(np.array(y).flatten()).float()
        loss = loss_fn(pred, real)

        # Backpropagation
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 100 == 0:
            loss, current = loss.item(), batch
            print(f"loss: {loss:.5f}  [{current:5d}/{len(X_train):5d}]")

# Predict with the testing data.
predict = model(X_test)
y_predict = predict.detach().numpy()   # Convert tensor to numpy ndarray
# Plot the actual and predicted labels of the testing period.
df = pd.DataFrame({'Real': y_test.flatten(), 'Predicted': y_predict.flatten()})
df.plot(title='Model Performance: predicted vs actual standardized fractional return', figsize=(15, 10))
plt.show()
# Calculate the R-square value.
r2 = 1 - np.sum(np.square(y_test.flatten() - y_predict.flatten())) / np.sum(np.square(y_test.flatten() - y_test.mean()))
print(f"The explained variance by the model (r-square): {r2*100:.2f}%")

# Store the model in the object store to allow accessing the model in the next research session or in the algorithm for trading.
model_key = "model"
file_name = qb.object_store.get_file_path(model_key)
joblib.dump(model, file_name)
```
