当前位置:首页>python>亏损 40% 的“烂股”,Python 策略却反赚 164%?

亏损 40% 的“烂股”,Python 策略却反赚 164%?

  • 2026-10-11 05:55:16
亏损 40% 的“烂股”,Python 策略却反赚 164%?

用 Python 揭秘均值回归策略:你的收益从何而来?

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

引言

在投资世界里,有一类股票最让长期持有者头疼:它不会归零,也不会干脆利落地崩盘让你死心,而是年复一年地横盘、阴跌、偶尔反弹。AES 这家在纽交所上市的全球电力公司,就是典型代表。

从 2000 年 1 月到 2025 年 12 月,整整 25 年里,单纯买入并持有 AES 的投资者会亏掉将近 40% 的本金(基准收益 -39.80%)。这不是一段“小回调”,而是长达四分之一世纪的价值毁灭。

于是问题来了:如果这只股票本身是个“赔钱货”,一套系统化的交易策略,能否从它的波动噪声里榨出收益?本文就用 Python 带大家完整复现这套策略,看看结果到底如何。

策略思路:动量遇上均值回归

这套策略的核心思想,是回答一个具体的问题:这只股票是不是被暂时打到了超卖区,而短期动量正在悄悄回升?

它由两个指标组成,逻辑非常清晰:

  • • 入场信号:动量指标 AO(Awesome Oscillator,动量震荡指标)正在上升
  • • 离场信号:收盘价跌破 Keltner Channel(肯特纳通道)下轨

下面我们逐个拆解。

第一步:用 AO 判断动量是否回升

AO 衡量的是“中位价”的 5 周期简单移动平均与 34 周期简单移动平均之差。这里有个关键细节:我们不只要求 AO 为正,而是要求它比 5 根 K 线之前更高,以此确认短期买盘正在加速。

import pandas as pd

# AO 参数设置

AO_CHANGE_SHIFT_1 = 5   # 用于对比 5 根 K 线前的数值
AO_LONG_PERIOD = 34     # 长周期 SMA
AO_SHORT_PERIOD = 5     # 短周期 SMA

def
 calculate_ao(df, short_period=AO_SHORT_PERIOD, long_period=AO_LONG_PERIOD):
    """计算 Awesome Oscillator(动量震荡指标)"""

    df = df.copy()
    # 中位价 = (最高价 + 最低价)/ 2

    df["MedianPrice"] = (df["High"] + df["Low"]) / 2
    # 短周期与长周期的简单移动平均

    df["SMA_short"] = df["MedianPrice"].rolling(window=short_period).mean()
    df["SMA_long"] = df["MedianPrice"].rolling(window=long_period).mean()
    # AO = 短周期均线 - 长周期均线

    df["AO"] = df["SMA_short"] - df["SMA_long"]
    return
 df

def
 ao_is_rising(df, short_period=AO_SHORT_PERIOD,
                 long_period=AO_LONG_PERIOD, shift=AO_CHANGE_SHIFT_1
):
    """判断 AO 是否在上升:当前值 > 5 根 K 线前的值"""

    df = calculate_ao(df, short_period, long_period)
    return
 df["AO"] > df["AO"].shift(shift)

小知识补充:AO 由著名交易者 Bill Williams 提出,本质上是一个衡量市场动能的柱状图。用“当前值高于 N 根 K 线前”的写法,比单纯看正负号更能捕捉“动能拐头向上”的瞬间,能有效过滤掉在零轴附近反复震荡的假信号。

第二步:用 Keltner Channel 控制离场

离场条件是收盘价跌破肯特纳通道下轨。该通道以 20 周期的典型价 EMA 为中轨,上下轨分别为中轨加减 2 倍 ATR(平均真实波幅)。一旦收盘价跌穿下轨,就说明价格已被打到了一个经过波动率调整后的极端位置,此时果断离场止损。

KC_MULTIPLIER = 2    # 通道宽度倍数
KC_PERIOD = 20       # 计算周期

def
 calculate_keltner_channel(df, period=KC_PERIOD, multiplier=KC_MULTIPLIER):
    """计算肯特纳通道(中轨、上轨、下轨)和 ATR"""

    df = df.copy()
    # 典型价 = (最高价 + 最低价 + 收盘价)/ 3

    df["TP"] = (df["High"] + df["Low"] + df["Close"]) / 3
    # 中轨:典型价的指数移动平均(EMA)

    df["KC_Mid"] = df["TP"].ewm(span=period, adjust=False).mean()

    # 计算真实波幅 TR,再求 ATR

    df["H-L"] = df["High"] - df["Low"]
    df["H-PC"] = abs(df["High"] - df["Close"].shift(1))
    df["L-PC"] = abs(df["Low"] - df["Close"].shift(1))
    df["TR"] = df[["H-L", "H-PC", "L-PC"]].max(axis=1)
    df["ATR"] = df["TR"].rolling(period).mean()

    # 上轨与下轨

    df["KC_Upper"] = df["KC_Mid"] + multiplier * df["ATR"]
    df["KC_Lower"] = df["KC_Mid"] - multiplier * df["ATR"]
    return
 df

def
 kc_close_below_lower(df):
    """判断收盘价是否跌破下轨"""

    df = calculate_keltner_channel(df)
    return
 df["Close"] < df["KC_Lower"]

易错点提醒:肯特纳通道与布林带(Bollinger Bands)很像,但通道宽度用的是 ATR 而非标准差,因此对极端跳空更敏感,更适合用来界定“波动率意义上的极端价位”。

第三步:组合信号并回测

把入场、离场条件组合起来,用 vectorbt 完成回测。注意一个工程上的关键细节:信号当天不立刻成交,而是在次日开盘价执行,并加入 0.1% 手续费和 0.2% 滑点,初始资金 10 万美元。这样做是为了避免“用今天才知道的信号去交易今天”的未来函数陷阱。

import vectorbt as vbt

# 生成入场、离场信号

df["AO_Rising"] = ao_is_rising(df)
df["KC_Close_Below_Lower"] = kc_close_below_lower(df)
df["entry_signal"] = df["AO_Rising"]
df["exit_signal"] = df["KC_Close_Below_Lower"]

# 关键:信号延后一天执行,用次日开盘价成交,避免未来函数

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

# 构建投资组合:用开盘价成交,含手续费与滑点

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())   # 打印绩效指标

回测结果:低胜率,却能盈利

跑完 26 年数据,结果相当有看头:

  • • 总收益:约 164%(10 万 → 约 26.37 万美元)
  • • 基准(买入持有):-39.80%
  • • 最大回撤:85.61%,持续约 2743 天
  • • 总交易数:92 笔(91 笔已平仓,1 笔仍持有)
  • • 胜率:仅 32.97%
  • • 盈利因子:1.08

这里最反直觉的一点是:胜率只有 33%,相当于每 3 笔交易里输掉 2 笔,但策略整体却是盈利的。

秘密在于盈亏的不对称:

  • • 最赚的一笔赚了 403.53%,最亏的一笔只亏 34.16%
  • • 平均盈利交易赚 35.07%,平均持有 111 天
  • • 平均亏损交易仅亏 9.65%,平均 35 天就被止损出局

“小亏快跑、大赚慢走” 正是这套系统能活下来的引擎。这也印证了量化交易里一句老话:胜率高不等于赚钱,盈亏比和期望值才是关键。

真正的痛点:长达八年的回撤

漂亮的总收益掩盖了一个残酷事实:最大回撤高达 85.61%,且持续了近 8 年(2743 天)。最痛苦的阶段在 2001—2003 年,安然事件引发能源板块崩塌,AES 从 40 美元上方一路跌到 2 美元以下。

8 年的水下煎熬,已经不是回测里的一个数字,而是对人性的极限拷问。绝大多数交易者根本撑不到 2021—2022 年那波把累计收益推到近 5 倍的反弹。

这也是为什么夏普比率只有 0.352、卡玛比率仅 0.065——收益确实存在,但代价是巨大的波动与煎熬。

与买入持有的对比

对比非常清晰:同样 10 万美元,单纯买入持有 26 年后只剩约 6.02 万美元(尚未计入分红),而策略却把它变成了约 26.37 万美元。在一只长期没有方向、只有波动的股票上,一套基于规则的均值回归纪律,确实能榨出被动持有者拿不到的收益。

需要强调的是,这并非对 AES 的“看多背书”。它长期跑输背后是能源转型压力、拉美货币风险等结构性逆风,这些都不是任何震荡指标能预测的。策略的真正价值,是用机械化纪律避免了最糟糕的结局——傻傻持有 25 年。

总结

这套“动量 + 均值回归”策略给 Python 量化学习者的启示很实在:

  1. 1. 策略逻辑要清晰:入场看动量回升(AO 上升),离场看波动率极端(跌破通道下轨),两个指标各司其职。
  2. 2. 胜率不是一切:33% 的胜率照样盈利,关键在盈亏比和期望值,靠“大赚小亏”取胜。
  3. 3. 回撤才是真考验:85% 的回撤、8 年水下,任何漂亮收益都要先问问自己扛不扛得住。
  4. 4. 工程细节决定成败:次日开盘价成交、计入手续费与滑点,是避免高估收益的基本功。
  5. 5. 单次回测远远不够:26 年的历史回测只是起点,还需要走向前优化(Walk-Forward)等稳健性测试,才能判断策略能否在真实市场存活。

最后照例提醒:本文仅用于 Python 与量化学习交流,不构成任何投资建议。所有回测都基于历史数据,无法保证未来表现,实盘前请务必自行充分研究与测试。

参考文章

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

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

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

  1. 1. 双典系统赋能:获赠《财经数据宝典》与《量化投研宝典》完整文档,凝练多年实战经验,构建系统化知识框架;
  2. 2. 量化因子日更教程(2026重磅新增):每日更新「量化因子专题教程」,配套完整可运行代码与实战案例,深度拆解因子构建、回测与优化全流程;
  3. 3. 量化文章专题教程库:500+篇星球独有高质量教程式文章,系统覆盖策略开发、因子研究、风险管理等核心领域,内容基本每日更新,并配套精选学习资料与实战参考;
  4. 4. 量化投研实战课程:赠送《AKQuant-入门及实战》《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 实现指南

好书推荐

最新文章

随机文章