
Python算法交易策略
随着算法交易的兴起,Python已成为量化开发人员不可或缺的工具。这主要得益于Python在科学计算和数据分析领域强大的生态系统,以及优秀的第三方
随着算法交易的兴起,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)
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 配对交易
配对交易是一种基于两个高度相关资产之间价格差异的统计套利策略。当两者之间的价差偏离正常范围时,我们买入被低估的资产并卖出被高估的资产。从长期来看,它们的价格应回归均值,从而带来短期套利机会。
我们可以分析两个资产之间的历史价格关系,并根据其偏离预期价差的程度创建交易信号:
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']
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
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']
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 倍时买入。以下是相应的 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)
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()