找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1561

积分

0

好友

231

主题
发表于 12 小时前 | 查看: 2| 回复: 0

你是否想过,如何运用简洁的技术指标逻辑,在长期市场波动中捕捉交易机会?今天,我们将深入剖析一个结合了CMO(钱德动量震荡指标)与QQE(量化定性估计指标)的超卖反转策略。该策略遵循一个朴素但有力的交易哲学:在市场出现极端恐慌情绪时入场,在上涨动量开始衰减时离场。下文将详细拆解其核心逻辑,并提供完整的Python实现代码,适合量化交易初学者入门实践。

策略核心逻辑

这个策略建立在一个清晰的二元框架之上:

  • 入场时机:当市场恐慌情绪达到极致,出现非理性抛售时买入。
  • 离场时机:当价格上涨的动能开始减弱、出现衰减迹象时卖出。

问题的关键在于,如何量化定义“恐慌”和“动量衰减”。这正是CMO和QQE两个技术指标发挥作用的舞台。

技术指标详解与实现

1. CMO:钱德动量震荡指标

CMO由Tushar Chande发明,是一个动量振荡器,其数值在-100到100之间波动。当CMO值跌破-50时,通常意味着市场的卖压已达到极端水平,可能处于超卖状态,这构成了我们的入场信号基础。

CMO_LEVEL_OVERSOLD = -50  # 超卖阈值
CMO_PERIOD = 14 # 计算周期

def chande_momentum_oscillator(df, period=CMO_PERIOD):
    """
    计算钱德动量震荡指标(CMO)
    参数:
        df: 包含收盘价的 DataFrame
        period: 计算周期,默认 14 天
    返回:
        添加了 CMO 列的 DataFrame
    """
    diff = df['Close'].diff()  # 计算价格变化
    up = diff.clip(lower=0).rolling(period).sum()  # 上涨幅度之和
    down = (-diff.clip(upper=0)).rolling(period).sum()  # 下跌幅度之和
    df['CMO'] = 100 * (up - down) / (up + down)  # CMO 公式
    return df

def cmo_is_cross_below_oversold(df, level=CMO_LEVEL_OVERSOLD):
    """
    判断 CMO 是否向下穿越超卖线
    这个“穿越”的瞬间被视为恐慌达到顶点,生成潜在入场信号。
    """
    df = chande_momentum_oscillator(df)
    return (df['CMO'] < level) & (df['CMO'].shift(1) >= level)
2. QQE:量化定性估计指标

QQE可以理解为RSI指标的平滑版本,并结合了波动率调整。当QQE指标线(Value1)向下跌破50水平线时,表明当前的上涨动量正在消退,这作为我们离场的信号。

QQE_FACTOR = 4.236  # 波动率乘数
QQE_LEVEL = 50 # 动量阈值
QQE_PERIOD = 14 # RSI 周期
QQE_SMOOTH = 5 # 平滑周期

def calculate_qqe(df, rsi_period=QQE_PERIOD, smooth=QQE_SMOOTH, factor=QQE_FACTOR):
    """
    计算 QQE 指标的两条线(Value1 和 Value2)
    参数:
        df: 包含收盘价的 DataFrame
        rsi_period: RSI 计算周期
        smooth: 平滑窗口
        factor: ATR 波动率乘数
    """
    df = df.copy()

    # 计算 RSI
    delta = df['Close'].diff()
    up = delta.clip(lower=0)
    down = -delta.clip(upper=0)
    roll_up = up.ewm(alpha=1/rsi_period, adjust=False).mean()
    roll_down = down.ewm(alpha=1/rsi_period, adjust=False).mean()
    rsi = 100 - (100 / (1 + roll_up / roll_down))

    # 平滑 RSI
    rsi_ma = rsi.rolling(window=smooth).mean().fillna(method='bfill')

    # 计算 RSI 的波动率(类似 ATR)
    rsi_delta = rsi_ma.diff().abs().fillna(0)
    atr_rsi = rsi_delta.ewm(alpha=1/smooth, adjust=False).mean()

    # 计算 QQE 的两条线
    value1 = rsi_ma.copy()
    value2 = pd.Series(index=df.index, dtype=float)
    value2.iloc[0] = value1.iloc[0]

    for i in range(1, len(df)):
        prev_trail = value2.iloc[i-1]
        prev_value1 = value1.iloc[i-1]
        atr = atr_rsi.iloc[i]
        direction = 1 if prev_value1 > prev_trail else -1
        value2.iloc[i] = prev_trail + direction * factor * atr

    df['QQE_Value1'] = value1
    df['QQE_Value2'] = value2
    return df

def qqe_cross_below_level(df, level=QQE_LEVEL):
    """
    判断 QQE Value1 是否向下穿越阈值线
    这是离场的信号。
    """
    df = calculate_qqe(df)
    return (df['QQE_Value1'] < level) & (df['QQE_Value1'].shift(1) >= level)

完整策略回测代码

以下是完整的策略回测实现,我们使用高效的vectorbt库进行向量化回测。

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

# -------------------------
# 下载历史数据
# -------------------------
symbol = “AVY“ # 示例股票:艾利丹尼森公司
start_date = “2000-01-01“
end_date = “2026-01-01“
interval = “1d“ # 日线数据

df = yf.download(symbol, start=start_date, end=end_date, interval=interval)
df.to_csv(“AVY_clean.csv“, index=False)

# -------------------------
# 生成交易信号
# -------------------------
# 入场信号:CMO向下穿越超卖线
df[“CMO_is_Cross_Below_Oversold“] = cmo_is_cross_below_oversold(df)
entry_conditions = [‘CMO_is_Cross_Below_Oversold‘]
df[‘entry_signal‘] = df[entry_conditions].all(axis=1)

# 离场信号:QQE Value1向下穿越50水平线
df[“QQE_Value1_CrossBelow_Level“] = qqe_cross_below_level(df)
exit_conditions = [‘QQE_Value1_CrossBelow_Level‘]
df[‘exit_signal‘] = df[exit_conditions].all(axis=1)

# -------------------------
# 执行回测
# -------------------------
# 信号延迟一天执行,以模拟更真实的交易场景
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()

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()

回测结果分析

在2000年1月至2025年12月长达约25年的回测区间内,该策略表现如下关键指标(具体数值可能因数据源和细微参数差异略有浮动):

  • 总收益率:约663%
  • 最大回撤:约52%
  • 总交易次数:69次
  • 胜率:约66.67%
  • 盈亏比:约2.08

作为对比,同期简单的买入持有(Buy and Hold)策略的最大回撤高达73%,远高于本策略的52%,体现了该策略在风险控制方面的潜在优势。

策略核心启示

  1. 逆向布局:当CMO指标揭示市场处于极端超卖(恐慌)状态时,往往是逆向投资者寻找机会的窗口。
  2. 动量跟踪离场:无需等到价格趋势完全反转,QQE指标发出的动量衰减信号有助于早期锁定利润,避免大幅回吐。
  3. 理性看待回撤:52%的最大回撤提醒我们,任何旨在获取超额收益的策略都需承担相应的波动风险。
  4. 数据驱动决策:25年间仅触发69次交易,结合超过66%的胜率和大于2的盈亏比,展示了系统化、纪律化交易的统计优势。

风险提示

  • 历史回测业绩不代表未来表现,市场环境与规律可能发生变化。
  • 本文内容仅用于量化交易技术交流与学习,不构成任何投资建议。
  • 所有交易策略均存在风险,应用前请充分理解其逻辑并进行严格测试。

总结

本文详细阐述了一个基于CMO与QQE技术指标的超卖反转策略。其逻辑链条清晰:利用CMO捕捉市场极端恐慌带来的入场机会,借助QQE监控上涨动能的衰减以提示离场。长期的回测数据显示,该策略在控制最大回撤的同时,实现了显著的总收益累积。对于希望入门Python量化交易的朋友而言,这个案例提供了一个从指标理解、信号构建到vectorbt回测的完整实践路径。




上一篇:2种无需Google账号的Chrome浏览器书签同步方案
下一篇:C语言设计哲学解析:为何在系统编程与嵌入式开发中保持简洁高效
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-24 17:20 , Processed in 0.169490 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表