🚀 AI 一键生成 joinquant 策略代码

JoinQuant 量化交易:利用佳庆指标 (Chaikin Oscillator) 监控资金流

joinquant | 发布时间: 2025/12/24
以下内容由 EasyQuant 生成。

问题描述

如何利用佳庆指标 CHO 编写量化交易策略?

解决方案

佳庆指标(Chaikin Oscillator,简称 CHO)是由马克·佳庆(Marc Chaikin)发明的,它本质上是累积/派发线(Accumulation/Distribution Line, ADL)的移动平均线差值

CHO 结合了价格和成交量,用于衡量资金流入(累积)和流出(派发)的动量。它类似于 MACD,但应用于 ADL 指标而非价格本身。

1. 佳庆指标 (CHO) 的计算原理

CHO 的计算步骤如下:

  1. 计算资金流量乘数 (CLV)
    $$CLV = \frac{(收盘价 - 最低价) - (最高价 - 收盘价)}{最高价 - 最低价}$$
  2. 计算资金流量 (Money Flow Volume)
    $$Money Flow Volume = CLV \times 成交量$$
  3. 计算累积/派发线 (ADL)
    $$ADL_{今日} = ADL_{昨日} + Money Flow Volume_{今日}$$
  4. 计算 CHO
    $$CHO = EMA(ADL, 3) - EMA(ADL, 10)$$
    (通常使用 3日 EMA 和 10日 EMA)

2. 交易策略逻辑

在本示例策略中,我们将采用经典的零轴交叉策略:

  • 买入信号:CHO 线由下向上穿过零轴(金叉)。这表明短期资金流入动能强于长期,市场进入累积阶段。
  • 卖出信号:CHO 线由上向下穿过零轴(死叉)。这表明短期资金流出动能增强,市场进入派发阶段。

3. 聚宽 (JoinQuant) 策略代码实现

以下是一个完整的策略代码,您可以直接复制到聚宽的回测环境中运行。代码使用了 talib 库来计算 CHO,以确保计算的高效和准确。

# -*- coding: utf-8 -*-
import jqdata
import talib
import numpy as np

def initialize(context):
    """
    初始化函数,设定基准、手续费、滑点等
    """
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    
    # 设定操作的股票(示例:平安银行)
    g.security = '000001.XSHE'
    
    # CHO指标参数
    g.fast_period = 3   # 短周期
    g.slow_period = 10  # 长周期
    
    # 设定交易费用
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')

def handle_data(context, data):
    """
    按天运行的策略函数
    """
    security = g.security
    
    # 1. 获取历史数据
    # 获取足够长的数据以确保EMA计算稳定,通常取 slow_period 的 3-4 倍以上
    # 这里获取过去 60 天的 High, Low, Close, Volume
    h_data = attribute_history(security, 60, '1d', ['high', 'low', 'close', 'volume'])
    
    # 如果数据不足(例如停牌或刚上市),则跳过
    if len(h_data) < 40:
        return

    # 2. 提取数据为 numpy 数组,供 talib 使用
    high = h_data['high'].values
    low = h_data['low'].values
    close = h_data['close'].values
    volume = h_data['volume'].values
    
    # 3. 计算 CHO 指标
    # talib.ADOSC(high, low, close, volume, fastperiod=3, slowperiod=10)
    # 注意:talib计算的是 Chaikin Oscillator
    cho = talib.ADOSC(high, low, close, volume, fastperiod=g.fast_period, slowperiod=g.slow_period)
    
    # 获取当前和前一天的 CHO 值
    current_cho = cho[-1]
    prev_cho = cho[-2]
    
    # 检查是否计算出有效值(剔除 NaN)
    if np.isnan(current_cho) or np.isnan(prev_cho):
        return

    # 4. 获取当前账户资金和持仓
    cash = context.portfolio.available_cash
    curr_position = context.portfolio.positions[security].closeable_amount
    
    # 5. 生成交易信号
    
    # 买入信号:CHO 上穿 0 轴
    if prev_cho < 0 and current_cho > 0:
        if cash > 0:
            # 全仓买入
            order_value(security, cash)
            log.info(f"买入信号: CHO上穿0轴 (前值:{prev_cho:.2f}, 现值:{current_cho:.2f})")
            
    # 卖出信号:CHO 下穿 0 轴
    elif prev_cho > 0 and current_cho < 0:
        if curr_position > 0:
            # 清仓卖出
            order_target(security, 0)
            log.info(f"卖出信号: CHO下穿0轴 (前值:{prev_cho:.2f}, 现值:{current_cho:.2f})")

    # 6. 绘制图表(可选)
    record(CHO=current_cho)

4. 策略优化建议

单纯使用 CHO 进行零轴交叉交易可能会在震荡市中产生较多虚假信号。在实际量化研究中,通常会结合以下方法进行优化:

  1. 结合趋势过滤器
    • 引入移动平均线(如 MA60 或 MA200)。只有当价格位于均线之上(趋势向上)时,才执行 CHO 的买入信号;当价格位于均线之下时,忽略买入信号或仅执行卖出信号。
  2. 背离分析
    • 底背离:股价创新低,但 CHO 没有创新低(底部抬高),通常是强烈的买入信号。
    • 顶背离:股价创新高,但 CHO 没有创新高(顶部降低),通常是强烈的卖出信号。
    • 注:编写背离策略需要识别局部极值点,逻辑比零轴交叉复杂。
  3. 阈值调整
    • 不使用 0 作为界限,而是设定一个缓冲区。例如:CHO > 5000 买入,CHO < -5000 卖出(具体数值取决于成交量级,或者对 CHO 进行标准化处理)。

Q&A

Q1: 为什么代码中要使用 talib.ADOSC 而不是自己写公式计算?
A1: talib 是底层的 C 语言库,计算速度极快且经过了广泛验证。自己编写公式容易在 EMA 初始化或数据对齐上出错。在量化平台中,优先使用标准库是最佳实践。

Q2: CHO 指标和 MACD 有什么区别?
A2: MACD 是基于价格的 EMA 差值,反映价格趋势;CHO 是基于**ADL(累积/派发线)**的 EMA 差值,反映资金流向(成交量)的动量。CHO 通常能比单纯的价格指标更早发现趋势的反转,因为“量在价先”。

Q3: 这个策略适合什么类型的股票?
A3: CHO 严重依赖成交量数据,因此它更适合成交量活跃、流动性好的个股(如沪深300成分股)。对于成交量极不规则或经常停牌的股票,CHO 可能会产生剧烈波动和误导性信号。