AllTick
Python Quantitative Trading: 5 Classic Strategies with Code
Blog

Python Quantitative Trading Strategies

Learn mean reversion, trend following, pair trading, statistical arbitrage, and volatility trading strategies with Python code examples. Ideal for quant developers.

AllTick5 min read

With the rise of algorithmic trading, Python has become an essential tool for quantitative development practitioners. This is due to Python's powerful ecosystem in scientific computing and data analysis, as well as its excellent third‑party library support. Libraries such as Pandas, NumPy, and SciPy provide rich data processing, numerical computation, and scientific computing functions for quantitative trading, enabling developers to conduct quantitative analysis and strategy development more efficiently. Today we introduce five classic quantitative trading strategies with corresponding Python code examples.

#1 Mean Reversion Strategy

The mean reversion strategy is a statistical arbitrage strategy based on the assumption that, in the long run, asset prices fluctuate around an average value, but eventually return to that long‑term mean. Below is a simple mean reversion strategy code example using a simple moving average to define the "mean" price and standard deviation to generate buy and sell signals. Here is the code:

python

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data = pd.DataFrame({
'Date': pd.date_range(start='2023-01-01', periods=100),
'Close': np.random.normal(100, 10, 100) # generate simulated data
})
data.set_index('Date', inplace=True)

# Calculate 20‑day moving average and standard deviation
window = 20
data['Moving Average'] = data['Close'].rolling(window=window).mean()
data['Standard Deviation'] = data['Close'].rolling(window=window).std()

# Define buy and sell signal thresholds
data['Upper Bound'] = data['Moving Average'] + data['Standard Deviation']
data['Lower Bound'] = data['Moving Average'] - data['Standard Deviation']

# Generate trading signals
# Buy when price is below the mean, sell when above the mean
data['Position'] = 0
data.loc[data['Close'] < data['Lower Bound'], 'Position'] = 1 # buy signal
data.loc[data['Close'] > data['Upper Bound'], 'Position'] = -1 # sell signal

# Plot price and mean reversion bands
plt.figure(figsize=(14, 7))
plt.plot(data['Close'], label='Close Price')
plt.plot(data['Moving Average'], label='Moving Average')
plt.fill_between(data.index, data['Upper Bound'], data['Lower Bound'], color='gray', alpha=0.3, label='Mean Reversion Band')
plt.plot(data.index, data['Position'] * 50, label='Trading Signal', color='magenta')
plt.legend()
plt.show()

#2 Trend Following Strategy

The trend following strategy compares the short‑term average price with the long‑term average to identify the dominant market trend and follow it until the trend reverses. In simple terms, it finds the current market consensus for a stock – if everyone is buying, we follow suit and hold until the trend changes. In Python, we use the Moving Average Convergence Divergence (MACD) to judge short‑term price trends and generate corresponding buy/sell signals.

python

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data = pd.DataFrame({
'Date': pd.date_range(start='2023-01-01', periods=200),
'Close': np.random.normal(100, 15, 200) # simulated data
})
data.set_index('Date', inplace=True)

# Calculate simple moving averages
short_window = 40
long_window = 100
data['Short MA'] = data['Close'].rolling(window=short_window).mean()
data['Long MA'] = data['Close'].rolling(window=long_window).mean()

# Generate trading signals
# Signal when short‑term MA crosses long‑term MA
data['Signal'] = 0
data['Signal'][short_window:] = np.where(data['Short MA'][short_window:] > data['Long MA'][short_window:], 1, 0)
data['Position'] = data['Signal'].diff()

# Plot price and moving averages
plt.figure(figsize=(14, 7))
plt.plot(data['Close'], label='Close Price')
plt.plot(data['Short MA'], label='40-Day Moving Average')
plt.plot(data['Long MA'], label='100-Day Moving Average')
plt.plot(data.index, data['Position'] * 50, label='Trading Signal', color='magenta', marker='o', linestyle='None')
plt.legend()
plt.show()

#3 Pair Trading

Pair trading is based on statistical arbitrage between two different assets that are highly correlated in price. When the price difference between the two deviates beyond the normal range, we buy the undervalued asset and sell the overvalued one. Over the long run, both prices should revert to their mean, but short‑term arbitrage opportunities may appear.

We can analyse the historical price relationship between two assets and generate trading signals based on deviations from the expected spread:

python

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Create simulated price data for two highly correlated assets
np.random.seed(42)
data = pd.DataFrame({
'Date': pd.date_range(start='2023-01-01', periods=180),
'Asset_A': np.random.normal(100, 10, 180).cumsum() + 100,
'Asset_B': np.random.normal(100, 10, 180).cumsum() + 120
})
data.set_index('Date', inplace=True)

# Calculate price difference (spread)
data['Price_Diff'] = data['Asset_A'] - data['Asset_B']

# Calculate moving average and standard deviation of the spread
window = 30
data['Mean_Diff'] = data['Price_Diff'].rolling(window=window).mean()
data['Std_Diff'] = data['Price_Diff'].rolling(window=window).std()

# Set entry and exit thresholds
data['Upper_Bound'] = data['Mean_Diff'] + data['Std_Diff']
data['Lower_Bound'] = data['Mean_Diff'] - data['Std_Diff']

# Generate signals
# Spread > upper bound → short Asset A, long Asset B
# Spread < lower bound → long Asset A, short Asset B
data['Position'] = 0
data.loc[data['Price_Diff'] > data['Upper_Bound'], 'Position'] = -1
data.loc[data['Price_Diff'] < data['Lower_Bound'], 'Position'] = 1

# Plot asset prices and signals
plt.figure(figsize=(14, 7))
plt.subplot(211)
plt.plot(data['Asset_A'], label='Asset A')
plt.plot(data['Asset_B'], label='Asset B')
plt.legend()

plt.subplot(212)
plt.plot(data['Price_Diff'], label='Price Difference')
plt.plot(data['Mean_Diff'], label='Mean Difference')
plt.fill_between(data.index, data['Upper_Bound'], data['Lower_Bound'], color='gray', alpha=0.3, label='Trading Zone')
plt.plot(data.index, data['Position'] * 20, label='Trading Signal', color='magenta', marker='o', linestyle='None')
plt.legend()
plt.show()

#4 Statistical Arbitrage

Statistical arbitrage exploits price differences among multiple assets. One common approach is to identify pairs or portfolios of stocks that deviate from their normal value ranges and trade accordingly to earn profits. Below is a simple statistical arbitrage example in Python, trading based on the spread between two stocks.

python

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

np.random.seed(42)
data = pd.DataFrame({
'Date': pd.date_range(start='2023-01-01', periods=250),
'Stock_A': np.random.normal(0, 1, 250).cumsum() + 50,
'Stock_B': np.random.normal(0, 1, 250).cumsum() + 50
})
data.set_index('Date', inplace=True)

# Calculate spread between two stocks
data['Spread'] = data['Stock_A'] - data['Stock_B']

# Calculate moving average and std of spread
window = 20
data['Spread Mean'] = data['Spread'].rolling(window=window).mean()
data['Spread Std'] = data['Spread'].rolling(window=window).std()

# Set entry and exit thresholds
entry_z = 2
exit_z = 0
data['Upper Threshold'] = data['Spread Mean'] + entry_z * data['Spread Std']
data['Lower Threshold'] = data['Spread Mean'] - entry_z * data['Spread Std']
data['Exit Threshold'] = data['Spread Mean'] + exit_z * data['Spread Std']

# Generate signals
data['Position'] = 0
data.loc[data['Spread'] > data['Upper Threshold'], 'Position'] = -1 # short A, long B
data.loc[data['Spread'] < data['Lower Threshold'], 'Position'] = 1 # long A, short B
data.loc[data['Spread'] * data['Position'] < data['Exit Threshold'], 'Position'] = 0 # exit

# Plot prices and signals
plt.figure(figsize=(14, 7))
plt.subplot(211)
plt.plot(data['Stock_A'], label='Stock A')
plt.plot(data['Stock_B'], label='Stock B')
plt.title('Stock Prices')
plt.legend()

plt.subplot(212)
plt.plot(data['Spread'], label='Spread')
plt.plot(data['Spread Mean'], label='Mean Spread')
plt.fill_between(data.index, data['Upper Threshold'], data['Lower Threshold'], color='gray', alpha=0.3, label='Entry Zone')
plt.plot(data.index, data['Position'] * 10, label='Trading Signal', color='magenta', marker='o', linestyle='None')
plt.title('Spread and Trading Signals')
plt.legend()
plt.show()

#5 Volatility Trading

Volatility strategies profit from changes in market volatility – buying when volatility is low and selling when it is high. For example, we compute daily returns and historical volatility (annualised standard deviation), then set conditions: sell when volatility exceeds 1.2 times the average, buy when it falls below 0.8 times the average. See code below:

python

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

np.random.seed(42)
dates = pd.date_range(start='2023-01-01', periods=250)
prices = np.random.normal(0, 1, 250).cumsum() + 100
data = pd.DataFrame({
'Date': dates,
'Price': prices
})
data.set_index('Date', inplace=True)

# Calculate daily returns
data['Returns'] = data['Price'].pct_change()
data.dropna(inplace=True)

# Calculate historical volatility (using standard deviation as measure)
window = 20
data['Volatility'] = data['Returns'].rolling(window=window).std() * np.sqrt(252) # annualised

# Define strategy
threshold_high = data['Volatility'].mean() * 1.2
threshold_low = data['Volatility'].mean() * 0.8
data['Position'] = 0
data.loc[data['Volatility'] > threshold_high, 'Position'] = -1 # sell on high volatility
data.loc[data['Volatility'] < threshold_low, 'Position'] = 1 # buy on low volatility

# Plot price and volatility
plt.figure(figsize=(14, 10))
plt.subplot(211)
plt.plot(data['Price'], label='Price')
plt.title('Stock Price')
plt.legend()

plt.subplot(212)
plt.plot(data['Volatility'], label='Volatility')
plt.axhline(y=threshold_high, color='r', linestyle='--', label='High Threshold')
plt.axhline(y=threshold_low, color='g', linestyle='--', label='Low Threshold')
plt.plot(data.index, data['Position'] * 0.01, label='Trading Signal', color='magenta', marker='o', linestyle='None')
plt.title('Volatility and Trading Signals')
plt.legend()
plt.show()

Recommended Python Quantitative Trading Books

Doing quantitative trading with Python is a technical skill – you should maintain a lifelong learning mindset and keep improving.

Below are some e‑books I personally consider good, suitable for both beginners and experts. Click the image to start reading directly – feel free to take them. If these books help you, don't forget to recommend them to your friends.

  • 1. Zero‑starting Point Python Big Data and Quantitative Trading – Target: Beginners
    Click to download "Zero‑starting Point Python Big Data and Quantitative Trading".pdf
  • 2. The Road to Quantitative Trading: Stock Quantitative Analysis with Python – Target: Intermediate learners
    Click to download "The Road to Quantitative Trading: Stock Quantitative Analysis with Python".pdf
  • 3. Artificial Intelligence in Finance: Implementing AI Quantitative Trading with Python – Target: Advanced practitioners
    Click to download "Artificial Intelligence in Finance: Implementing AI Quantitative Trading with Python".pdf

【Recommended Reading】Essential Books for Futures Trading
【Recommended Reading】Recommended Books on Quantitative Investment

Start streaming market data today

Generate a free API key in seconds and connect to every market from one endpoint.