欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 《量化投研宝典》精选了业内持续维护且实用性强的开源工具(Backtrader、Qlib、VeighNa等),配合详细教程与代码示例,帮助您快速构建量化策略;《财经数据宝典》则汇集了多年财经数据维护经验,全面介绍从 AKShare、Tushare 到 Wind、iFind 等国内外数据源,并附有丰富的使用技巧。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!
引言
你是否想过,通过 Python 编程就能让你的投资收益翻倍?今天要分享的这个量化交易策略,不仅实现了 293% 的惊人回报率,更重要的是,它将最大回撤从 37% 降低到了 16%!这意味着在获得高收益的同时,风险反而更小了。
本文将带你深入了解如何使用 Fisher Transform 和 KST(Know Sure Thing)技术指标,结合走步前进优化(Walk-Forward Optimization)方法,构建一个稳健的自适应动量交易策略。
核心策略解析
1. 技术指标介绍
Fisher Transform 指标
Fisher Transform 是一种将价格数据转换为近似正态分布的技术指标,能够更清晰地识别价格转折点。
def calculate_fisher_transform(df, period=10):
"""
计算 Fisher Transform 指标
参数:
df: 包含股票数据的 DataFrame
period: 计算周期,默认为 10
"""
# 计算指定周期内的最高价和最低价
high_rolling = df['High'].rolling(window=period).max()
low_rolling = df['Low'].rolling(window=period).min()
# 标准化价格到 -1 到 1 之间
X = 2 * ((df['Close'] - low_rolling) / (high_rolling - low_rolling) - 0.5)
# 应用 Fisher 变换公式
fisher = 0.5 * np.log((1 + X) / (1 - X))
# 计算信号线(9 期指数移动平均)
fisher_signal = fisher.ewm(span=
9).mean()
return fisher, fisher_signal
KST(Know Sure Thing)指标
KST 是一种动量振荡器,通过组合不同周期的变化率(ROC)来识别市场趋势。
def calculate_kst(df, roc1=10, roc2=15, roc3=20, roc4=30):
"""
计算 KST 指标
参数:
df: 股票数据 DataFrame
roc1-roc4: 不同的变化率周期
"""
# 计算四个不同周期的变化率
r1 = df['Close'].pct_change(roc1).rolling(10).mean()
r2 = df['Close'].pct_change(roc2).rolling(10).mean()
r3 = df['Close'].pct_change(roc3).rolling(10).mean()
r4 = df['Close'].pct_change(roc4).rolling(15).mean()
# 加权组合形成 KST 指标
kst = r1 + 2 * r2 + 3 * r3 + 4 * r4
# 计算信号线和直方图
kst_signal = kst.rolling(9).mean()
kst_hist = kst - kst_signal
return kst, kst_signal, kst_hist
2. 交易信号生成
策略的核心逻辑非常简单:
- 买入信号:当 Fisher Transform 及其信号线都大于 0,且 KST 直方图大于 0
- 卖出信号:当 Fisher Transform 小于 0,信号线大于 0,且 KST 直方图小于 0
def generate_signals_fisher_kst(df):
"""生成买卖信号"""
# 买入条件:三个指标都为正
entry = (df['Fisher'] > 0) & (df['Fisher_Signal'] > 0) & (df['KST_Hist'] > 0)
# 卖出条件:Fisher 转负,KST 直方图转负
exit = (df['Fisher'] 0) & (df['Fisher_Signal'] > 0) & (df['KST_Hist'] 0)
return entry, exit
3. 走步前进优化
这是策略的精髓所在!传统回测容易过度拟合历史数据,而走步前进优化通过滚动窗口的方式,更接近真实交易环境。
def walk_forward_optimization(df, start_year, end_year):
"""
走步前进优化
使用 2:1 的训练测试比例
每年使用前两年的数据训练,第三年测试
"""
results = []
param_combinations = generate_parameter_combinations()
for test_year in range(start_year + 2, end_year + 1):
# 定义训练期(前两年)
train_start = test_year - 2
train_end = test_year - 1
train_data = df[(df.index.year >= train_start) & (df.index.year <= train_end)]
best_params = None
best_performance = -np.inf
# 遍历所有参数组合
for params in param_combinations:
fisher_p, r1, r2, r3, r4 = params
data = train_data.copy()
# 计算指标
data['Fisher'], data['Fisher_Signal'] = calculate_fisher_transform(data, fisher_p)
data['KST'], data['KST_Signal'], data['KST_Hist'] = calculate_kst(data, r1, r2, r3, r4)
# 生成信号并回测
entries, exits = generate_signals_fisher_kst(data)
# 使用 vectorbt 进行回测
pf = vbt.Portfolio.from_signals(
close=data['Open'],
entries=entries.shift(1), # 信号延迟一天执行
exits=exits.shift(1),
init_cash=100_000, # 初始资金 10 万
fees=0.001, # 手续费 0.1%
slippage=0.002, # 滑点 0.2%
freq='D'
)
# 记录最佳参数
performance = pf.total_return()
if performance > best_performance:
best_performance = performance
best_params = params
results.append({
'Year': test_year,
'Best_Params': best_params
})
return pd.DataFrame(results)
实战案例:AJG 股票测试
让我们看看这个策略在 Arthur J. Gallagher & Co(AJG)股票上的表现:
1. 数据准备与运行
import numpy as np
import pandas as pd
import yfinance as yf
import vectorbt as vbt
# 下载股票数据
symbol = 'AJG'
start_date = '2015-01-01'
end_date = '2025-01-01'
df = yf.download(symbol, start=start_date, end=end_date)
# 运行走步前进优化
results = walk_forward_optimization(df, 2018, 2025)
2. 优化结果
系统为每一年找到了最优参数组合:
- 2020 年:(7, 15, 15, 15, 20)
- 2021 年:(8, 5, 10, 30, 20)
- 2022 年:(8, 5, 10, 30, 20)
- 2023 年:(6, 5, 10, 15, 20)
- 2024 年:(6, 15, 15, 15, 25)
- 2025 年:(10, 10, 20, 25, 20)
3. 性能指标对比
量化策略表现:
买入持有表现:
策略稳健性验证
1. Alpha 和 Beta 分析
from scipy.stats import linregress
# 计算策略与基准的关系
portfolio_returns = portfolio.returns()
benchmark_returns = benchmark.returns()
# 线性回归计算 Alpha 和 Beta
slope, intercept, r_value, _, _ = linregress(benchmark_returns, portfolio_returns)
print(f"Alpha: {intercept:.4f}") # 0.0006,年化约 15.12%
print(f"Beta: {slope:.4f}") # 0.5256,风险较低
print(f"相关性: {r_value**2:.4f}") # 0.7215,部分市场驱动
2. 蒙特卡洛模拟
为了验证策略的稳健性,我们进行了 1000 次蒙特卡洛模拟:
# 区块自助法蒙特卡洛模拟
n_simulations = 1000
block_size = 5 # 每个区块 5 天,保持时间序列特性
# 统计结果
print("蒙特卡洛模拟结果(1000 次):")
print(f"平均回报率:329.61%")
print(f"中位数回报率:296.26%")
print(f"5% 分位数回报率:115.10%")
print(f"95% 分位数回报率:643.93%")
print(f"平均最大回撤:18.26%")
print(f"平均夏普比率:1.56")
关键发现:
实用建议
参数选择:不要使用固定参数,走步前进优化能够适应市场变化
风险管理:虽然策略表现优异,但记住过去的业绩不代表未来
扩展应用:可以尝试在其他股票或 ETF 上测试该策略
总结
这个基于 Fisher Transform 和 KST 指标的自适应动量策略展现了量化交易的魅力。通过 Python 编程和科学的回测方法,我们不仅实现了高达 293% 的回报率,更重要的是将风险(最大回撤)降低了一半以上。
走步前进优化方法让策略能够动态适应市场变化,避免了过度拟合的陷阱。蒙特卡洛模拟进一步验证了策略的稳健性,给了我们更多信心。
记住,所有的回测结果都基于历史数据,实盘交易需要谨慎。但这个案例充分展示了 Python 在量化交易中的强大威力——通过编程,我们可以系统化地寻找市场中的交易机会。
参考文章
加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取完整研究解析、详细回测框架代码实现和完整策略逻辑实操指南。财经数据与量化投研知识社区
核心权益如下:
- 赠送《财经数据宝典》完整文档,汇集多年财经数据维护经验
- 赠送《量化投研宝典》完整文档,汇集多年量化投研领域经验
- 赠送《PyBroker-入门及实战》视频课程,手把手学习量化策略开发
星球已有丰富内容积累,包括量化投研论文、财经高频数据、 PyBroker 视频教程、定期直播、数据分享和答疑解难。适合对量化投研和财经数据分析有兴趣的学习者及从业者。欢迎加入我们!