100.3 AI量化面试题:解释配对交易(Pairs Trading)的原理,并说明如何选择配对股票以及设计交易信号
目录
- 0. 承前
- 1. 配对交易基本原理
- 1.1 什么是配对交易
- 1.2 基本假设
- 2. 配对选择方法
- 2.1 相关性分析
- 2.2 协整性检验
- 3. 价差计算方法
- 3.1 简单价格比率
- 3.2 回归系数法
- 4. 交易信号设计
- 4.1 标准差方法
- 4.2 动态阈值方法
- 5. 风险管理
- 5.1 止损设计
- 5.2 仓位管理
- 6. 策略评估
- 6.1 回测框架
- 6.2 性能指标
- 7. 回答话术
0. 承前
如果想更加全面清晰地了解金融资产组合模型进化论的体系架构,可参考:
0. 金融资产组合模型进化全图鉴
1. 配对交易基本原理
1.1 什么是配对交易
配对交易(Pairs Trading)是一种市场中性策略,核心思想是找到两个价格走势高度相关的金融资产,当它们之间的价差偏离历史均值时进行交易,等待价差回归获利。主要特点:
- 市场中性:对冲了系统性风险
- 均值回归:基于价差回归特性
- 统计套利:依赖统计规律获利
1.2 基本假设
- 两个资产存在长期均衡关系
- 价差的短期偏离最终会回归
- 回归过程中的交易成本低于预期收益
2. 配对选择方法
2.1 相关性分析
import pandas as pd
import numpy as np
from scipy.stats import pearsonr
def find_correlated_pairs(price_data, threshold=0.8):
"""
寻找相关性高的股票对
"""
n_stocks = len(price_data.columns)
pairs = []
# 计算相关系数矩阵
corr_matrix = price_data.pct_change().corr()
# 筛选高相关对
for i in range(n_stocks):
for j in range(i+1, n_stocks):
corr = corr_matrix.iloc[i,j]
if abs(corr) > threshold:
pairs.append((
price_data.columns[i],
price_data.columns[j],
corr
))
return pd.DataFrame(pairs, columns=['stock1', 'stock2', 'correlation'])
2.2 协整性检验
from statsmodels.tsa.stattools import coint
def cointegration_test(price1, price2, significance=0.05):
"""
对股票对进行协整性检验
"""
score, pvalue, _ = coint(price1, price2)
return {
'score': score,
'pvalue': pvalue,
'is_cointegrated': pvalue < significance
}
def find_cointegrated_pairs(pairs_df, price_data):
"""
从相关性高的股票对中筛选协整对
"""
cointegrated_pairs = []
for _, row in pairs_df.iterrows():
stock1, stock2 = row['stock1'], row['stock2']
test_result = cointegration_test(
price_data[stock1],
price_data[stock2]
)
if test_result['is_cointegrated']:
cointegrated_pairs.append({
'stock1': stock1,
'stock2': stock2,
'correlation': row['correlation'],
'coint_pvalue': test_result['pvalue']
})
return pd.DataFrame(cointegrated_pairs)
3. 价差计算方法
3.1 简单价格比率
def calculate_price_ratio(price1, price2):
"""
计算价格比率
"""
return price1 / price2
def calculate_log_ratio(price1, price2):
"""
计算对数价格比率
"""
return np.log(price1) - np.log(price2)
3.2 回归系数法
from sklearn.linear_model import LinearRegression
def calculate_hedge_ratio(price1, price2):
"""
计算对冲比率
"""
model = LinearRegression()
model.fit(price2.values.reshape(-1,1), price1.values)
hedge_ratio = model.coef_[0]
# 计算价差
spread = price1 - hedge_ratio * price2
return hedge_ratio, spread
4. 交易信号设计
4.1 标准差方法
class PairsTrader:
def __init__(self, window=20, entry_threshold=2, exit_threshold=0.5):
self.window = window
self.entry_threshold = entry_threshold
self.exit_threshold = exit_threshold
def generate_signals(self, spread):
"""
生成交易信号
"""
# 计算移动均值和标准差
rolling_mean = spread.rolling(window=self.window).mean()
rolling_std = spread.rolling(window=self.window).std()
# 计算z-score
z_score = (spread - rolling_mean) / rolling_std
# 生成信号
signals = pd.Series(index=spread.index, data=0)
# 开仓信号
signals[z_score > self.entry_threshold] = -1 # 做空spread
signals[z_score < -self.entry_threshold] = 1 # 做多spread
# 平仓信号
signals[abs(z_score) < self.exit_threshold] = 0
return signals
4.2 动态阈值方法
class DynamicThresholdTrader:
def __init__(self, window=20, quantile=0.95):
self.window = window
self.quantile = quantile
def calculate_dynamic_threshold(self, spread):
"""
计算动态阈值
"""
rolling_quantile = spread.rolling(window=self.window).quantile(self.quantile)
rolling_min = spread.rolling(window=self.window).min()
upper_threshold = rolling_quantile
lower_threshold = rolling_min
return upper_threshold, lower_threshold
def generate_signals(self, spread):
upper, lower = self.calculate_dynamic_threshold(spread)
signals = pd.Series(index=spread.index, data=0)
signals[spread > upper] = -1
signals[spread < lower] = 1
return signals
5. 风险管理
5.1 止损设计
class RiskManager:
def __init__(self, max_loss_pct=0.02, max_holding_days=10):
self.max_loss_pct = max_loss_pct
self.max_holding_days = max_holding_days
def check_stop_loss(self, position, current_pnl):
"""
检查止损条件
"""
if position != 0: # 有持仓
if current_pnl < -self.max_loss_pct:
return True
return False
def check_time_stop(self, position, holding_days):
"""
检查时间止损
"""
if position != 0 and holding_days > self.max_holding_days:
return True
return False
5.2 仓位管理
def calculate_position_size(spread_volatility, account_value, risk_per_trade=0.01):
"""
计算仓位大小
"""
# 基于波动率的仓位计算
position_size = account_value * risk_per_trade / spread_volatility
return position_size
def adjust_for_correlation(position_size, correlation):
"""
根据相关性调整仓位
"""
# 相关性越高,仓位越大
adjusted_size = position_size * abs(correlation)
return adjusted_size
6. 策略评估
6.1 回测框架
class PairsStrategy:
def backtest(self, price_data, pairs):
results = []
for pair in pairs:
# 计算价差
spread = self.calculate_spread(
price_data[pair['stock1']],
price_data[pair['stock2']]
)
# 生成信号
signals = self.generate_signals(spread)
# 计算收益
returns = self.calculate_returns(signals, spread)
# 计算指标
metrics = self.calculate_metrics(returns)
results.append(metrics)
return pd.DataFrame(results)
6.2 性能指标
def calculate_performance_metrics(returns):
"""
计算策略表现指标
"""
metrics = {
'sharpe_ratio': returns.mean() / returns.std() * np.sqrt(252),
'max_drawdown': (returns.cumsum() - returns.cumsum().cummax()).min(),
'win_rate': (returns > 0).mean(),
'profit_factor': abs(returns[returns > 0].sum() / returns[returns < 0].sum()),
'annual_return': returns.mean() * 252
}
return metrics
通过以上详细的策略框架和代码示例,我们可以看到配对交易是一个系统性的策略,需要在配对选择、信号生成、风险管理等多个环节都进行精心设计。成功的配对交易策略需要持续监控和优化,以适应不断变化的市场环境。
7. 回答话术
配对交易是一种市场中性策略,核心是寻找价格走势高度相关的资产对,在价差偏离时进行交易,等待回归获利。策略实施分为四个关键步骤:
首先,通过相关性分析和协整性检验选择合适的配对;其次,采用价格比率或回归系数法计算价差;然后,基于标准差或动态阈值设计交易信号;最后,配合止损和仓位管理进行风险控制。
策略评估需要通过回测框架,计算夏普比率、最大回撤、胜率等指标来衡量策略表现。成功的配对交易需要持续监控和优化,以适应市场变化。