🚀 AI 一键生成 joinquant 策略代码

如何用 Python 实现唐奇安通道(Donchian Channel)突破策略?

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

问题描述

请帮我编写一个基于唐奇安通道的突破交易策略

解决方案

这是一个基于**唐奇安通道(Donchian Channel)**的趋势突破策略。

策略原理

唐奇安通道由理查德·唐奇安(Richard Donchian)提出,是海龟交易法则的核心技术指标之一。

  1. 上轨:过去 $N$ 天的最高价。
  2. 下轨:过去 $M$ 天的最低价。
  3. 买入信号:当当前价格突破过去 $N$ 天的最高价(上轨)时,做多。
  4. 卖出信号:当当前价格跌破过去 $M$ 天的最低价(下轨)时,平仓。

策略代码

以下代码可以直接在聚宽(JoinQuant)的回测环境中运行。为了演示方便,本策略选取沪深300ETF (510300.XSHG) 作为交易标的,采用经典的 20日突破买入,10日跌破卖出 的参数设置。

# -*- coding: utf-8 -*-
# 导入聚宽函数库
import jqdata

def initialize(context):
    """
    初始化函数,设定基准、手续费、滑点、策略参数
    """
    # 1. 设定基准(沪深300指数)
    set_benchmark('000300.XSHG')
    
    # 2. 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 3. 设置手续费:买入万三,卖出万三加千一印花税,最低5元
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 4. 设定要操作的股票(这里以沪深300ETF为例,方便回测)
    g.security = '510300.XSHG'
    
    # 5. 唐奇安通道参数设置
    # N日突破买入 (通常为20)
    g.buy_window = 20
    # M日跌破卖出 (通常为10,短于买入窗口以保护利润)
    g.sell_window = 10
    
    # 6. 每天开盘时运行
    run_daily(market_open, time='09:30')

def market_open(context):
    """
    每日交易逻辑
    """
    security = g.security
    
    # 获取股票的当前数据
    current_data = get_current_data()
    
    # 如果停牌,则跳过
    if current_data[security].paused:
        return

    # 获取历史数据
    # 我们需要过去 N 天的数据来计算上轨,过去 M 天的数据计算下轨
    # 注意:attribute_history 获取的是不包含当前时刻的历史数据(昨天及之前)
    # 这样可以避免"未来函数",即用今天的收盘价来决定今天是否开盘买入
    
    # 获取买入窗口的历史最高价数据
    buy_history = attribute_history(security, g.buy_window, '1d', ['high'])
    # 获取卖出窗口的历史最低价数据
    sell_history = attribute_history(security, g.sell_window, '1d', ['low'])
    
    # 计算唐奇安通道上轨(过去N天的最高价)
    donchian_upper = buy_history['high'].max()
    # 计算唐奇安通道下轨(过去M天的最低价)
    donchian_lower = sell_history['low'].min()
    
    # 获取当前最新价格
    current_price = current_data[security].last_price
    
    # 获取当前账户持仓情况
    position = context.portfolio.positions[security]
    
    # --- 交易逻辑 ---
    
    # 1. 买入逻辑:如果当前价格突破上轨,且空仓
    if current_price > donchian_upper and position.closeable_amount == 0:
        # 全仓买入
        order_value(security, context.portfolio.available_cash)
        log.info("价格突破上轨 (%.2f > %.2f),买入 %s" % (current_price, donchian_upper, security))
        
    # 2. 卖出逻辑:如果当前价格跌破下轨,且持有仓位
    elif current_price < donchian_lower and position.closeable_amount > 0:
        # 清仓卖出
        order_target(security, 0)
        log.info("价格跌破下轨 (%.2f < %.2f),卖出 %s" % (current_price, donchian_lower, security))
        
    # 3. 记录通道值以便在回测图表中查看
    record(Upper_Band=donchian_upper, Lower_Band=donchian_lower, Price=current_price)

代码详解

  1. 初始化 (initialize):

    • 设置了 g.buy_window = 20g.sell_window = 10。这是经典的“海龟法则”短周期配置。意味着价格突破过去20天最高价买入,跌破过去10天最低价卖出。
    • 使用了 510300.XSHG (ETF) 作为标的,因为指数本身不能交易,ETF更适合模拟真实交易。
  2. 数据获取 (attribute_history):

    • 使用 attribute_history 获取过去 N 天的数据。在 market_open (09:30) 调用时,它返回的是截止到昨天收盘的数据。这是非常重要的,因为唐奇安通道的突破标准必须基于过去的数据,否则会产生未来函数。
  3. 交易逻辑:

    • 买入: current_price > donchian_upper。当今天的实时价格超过了过去20天的最高价,视为趋势确立,执行买入。
    • 卖出: current_price < donchian_lower。当今天的实时价格低于了过去10天的最低价,视为趋势反转或回调过深,执行止损/止盈。
  4. 可视化 (record):

    • 使用 record 函数将上轨、下轨和当前价格画在回测收益图的下方,方便直观判断策略是否按预期执行。

常见问题 (Q&A)

Q1: 为什么卖出窗口(10天)比买入窗口(20天)短?
A: 这是一个非对称的通道设计。较长的买入窗口是为了过滤掉市场的短期噪音,确认趋势真正形成后再进场;较短的卖出窗口是为了在趋势反转时能够更快地离场,保住利润,即“让利润奔跑,快速截断亏损”。

Q2: 这个策略适合什么类型的市场?
A: 唐奇安通道是典型的趋势跟踪策略。它在单边上涨或下跌的大趋势行情中表现最好。在横盘震荡市中,由于价格频繁上下穿越通道,会导致频繁止损,产生连续的小额亏损。

Q3: 如何扩展到多只股票?
A: 可以将 g.security 修改为一个列表(例如 get_index_stocks('000300.XSHG')),然后在 market_open 中使用 for 循环遍历列表,对每一只股票单独计算通道和信号。同时需要注意资金分配(例如每只股票分配总资金的1/10)。

Q4: 回测时发现买入价格比上轨高很多怎么办?
A: 这是滑点或跳空高开造成的。如果开盘价直接跳空高开突破上轨,策略会以开盘价买入。可以通过 set_slippage 设置滑点模型来模拟真实的交易成本。