问题描述
解决方案
这是一个基于威廉指标(Williams %R)的均值回归交易策略。
策略原理
威廉指标(Williams %R)主要用于判断市场的超买和超卖状态,取值范围为 -100 到 0。
- 计算公式:$WR = \frac{Highest High_n - Close}{Highest High_n - Lowest Low_n} \times -100$
- 超卖区间(-100 到 -80):市场处于超卖状态,股价可能见底反弹,视为买入信号。
- 超买区间(-20 到 0):市场处于超买状态,股价可能见顶回落,视为卖出信号。
策略逻辑
- 买入条件:当威廉指标低于 -80(超卖),且当前无持仓时,全仓买入。
- 卖出条件:当威廉指标高于 -20(超买),且当前有持仓时,清仓卖出。
- 回测标的:以平安银行(000001.XSHE)为例。
- 参数设置: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,默认获取的是截止到昨天收盘的数据。这意味着我们是利用昨天的收盘指标来决定今天开盘的操作,这是一种避免“未来函数”的标准做法。