社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

收益率从 32% 飙升至 168%!用 Python 贝叶斯优化打造超级交易策略

数据科学实战 • 4 月前 • 325 次点击  

欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 我们提供了精选的国内外量化投研的 180+ 篇高质量文章,并每日更新最新研究成果,涵盖策略开发、因子分析、风险管理等核心领域。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!

引言

在量化交易的世界里,策略的参数选择往往决定了最终的成败。许多交易者习惯凭经验或感觉“手动”调整参数,这不仅效率低下,而且很难找到最优解。

这就好比在大海捞针,你可能永远不知道是否存在更好的参数组合。

今天我们要介绍的案例来自 Brian Hulela,他通过 贝叶斯优化 (Bayesian Optimization) 技术,将一个经典的 Ichimoku Cloud (一目均衡表) 交易策略的四年期回报率,从原本不错的 31.77% 惊人地提升到了 **167.50%**,同时还将最大回撤 (Max Drawdown) 从 -32% 降低到了 -21%。

本文将带你一步步通过 Python 复现这个过程,看看数据科学是如何赋能金融交易的。

什么是 Ichimoku 策略与贝叶斯优化?

在开始代码实战之前,我们先简单理解两个核心概念:

  1. **Ichimoku Cloud (一目均衡表)**:这是一种多功能的如意指标,用于定义支撑位和阻力位,识别趋势方向,衡量动量并提供交易信号。它主要由 Tenkan (转折线)、Kijun (基准线) 和 Senkou B (先行带 B) 等线条组成。
  2. 贝叶斯优化:这是一种寻找函数最大值或最小值的策略。与暴力尝试所有可能的参数组合 (网格搜索) 不同,贝叶斯优化会根据之前的测试结果来“智能”地猜测下一组最可能带来更好结果的参数,从而高效地找到最优解。

Python 实战案例

接下来,我们将使用 yfinance 获取数据,并利用 scikit-optimize 库进行参数优化。

1. 环境准备

首先,我们需要安装必要的 Python 库。

# 安装必要的软件包
# yfinance: 下载历史股价数据
# matplotlib: 绘图可视化
# tabulate: 格式化表格输出
# scikit-optimize: 执行贝叶斯优化
%pip install yfinance matplotlib tabulate scikit-optimize -q

导入所需的库:

import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
from tabulate import tabulate
from skopt import gp_minimize
from skopt.space import Integer
import numpy as np

# 设置绘图风格 (可选)
plt.style.use('seaborn-v0_8')

2. 获取历史数据

在这个案例中,我们以  AAPL (苹果公司) 从 2020 年到 2024 年的股票数据为例。

# 下载历史股票数据
symbol = "AAPL"
data = yf.download(symbol, start="2020-01-01", end="2024-12-31")

# 扁平化多层列索引 (处理 yfinance 新版格式)
if isinstance(data.columns, pd.MultiIndex):
    data.columns = data.columns.get_level_values(0)

# 查看前几行数据
print(data.head())

3. 定义 Ichimoku 策略逻辑

这是核心部分。我们需要编写一个函数,根据输入的参数 (Tenkan,Kijun,Senkou B 的周期) 计算指标,生成买卖信号,并计算回测的收益率。

策略逻辑如下:

  • 买入信号:收盘价高于云带 (Senkou A 和 B 的最大值),且 Tenkan 线金叉 Kijun 线。
  • 卖出信号:收盘价跌破云带。
def ichimoku_signals(data, tenkan_period, kijun_period, senkou_b_period):
    """
    计算 Ichimoku 指标并进行简单的回测
    """

    df = data.copy()
    high = df['High']
    low = df['Low']
    
    # 1. 计算 Ichimoku 线条
    # Tenkan-sen (转折线): (过去 N 期的最高价 + 最低价) / 2
    df['tenkan'] = (high.rolling(tenkan_period).max() + low.rolling(tenkan_period).min()) / 2
    
    # Kijun-sen (基准线): (过去 M 期的最高价 + 最低价) / 2
    df['kijun'] = (high.rolling(kijun_period).max() + low.rolling(kijun_period).min()) / 2
    
    # Senkou Span A (先行带 A): (Tenkan + Kijun) / 2,向未来平移 Kijun 周期
    df['senkou_a'] = ((df['tenkan'] + df['kijun']) / 2).shift(kijun_period)
    
    # Senkou Span B (先行带 B): (过去 P 期的最高价 + 最低价) / 2,向未来平移 Kijun 周期
    df['senkou_b'] = ((high.rolling(senkou_b_period).max() + low.rolling(senkou_b_period).min()) / 2).shift(kijun_period)
    
     # 2. 生成信号
    # 价格在云带之上
    df['above_cloud'] = df['Close'] > df[['senkou_a''senkou_b']].max(axis=1)
    
    # Tenkan 上穿 Kijun (金叉)
    # 当前 Tenkan > Kijun 且 上一期 Tenkan <= 上一期 Kijun
    df['tenkan_cross'] = (df['tenkan'] > df['kijun']) & (df['tenkan'].shift(1) <= df['kijun'].shift(1))
    
    # 综合买入信号
    df['signal'] = np.where(df['above_cloud'] & df['tenkan_cross'], 10)
    
    # 3. 回测逻辑
    balance = 10000  # 初始资金 10000 美元
    position = 0     # 持仓状态
    equity_curve = []
    
    for i in range(len(df)):
        current_close = df['Close'].iloc[i]
        
        # 买入逻辑
        if df['signal'].iloc[i] == 1 and position == 0:
            position = balance / current_close
            balance = 0
        
        # 卖出/止损逻辑: 价格跌破云带
        elif position > 0 and current_close < df[['senkou_a''senkou_b']].min(axis=1).iloc[i]:
            balance = position * current_close
            position = 0
            
        # 记录每日权益
        current_equity = balance + position * current_close
        equity_curve.append(current_equity)
        
    df['equity'] = equity_curve
    
    # 计算总回报率
    total_return = (df['equity'].iloc[-1] - 10000) / 10000 * 100
    
    return df, total_return

4. 使用贝叶斯优化寻找最佳参数

我们定义一个目标函数。因为优化器通常是寻找“最小值”,而我们想要“最大化”收益,所以我们返回收益率的负数。

# 定义目标函数
def objective(params):
    tenkan, kijun, senkou_b = params
    # 运行策略并获取回报率
    _, total_return = ichimoku_signals(data, tenkan, kijun, senkou_b)
    # 返回负值,因为 gp_minimize 是求最小值的
    return -total_return

# 定义参数的搜索空间
# Tenkan 周期范围: 5 到 20
# Kijun 周期范围: 20 到 50
# Senkou B 周期范围: 40 到 100
search_space = [
    Integer(520, name='tenkan_period'),
    Integer(2050, name='kijun_period'),
    Integer(40100, name='senkou_b_period')
]

# 运行贝叶斯优化
print("开始优化参数,请稍候...")
result = gp_minimize(
    objective, 
    search_space, 
    n_calls=25,       # 尝试 25 次组合
    random_state=42   # 保证结果可复现
)

print("优化完成!")

5. 结果分析与可视化

优化完成后,我们提取最佳参数,并再次运行策略以查看详细表现。

best_tenkan, best_kijun, best_senkou_b = result.x
best_return = -result.fun

# 使用优化后的参数运行策略
data_optimized, final_return = ichimoku_signals(data.copy(), best_tenkan, best_kijun, best_senkou_b)

# 计算最大回撤 (Max Drawdown)
max_equity = data_optimized['equity'].cummax()
drawdown = (data_optimized['equity'] - max_equity) / max_equity
max_drawdown = drawdown.min() * 100

# 打印结果表格
stats = [
    ["优化后的 Tenkan 周期", best_tenkan],
    ["优化后的 Kijun 周期", best_kijun],
    ["优化后的 Senkou B 周期", best_senkou_b],
    ["预期总回报率"f"{best_return:.0f}%"],
    ["最大回撤"f"{max_drawdown:.0f}%"]
]

print(tabulate(stats, headers=["指标""数值"], tablefmt="rounded_outline"))

输出结果示例:

╭──────────────────────┬───────╮
│ 指标                 │ 数值  │
├──────────────────────┼───────┤
│ 优化后的 Tenkan 周期  │ 19    │
│ 优化后的 Kijun 周期   │ 20    │
│ 优化后的 Senkou B 周期│ 98    │
│ 预期总回报率          │ 168%  │
│ 最大回撤             │ -21%  │
╰──────────────────────┴───────╯

通过对比,我们发现:

  • 手动参数:回报率约 31.77%,最大回撤 -32%。
  • 优化参数:回报率飙升至 168%,最大回撤缩小至 -21%。

这说明优化后的策略不仅更赚钱,而且风险更低 (回撤更小)。

最后,我们可以绘制出优化后的交易信号图:

# 提取买卖点用于绘图
buy_signals = data_optimized[(data_optimized['signal'] == 1) & (data_optimized['signal'].shift(1) == 0)]
# 注意:这里为了简化绘图,只标记开仓点,实际平仓逻辑在回测循环中

plt.figure(figsize=(148))
plt.plot(data_optimized.index, data_optimized['Close'], label="收盘价", color='black', alpha=0.6)

# 绘制云带
plt.fill_between(
    data_optimized.index, 
    data_optimized['senkou_a'], 
    data_optimized['senkou_b'],
    where=data_optimized['senkou_a'] >= data_optimized['senkou_b'],
    color='lightgreen', alpha=0.3, label='看涨云带'
)
plt.fill_between(
    data_optimized.index, 
    data_optimized['senkou_a'], 
    data_optimized['senkou_b'],
    where=data_optimized['senkou_a'] < data_optimized['senkou_b'],
    color='lightcoral', alpha=0.3, label='看跌云带'
)

plt.title(f"{symbol} Ichimoku 策略 (优化后参数) 交易信号")
plt.xlabel("日期")
plt.ylabel("价格 ($)")
plt.legend()
plt.show()

总结

本文展示了如何利用 Python 的  scikit-optimize 库对经典的 Ichimoku 交易策略进行贝叶斯优化。

  1. 告别盲猜:通过算法自动寻找参数,替代了低效的手动尝试。
  2. 显著提升:在 AAPL 的案例中,回报率从 30% 级跃升至 160% 级,且风险控制更好。
  3. 方法通用:这套贝叶斯优化的逻辑不仅限于 Ichimoku,你可以将其应用到 MACD,RSI 或任何带有参数的量化策略中。

量化交易的核心在于数据驱动。当你下次构建策略时,不妨试试让算法来帮你做决定。

参考文章

加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。

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

核心权益如下:

  1. 赠送《财经数据宝典》完整文档,汇集多年财经数据维护经验
  2. 赠送《量化投研宝典》完整文档,汇集多年量化投研领域经验
  3. 赠送《PyBroker-入门及实战》视频课程,手把手学习量化策略开发
  4. 每日分享高质量量化投研文章(已更新 180+篇)、代码和相关资料
  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社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/189555