Py学习  »  Python

用 Python 打造稳健交易系统:TSI + GAPO 双指标策略实战

数据科学实战 • 2 天前 • 15 次点击  

欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 《量化投研宝典》精选了业内持续维护且实用性强的开源工具(Backtrader、Qlib、VeighNa等),配合详细教程与代码示例,帮助您快速构建量化策略;《财经数据宝典》则汇集了多年财经数据维护经验,全面介绍从 AKShare、Tushare 到 Wind、iFind 等国内外数据源,并附有丰富的使用技巧。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!

引言

在量化交易的世界里,如何构建一个既能获得超额收益又能控制风险的交易系统,一直是投资者追求的目标。今天,我们将深入探讨一个结合 TSI(真实强度指数)和 GAPO(价格振荡指标)的双指标交易策略。通过 Python 实现完整的回测框架,包括动态参数优化和蒙特卡洛模拟验证,让你了解如何构建和验证一个稳健的交易系统。

策略核心思想

这个交易系统的核心逻辑非常简单:

  • 入场信号:当 TSI 从负值穿越到正值,且 GAPO 低于阈值时买入
  • 出场信号:当 TSI 从正值穿越到负值,且 GAPO 低于阈值时卖出

TSI 指标用于捕捉市场动量,GAPO 指标用于识别市场波动率,两者结合可以在低波动环境下捕捉趋势转折点。

完整代码实现

让我们从导入必要的库开始:

import numpy as np
import pandas as pd
import yfinance as yf  # 用于获取股票数据
import vectorbt as vbt  # 用于回测框架
import itertools  # 用于生成参数组合

1. TSI 指标计算

TSI 是一个动量振荡器,通过双重指数移动平均来平滑价格变化:

def calculate_tsi(close, long=25, short=13):
    """
    计算 TSI(真实强度指数)
    
    参数:
    close: 收盘价序列
    long: 长期 EMA 周期
    short: 短期 EMA 周期
    """

    # 计算价格变化
    diff = close.diff()
    # 计算价格变化的绝对值
    abs_diff = diff.abs()
    
    # 双重 EMA 平滑
    double_ema_diff = diff.ewm(span=long).mean().ewm(span=short).mean()
    double_ema_abs = abs_diff.ewm(span=long).mean().ewm(span=short).mean()
    
    # 计算 TSI
    tsi = 100 * (double_ema_diff / double_ema_abs)
    return tsi

2. GAPO 指标计算

GAPO 指标用于衡量价格的波动性:

def calculate_gapo(df, period=10):
    """
    计算 GAPO(价格振荡指标)
    
    参数:
    df: 包含 High 和 Low 列的数据框
    period: 计算周期
    """

    high = df['High']
    low = df['Low']
    gapo = []
    
    for i in range(period, len(df)):
        # 获取周期内的最高价和最低价
        h = high[i - period:i].max()
        l = low[i - period:i].min()
        
        if h != l:
            r = h - l
            log_r = np.log10(r + 1e-10)   # 避免对 0 取对数
            log_n = np.log10(period)
            gapo_val = 1 - (log_r / log_n)
        else:
            gapo_val = 0
        gapo.append(gapo_val)
    
    return pd.Series([np.nan]*period + gapo, index=df.index)

3. 信号生成器

结合两个指标生成交易信号:

def generate_signals_tsi_gapo(df, tsi_long, tsi_short, tsi_prev_shift, 
                              gapo_period, gapo_threshold)
:

    """
    生成交易信号
    
    参数:
    df: 股票数据
    tsi_long: TSI 长期参数
    tsi_short: TSI 短期参数
    tsi_prev_shift: TSI 前值偏移
    gapo_period: GAPO 周期
    gapo_threshold: GAPO 阈值
    """

    df = df.copy()
    
    # 计算指标
    df['TSI'] = calculate_tsi(df['Close'], long=tsi_long, short=tsi_short)
    df['GAPO'] = calculate_gapo(df, period=gapo_period)
    df['TSI_prev'] = df['TSI'].shift(tsi_prev_shift)
    
    # 生成入场信号:TSI 由负转正且 GAPO 低于阈值
    entry_signal = (
        (df['TSI_prev'] 0) &
        (df['TSI'] > 0) &
        (df['GAPO'] < gapo_threshold)
    )
    
    # 生成出场信号:TSI 由正转负且 GAPO 低于阈值
    exit_signal = (
        (df['TSI_prev'] > 0) &
        (df['TSI'] 0) &
        (df['GAPO'] < gapo_threshold)
    )
    
    return entry_signal, exit_signal

4. Walk-Forward 优化

Walk-Forward 优化是一种动态参数优化方法,它使用滚动窗口的方式,在历史数据上训练参数,然后在未来数据上测试:

def walk_forward_optimization(df, start_year, end_year):
    """
    Walk-Forward 优化
    使用 4 年训练数据,1 年测试数据的滚动窗口
    """

    results = []
    
    # 生成所有参数组合
    param_combinations = generate_parameter_combinations()
    
    for test_year in range(start_year + 4, end_year + 1):
        # 定义训练期
        train_start = test_year - 4
        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:
            tsi_long, tsi_short, tsi_shift, gapo_period, gapo_thresh = params
            
            # 生成信号
            entries, exits = generate_signals_tsi_gapo(
                train_data, tsi_long, tsi_short, 
                tsi_shift, gapo_period, gapo_thresh
            )
            
            # 回测
            pf = vbt.Portfolio.from_signals(
                close=train_data['Open'],
                entries=entries.shift(1).astype(bool).fillna(False),
                exits=exits.shift(1).astype(bool).fillna(False),
                init_cash=100_000,
                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)

实战案例:CVS 股票回测

让我们在 CVS(CVS Health Corporation)股票上应用这个策略:

# 下载数据
symbol = 'CVS'
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, 20162025)
print("Walk Forward 优化结果:")
print(results)

优化结果显示,不同年份的最优参数有所不同,这体现了市场的动态性:

  • 2020-2021 年:TSI(30, 15),GAPO(5, 0.2)
  • 2022 年:TSI(30, 10),GAPO(10, 0.3)
  • 2023-2024 年:TSI(15, 5),GAPO(15, 0.2)

性能评估

1. 基础性能指标

策略在 2020-2025 年的表现:

  • 累计收益率:49.30%
  • 年化收益率:8.84%
  • 最大回撤:-19.68%
  • 夏普比率:0.46
  • 市场暴露时间:16.84%

相比之下,买入持有策略的表现:

  • 累计收益率:-31.67%
  • 年化收益率:-6.78%
  • 最大回撤:-56.50%

2. Alpha 和 Beta 分析

为了更深入地理解策略的表现,我们计算了相对于买入持有策略的 Alpha 和 Beta:

# 计算 Alpha、Beta 和相关性
from scipy.stats import linregress

# 获取策略和基准的收益率
portfolio_returns = portfolio.returns()
benchmark_returns = benchmark.returns()

# 线性回归计算 Beta 和 Alpha
slope, intercept, r_value, _, _ = linregress(
    benchmark_returns, portfolio_returns
)
beta = slope
alpha = intercept
correlation = r_value

print(f"Alpha: {alpha:.4f}")  # 0.0004
print(f"Beta: {beta:.4f}")   # 0.2030
print(f"相关性: {correlation:.4f}")  # 0.4505

结果解读:

  • Alpha = 0.0004:日均超额收益 0.04%,年化约 10.6%
  • Beta = 0.203:策略波动性仅为市场的 20%,风险显著降低
  • 相关性 = 0.45:与市场中度相关,具有一定的独立性

3. 蒙特卡洛模拟验证

为了验证策略的稳健性,我们使用区块引导法(Block Bootstrap)进行蒙特卡洛模拟:

# 区块引导蒙特卡洛模拟
n_simulations = 1000
block_size = 5  # 每个区块包含 5 个连续交易日

# 统计指标
below_benchmark_return_count = 0
above_benchmark_drawdown_count = 0

for _ in range(n_simulations):
    # 随机抽取区块并重组
    block_indices = np.random.randint(
        0, len(returns) - block_size + 1
        size=n_blocks
    )
    sampled_returns = np.concatenate(
        [returns[i:i+block_size] for i in block_indices]
    )[:n_days]
    
    # 计算模拟路径的指标
    equity = init_value * np.cumprod(1 + sampled_returns)
    total_return = (equity[-1] / init_value) - 1
    max_dd = np.max(1 - equity / np.maximum.accumulate(equity))
    
    # 统计表现不如基准的情况
    if total_return < benchmark_return:
        below_benchmark_return_count += 1
    if max_dd > benchmark_drawdown:
        above_benchmark_drawdown_count += 1

模拟结果(1000 次):

  • 平均收益率:57.16%
  • 5% 分位数收益率:-9.18%
  • 95% 分位数收益率:156.21%
  • 平均最大回撤:20.60%
  • 收益低于基准的概率:0.4%(仅 4 次)
  • 回撤高于基准的概率:0%(0 次)

策略优势与局限

优势

  1. 风险控制出色:最大回撤从 57% 降至 20%,降幅近三分之二
  2. 低市场暴露:仅 16.84% 的时间持仓,大幅降低市场风险
  3. 参数自适应:Walk-Forward 优化确保参数随市场变化调整
  4. 稳健性强:蒙特卡洛模拟显示策略表现稳定

局限

  1. 交易次数较少:5 年仅 14 笔交易,统计显著性有限
  2. 参数敏感性:需要定期重新优化参数
  3. 滑点影响:实盘交易可能面临更高的交易成本

总结

本文介绍了一个基于 TSI 和 GAPO 双指标的量化交易策略,通过 Python 实现了完整的回测框架。策略在 CVS 股票上展现出优秀的风险调整后收益,特别是在市场下跌期间仍能获得正收益。

关键要点:

  1. 双指标结合可以提高信号质量,TSI 捕捉动量,GAPO 过滤波动
  2. Walk-Forward 优化是验证策略稳健性的重要方法
  3. 蒙特卡洛模拟可以评估策略在不同市场情况下的表现
  4. 风险控制比追求高收益更重要,降低回撤是长期盈利的关键

需要注意的是,历史回测结果不代表未来表现,实盘交易前需要充分考虑市场风险。建议读者在理解策略原理的基础上,根据自己的风险偏好进行调整和优化。

参考文章

加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取完整研究解析、详细回测框架代码实现和完整策略逻辑实操指南。

财经数据与量化投研知识社区

核心权益如下:

  1. 赠送《财经数据宝典》完整文档,汇集多年财经数据维护经验
  2. 赠送《量化投研宝典》完整文档,汇集多年量化投研领域经验
  3. 赠送《PyBroker-入门及实战》视频课程,手把手学习量化策略开发
  4. 每日分享高质量量化投研文章、代码和相关资料
  5. 定期更新高频财经数据
  6. 参与年度不少于 10 次专属直播与录播课程
  7. 与核心开发者直接交流,解决实际问题
  8. 获取专业微信群交流机会和课程折扣

星球已有丰富内容积累,包括量化投研论文、财经高频数据、 PyBroker 视频教程、定期直播、数据分享和答疑解难。适合对量化投研和财经数据分析有兴趣的学习者及从业者。欢迎加入我们!

好文推荐

1. 用 Python 打造股票预测系统:Transformer 模型教程(一)

2. 用 Python 打造股票预测系统:Transformer 模型教程(二)

3. 用 Python 打造股票预测系统:Transformer 模型教程(三)

4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)

5. 揭秘隐马尔可夫模型:因子投资的制胜武器

6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用

7. 金融 AI 助手:FinGPT 让你轻松掌握市场分析

8. 量化交易秘籍:为什么专业交易员都在用对数收益率?

9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解

10. 掌握金融波动率模型:完整 Python 实现指南

好书推荐

《Python编程:从入门到实践(第3版)》是一本广受欢迎的 Python 入门经典教材,由经验丰富的程序员 Eric Matthes 编写。该书采用循序渐进的教学方式,从基础语法讲解到实战项目开发,内容编排合理,实例丰富,语言通俗易懂。全书配有大量练习题和完整项目实战,包括数据可视化、网络爬虫、Web 应用开发等,让读者在实践中掌握编程技巧。第3版还增加了 f-string、海龟绘图等最新的 Python 特性内容。这本书不仅适合零基础读者入门学习,也非常适合想系统掌握 Python 的编程爱好者以及数据分析、人工智能等领域的学习者。它不仅教授编程知识,更注重培养读者的编程思维,是一本非常值得投资的 Python 学习指南。


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/183642
 
15 次点击