🚀 AI 一键生成 joinquant 策略代码

JoinQuant 指南:如何实现威廉指标(Williams %R)的超买超卖策略?

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

问题描述

请编写一个基于威廉指标(%R)的交易策略

解决方案

这是一个基于威廉指标(Williams %R)的均值回归交易策略。

策略原理

威廉指标(Williams %R)主要用于判断市场的超买和超卖状态,取值范围为 -100 到 0。

  • 计算公式:$WR = \frac{Highest High_n - Close}{Highest High_n - Lowest Low_n} \times -100$
  • 超卖区间(-100 到 -80):市场处于超卖状态,股价可能见底反弹,视为买入信号。
  • 超买区间(-20 到 0):市场处于超买状态,股价可能见顶回落,视为卖出信号。

策略逻辑

  1. 买入条件:当威廉指标低于 -80(超卖),且当前无持仓时,全仓买入。
  2. 卖出条件:当威廉指标高于 -20(超买),且当前有持仓时,清仓卖出。
  3. 回测标的:以平安银行(000001.XSHE)为例。
  4. 参数设置:N = 14(周期)。

策略代码

# -*- coding: utf-8 -*-
# 导入聚宽函数库
import jqdata
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')
    
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # --- 策略参数设置 ---
    # 操作标的:平安银行
    g.security = '000001.XSHE'
    # 威廉指标计算周期 (通常为14或28)
    g.N = 14
    # 超卖阈值 (买入线)
    g.buy_threshold = -80
    # 超买阈值 (卖出线)
    g.sell_threshold = -20
    
    # 每天开盘时运行
    run_daily(market_open, time='09:30')

def market_open(context):
    """
    每日交易逻辑
    """
    security = g.security
    
    # 获取过去 g.N 天的最高价、最低价、收盘价
    # 注意:在09:30运行且不包含当天数据时,获取的是昨天及之前的数据
    h_data = attribute_history(security, g.N, '1d', ['high', 'low', 'close'])
    
    # 如果数据长度不足(例如刚上市),则跳过
    if len(h_data) < g.N:
        return

    # 计算周期内的最高价和最低价
    highest_high = h_data['high'].max()
    lowest_low = h_data['low'].min()
    # 获取最近一个交易日的收盘价
    current_close = h_data['close'][-1]
    
    # 防止分母为0(最高价等于最低价的情况)
    if highest_high == lowest_low:
        wr = -50 # 赋予一个中间值,不操作
    else:
        # 计算威廉指标公式: (Hn - C) / (Hn - Ln) * -100
        wr = (highest_high - current_close) / (highest_high - lowest_low) * -100
    
    # 打印日志方便调试
    # log.info("日期: %s, WR指标: %.2f" % (context.current_dt.date(), wr))
    
    # 获取当前现金和持仓
    cash = context.portfolio.available_cash
    position = context.portfolio.positions[security].closeable_amount
    
    # --- 交易信号判断 ---
    
    # 1. 买入逻辑:WR < -80 (超卖) 且 空仓
    if wr < g.buy_threshold and position == 0:
        # 全仓买入
        order_value(security, cash)
        log.info("威廉指标超卖 (WR=%.2f),买入 %s" % (wr, security))
        
    # 2. 卖出逻辑:WR > -20 (超买) 且 持仓
    elif wr > g.sell_threshold and position > 0:
        # 清仓卖出
        order_target(security, 0)
        log.info("威廉指标超买 (WR=%.2f),卖出 %s" % (wr, security))

常见问题 Q&A

Q1: 为什么选择 -80 和 -20 作为阈值?
A: 这是威廉指标的经典参数。-80 到 -100 区间通常表示市场情绪过度悲观(超卖),价格可能反弹;-20 到 0 区间表示市场情绪过度乐观(超买),价格可能回调。您可以根据回测结果调整这些阈值(例如调整为 -90 和 -10)。

Q2: 这个策略适合什么类型的行情?
A: 威廉指标属于震荡型指标,因此该策略在震荡市中表现较好,能够捕捉高抛低吸的机会。但在单边的大牛市或大熊市中,指标可能会出现“钝化”(长期停留在超买或超卖区),导致过早卖出或过早抄底。

Q3: 如何避免“指标钝化”带来的亏损?
A: 可以结合趋势指标(如均线 MA)进行过滤。例如:只有当股价在20日均线之上时,才允许执行威廉指标的买入信号,这样可以顺势而为。

Q4: 代码中的 attribute_history 获取的是什么时间的数据?
A:run_daily(func, time='09:30') 中调用 attribute_history,默认获取的是截止到昨天收盘的数据。这意味着我们是利用昨天的收盘指标来决定今天开盘的操作,这是一种避免“未来函数”的标准做法。