随着算法交易的兴起,Python已经成为量化开发从业者的必备工具。这得益于Python在科学计算和数据分析领域的强大生态系统,以及其优秀的第三方库的支持。其中,像Pandas、Numpy和Scipy等库为量化交易提供了丰富的数据处理、数值计算和科学计算功能,使得开发者能够更高效地进行量化分析和策略开发。今天为大家介绍五个经典的量化交易策略,以及对应的Python代码示例。

#1 均值回归策略

均值回归策略是一种统计套利策略,它是基于这样一种假设,即:长期来看,资产价格会围绕一个平均价值上下波动,但无论如何波动,价格最终都会回归到它的长期均值上来。下面是一个简单的均值回归策略的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)  # 生成一些模拟数据
})
data.set_index('Date', inplace=True)

# 计算20日移动均线和标准差
window = 20
data['Moving Average'] = data['Close'].rolling(window=window).mean()
data['Standard Deviation'] = data['Close'].rolling(window=window).std()

# 定义买入和卖出的信号阈值
data['Upper Bound'] = data['Moving Average'] + data['Standard Deviation']
data['Lower Bound'] = data['Moving Average'] - data['Standard Deviation']

# 生成交易信号
# 当价格低于均值时买入,高于均值时卖出
data['Position'] = 0
data.loc[data['Close'] < data['Lower Bound'], 'Position'] = 1  # 买入信号
data.loc[data['Close'] > data['Upper Bound'], 'Position'] = -1  # 卖出信号

# 绘制价格和均值回归带
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 趋势跟踪策略

趋势跟踪策略是指对比资产价格的短期均价与长期均价,找出目前市场的主导趋势,并跟随这一趋势,直到趋势扭转。简单来说就是找出一支股票现在的市场主流看法,如果大家都买入,我们也顺势而为,买入这支股票并持有,直到市场趋势开始反转。在Python代码的实现上,是利用移动平均收敛/发散(MACD)来判断短期的价格趋势,并根据趋势来生成对应的买入/卖出信号。

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)  # 生成一些模拟数据
})
data.set_index('Date', inplace=True)

# 计算简单移动平均线
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()

# 生成交易信号
# 当短期移动平均线穿越长期移动平均线时产生信号
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()

# 绘制价格和移动平均线
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)

配对交易主要基于两种不同资产之间价格差异的统计套利,前提是这两种资产在价格上有非常强的相关性。当两者的价格差异超出正常范围时,我们买入被低估的资产,同时卖出被高估的资产。从长期来看,这两个资产的价格都应该回归到长期均值,但短期内可能会出现套利机会。

我们可以分析两个资产之间的历史价格关系,并根据它们预期差价的偏离创造交易信号:

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=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)

# 计算两个资产的价格差(价差)
data['Price_Diff'] = data['Asset_A'] - data['Asset_B']

# 计算价差的移动平均和标准差
window = 30
data['Mean_Diff'] = data['Price_Diff'].rolling(window=window).mean()
data['Std_Diff'] = data['Price_Diff'].rolling(window=window).std()

# 设置入市和清仓的门槛
data['Upper_Bound'] = data['Mean_Diff'] + data['Std_Diff']
data['Lower_Bound'] = data['Mean_Diff'] - data['Std_Diff']

# 生成交易信号
# 价差大于上界时做空Asset A,做多Asset B
# 价差小于下界时做多Asset A,做空Asset B
data['Position'] = 0
data.loc[data['Price_Diff'] > data['Upper_Bound'], 'Position'] = -1  # 做空Asset A,做多Asset B
data.loc[data['Price_Diff'] < data['Lower_Bound'], 'Position'] = 1   # 做多Asset A,做空Asset B

# 绘制资产价格和交易信号
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 统计套利

统计套利是利用多种资产之间的价格差异进行套利。其中一种常见的方法是通过寻找价值偏离正常范围的股票对或资产组合,并进行相应的买卖以赚取利润。以下是一个使用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)

# 计算两个股票的价差
data['Spread'] = data['Stock_A'] - data['Stock_B']

# 计算价差的移动平均和标准差
window = 20
data['Spread Mean'] = data['Spread'].rolling(window=window).mean()
data['Spread Std'] = data['Spread'].rolling(window=window).std()

# 设置买入和卖出的阈值
entry_z = 2  # 买入Z分数
exit_z = 0   # 卖出Z分数
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']

# 生成交易信号
data['Position'] = 0
data.loc[data['Spread'] > data['Upper Threshold'], 'Position'] = -1  # 做空Stock A,做多Stock B
data.loc[data['Spread'] < data['Lower Threshold'], 'Position'] = 1   # 做多Stock A,做空Stock B
data.loc[data['Spread'] * data['Position'] < data['Exit Threshold'], 'Position'] = 0  # 退出信号

# 绘制股票价格和交易信号
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 波动性交易

波动策略利用市场的波动性变化来进行交易,从而在波动性的升高或降低中获利。比如我们可以先计算股票的日收益率和历史波动性(其实就是年化标准差),然后设置一个条件:当波动性高于平均水平1.2倍时卖出,低于均值0.8倍时买入,具体看下面的代码:

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)

# 计算日收益率
data['Returns'] = data['Price'].pct_change()
data.dropna(inplace=True)

# 计算历史波动性(这里我们使用标准差作为波动性的度量)
window = 20
data['Volatility'] = data['Returns'].rolling(window=window).std() * np.sqrt(252)  # 年化波动性

# 定义交易策略
# 波动性高于某个值时卖出,低于某个值时买入
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  # 高波动性时卖出
data.loc[data['Volatility'] < threshold_low, 'Position'] = 1   # 低波动性时买入

# 绘制价格图和波动性图
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()