当前位置:首页>python>用 Python 实现"看跌吞没 + 一目均衡图"量化交易策略

用 Python 实现"看跌吞没 + 一目均衡图"量化交易策略

  • 2026-09-02 20:27:51
用 Python 实现"看跌吞没 + 一目均衡图"量化交易策略

2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含300篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!

引言

在量化交易的世界里,价格图表乍看像是无规律的噪音——K 线不停地上下跳动。但隐藏在这些噪音背后的,是交易者们研究了数十年的模式和结构。

今天这篇文章,将带你拆解一个有趣的 Python 量化交易策略:将经典的日本 K 线反转形态(看跌吞没)与一目均衡图(Ichimoku Cloud)相结合,构建一套规则驱动的交易系统,并在长达 25 年的历史数据上进行回测。

这套策略的核心思想非常优雅——用短期恐慌信号入场,用长期趋势结构出场。让我们一步步来看它是如何实现的。

一、准备工作:获取 25 年的市场数据

策略回测的第一步是拿到足够长的历史数据。我们使用 yfinance 下载 CNP(CenterPoint Energy)从 2000 年到 2025 年底的日线数据。

import pandas as pd
import
 numpy as np
import
 yfinance as yf
import
 vectorbt as vbt

# -------------------------

# 下载数据

# -------------------------

symbol = "CNP"  # 股票代码
start_date = "2000-01-01"  # 起始日期
end_date = "2026-01-01"  # 结束日期
interval = "1d"  # 日线级别

# 通过 yfinance 下载历史数据

df = yf.download(symbol, start=start_date, end=end_date, interval=interval)

# 保存为 CSV 文件备用

df.to_csv("CNP_clean.csv", index=False)
df

为什么要用 25 年的数据? 短期回测可能会"骗人"。只有跨越多个市场周期(泡沫、崩盘、横盘、复苏),才能真正检验一个策略的生存能力。

二、策略的两个核心信号

这套系统建立在两个截然不同的市场信号之间的"对话"上。

信号 1:看跌吞没形态(Bearish Engulfing)——入场触发器

看跌吞没是经典的 K 线反转形态。它的出现条件是:

  • • 前一天是阳线(收盘价高于开盘价)
  • • 今天开盘价高于昨天的收盘价
  • • 今天收盘价低于昨天的开盘价
  • • 今天的阴线完全"吞没"了前一天的阳线

简单来说,这是多头力量被空头彻底压制的信号——买方先推高价格,但卖方随后完全接管了控制权。

def bearish_engulfing(df):
    """
    检测看跌吞没形态
    返回布尔型 Series,True 表示当天出现了看跌吞没
    """

    prev_close = df['Close'].shift(1)  # 前一天收盘价
    prev_open = df['Open'].shift(1)    # 前一天开盘价

    return
 (
        (prev_close > prev_open) &        # 前一天是阳线
        (df['Close'] < df['Open']) &       # 今天是阴线
        (df['Open'] > prev_close) &        # 今天开盘高于昨天收盘
        (df['Close'] < prev_open)          # 今天收盘低于昨天开盘
    )

注意:原文 PDF 中的代码对"前一天阳线"的判断写成了 prev_close < prev_open(即前一天是阴线),这与看跌吞没的标准定义不符。标准定义要求前一天是阳线(prev_close > prev_open),上面的代码已做修正。

信号 2:一目均衡图云层交叉(Ichimoku Cloud)——出场触发器

如果看跌吞没是"警报",那一目均衡图就是"天气系统"。

一目均衡图是一套综合性的技术分析工具,包含以下几条线:

  • • 转换线(Tenkan-sen):9 日内最高价与最低价的平均值,反映短期趋势
  • • 基准线(Kijun-sen):26 日内最高价与最低价的平均值,反映中期趋势
  • • 先行带 A(Senkou Span A):转换线和基准线的平均值,向前位移 26 日
  • • 先行带 B(Senkou Span B):52 日内最高价与最低价的平均值,向前位移 26 日
  • • 迟行带(Chikou Span):收盘价向后位移 26 日
# 一目均衡图参数
ICHIMOKU_DISPLACEMENT = 26      # 位移周期
ICHIMOKU_KIJUN_PERIOD = 26      # 基准线周期
ICHIMOKU_SENKOU_B_PERIOD = 52   # 先行带 B 周期
ICHIMOKU_TENKAN_PERIOD = 9      # 转换线周期

def
 calculate_ichimoku(df,
                       tenkan_period=ICHIMOKU_TENKAN_PERIOD,
                       kijun_period=ICHIMOKU_KIJUN_PERIOD,
                       senkou_b_period=ICHIMOKU_SENKOU_B_PERIOD,
                       displacement=ICHIMOKU_DISPLACEMENT
):
    """
    计算一目均衡图的各条线
    """

    df = df.copy()

    # 转换线:9 日最高价与最低价的均值

    df['tenkan_sen'] = (
        df['High'].rolling(tenkan_period).max() +
        df['Low'].rolling(tenkan_period).min()
    ) / 2

    # 基准线:26 日最高价与最低价的均值

    df['kijun_sen'] = (
        df['High'].rolling(kijun_period).max() +
        df['Low'].rolling(kijun_period).min()
    ) / 2

    # 先行带 A:转换线与基准线的均值,向前位移 26 日

    df['senkou_span_a'] = (
        (df['tenkan_sen'] + df['kijun_sen']) / 2
    ).shift(displacement)

    # 先行带 B:52 日最高价与最低价的均值,向前位移 26 日

    df['senkou_span_b'] = (
        (df['High'].rolling(senkou_b_period).max() +
         df['Low'].rolling(senkou_b_period).min()) / 2
    ).shift(displacement)

    # 迟行带:收盘价向后位移 26 日

    df['chikou_span'] = df['Close'].shift(-displacement)

    return
 df

这套策略并不使用一目均衡图的全部信号,而是专注于一个特定事件:先行带 A 从下方向上穿越先行带 B,即看涨交叉。这意味着前方的趋势结构正在转向看涨——此时选择出场。

def senkou_span_cross_bullish(df):
    """
    检测先行带 A 向上穿越先行带 B 的信号(看涨交叉)
    返回布尔型 Series,True 表示当天发生了看涨交叉
    """

    df = calculate_ichimoku(df)
    return
 (
        (df['senkou_span_a'].shift(1) < df['senkou_span_b'].shift(1)) &
        (df['senkou_span_a'] >= df['senkou_span_b'])
    )

三、组合信号:构建交易规则

策略的逻辑非常简洁且具有不对称美感:

  • • 入场:出现看跌吞没形态时买入(捕捉短期恐慌后的反弹机会)
  • • 出场:一目均衡图先行带出现看涨交叉时卖出(长期结构转好时获利了结)
# -------------------------
# 入场条件

# -------------------------

df["Bearish_Engulfing"] = bearish_engulfing(df)

# -------------------------

# 出场条件

# -------------------------

df["Ichimoku_Senkou_Span_Cross_Bullish"] = senkou_span_cross_bullish(df)

# -------------------------

# 生成交易信号

# -------------------------

entry_conditions = ['Bearish_Engulfing']       # 入场条件列表
exit_conditions = ['Ichimoku_Senkou_Span_Cross_Bullish']  # 出场条件列表

# 当所有入场条件同时满足时,生成入场信号

df['entry_signal'] = df[entry_conditions].all(axis=1)
# 当所有出场条件同时满足时,生成出场信号

df['exit_signal'] = df[exit_conditions].all(axis=1)

四、运行回测:让数据说话

使用 vectorbt 进行回测时,策略遵循以下规则以确保公平性:

  • • 信号向后偏移 1 根 K 线,避免"未来函数"偷看
  • • 交易在下一根 K 线的开盘价执行
  • • 包含手续费(0.1%)和滑点(0.2%)
  • • 没有任何人为干预或参数优化
# -------------------------
# 回测执行

# -------------------------


# 将信号向后移动一天,避免使用未来数据

shift_entries = df['entry_signal'].shift(1).astype(bool).fillna(False).to_numpy()
shift_exits = df['exit_signal'].shift(1).astype(bool).fillna(False).to_numpy()

# 使用 vectorbt 构建投资组合并回测

pf = vbt.Portfolio.from_signals(
    close=df['Open'],         # 以开盘价成交
    entries=shift_entries,    # 入场信号
    exits=shift_exits,        # 出场信号
    init_cash=100_000,        # 初始资金 10 万美元
    fees=0.001,               # 手续费 0.1%
    slippage=0.002,           # 滑点 0.2%
    freq='1d'                 # 日线频率
)

# 输出回测统计信息

print
(pf.stats())

# 绘制权益曲线

pf.plot().show()

同时,我们也可以计算"买入并持有"策略作为基准对比:

# -------------------------
# 买入持有基准

# -------------------------

df_holding = df['Open']
pf_holding = vbt.Portfolio.from_holding(
    df_holding,
    init_cash=100_000,  # 初始资金 10 万美元
    fees=0.001           # 手续费 0.1%
)
print
(pf_holding.stats())

五、回测结果解读

以下是该策略在 2000 年至 2025 年间的核心回测指标:

指标
数值
回测区间
2000-01-03 至 2025-12-31
总收益率
806%
最大回撤
88%
总交易次数
68 笔
胜率
49%
盈亏比(Profit Factor)
2.25

策略优势

这套策略在 25 年的回测中跑赢了买入持有策略。盈亏比达到 2.25,说明虽然胜率不到一半,但每次盈利的幅度远大于亏损。68 笔交易意味着平均每年不到 3 笔,避免了过度交易。更重要的是,它将微观层面的 K 线形态与宏观层面的趋势结构巧妙结合。

策略劣势

88% 的最大回撤极为惊人,在实盘中几乎不可承受。49% 的胜率意味着超过一半的交易是亏损的,对交易者心理是巨大考验。此外,入场信号基于下跌形态而非确认信号,时机偏早。实际部署时必须叠加风控手段,如止损、仓位管理等。

六、策略的哲学:简单 ≠ 无效

这套策略真正有趣的地方不仅是回测数字,而是它背后的设计哲学:

  • • 微观信号:一根 K 线的反转形态
  • • 宏观结构:前瞻性的云图趋势判断
  • • 机械执行:没有任何主观判断
  • • 长期验证:跨越多轮牛熊周期

它证明了一件事:不是所有的交易优势都来自复杂模型。有时候,优势恰恰来自"对比"——短期恐慌与长期结构之间的反差。

当然,原文作者也坦诚指出:仅仅在历史数据上回测 25 年是不够的。真正投入实盘之前,还需要进行更多的鲁棒性测试,比如滚动窗口优化(Walk-Forward Optimization)、跨标的验证等。

总结

本文通过拆解一篇量化交易策略文章,带大家用 Python 实现了一套结合"看跌吞没形态"和"一目均衡图云层交叉"的交易系统。

这套策略的核心要点包括:

  1. 1. 使用 yfinance 获取长周期历史数据
  2. 2. 用 Python 函数检测看跌吞没 K 线形态作为入场信号
  3. 3. 计算一目均衡图并检测先行带看涨交叉作为出场信号
  4. 4. 通过 vectorbt 进行信号驱动的回测,包含手续费和滑点
  5. 5. 25 年回测总收益 806%,盈亏比 2.25,但最大回撤高达 88%

最重要的启示:量化交易不是追求完美胜率,而是在概率和赔率之间寻找平衡。一个胜率不到 50% 的策略,只要盈亏比足够高,依然可以长期盈利。但高回撤提醒我们,任何策略都需要配合严格的风险管理。

本文仅供学习交流,不构成任何投资建议。量化交易涉及风险,请务必在充分研究后再做决策。

参考文章

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

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

2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:

  1. 1. 双典系统赋能:获赠《财经数据宝典》与《量化投研宝典》完整文档,凝练多年实战经验,构建系统化知识框架;
  2. 2. 量化因子日更教程(2026重磅新增):每日更新「量化因子专题教程」,配套完整可运行代码与实战案例,深度拆解因子构建、回测与优化全流程;
  3. 3. 量化文章专题教程库:300+篇星球独有高质量教程式文章,系统覆盖策略开发、因子研究、风险管理等核心领域,内容基本每日更新,并配套精选学习资料与实战参考;
  4. 4. PyBroker实战课程:赠送《PyBroker-入门及实战》视频课程,手把手教学,快速掌握量化策略开发技能;
  5. 5. 财经数据支持:定期更新国内外财经数据,为策略研发提供精准、可靠的数据基础;
  6. 6. 顶尖学者与行业专家分享:年度邀请学术界博士与业界资深专家开展前沿论文精讲与实战案例分享,不少于4场,直击研究前沿与产业实践;
    专家直连答疑:与核心开发者及领域专家实时互动,高效解决投研实战难题;
  7. 7. 专业社群与专属福利:加入高质量交流社群,获取课程折扣及更多独家资源。

星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、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 实现指南

最新文章

随机文章