一、前言
在众多震荡指标中,**威廉指标(Williams %R)**以其敏感度高、信号明确而著称。它能比RSI更快地捕捉到市场的超买超卖状态,是短线交易者的利器。
本文将介绍:
- 威廉指标的计算原理
- WR与RSI的区别
- 超买超卖交易策略
- 完整策略代码与回测
二、为什么选择天勤量化(TqSdk)
计算技术指标需要可靠的K线数据源。**天勤量化(TqSdk)**不仅提供高质量的行情数据,还内置了常用技术指标:
| 优势 | 说明 |
|---|---|
| 数据质量高 | K线数据完整准确 |
| 内置指标库 | tqsdk.tafunc提供MA、MACD等 |
| pandas友好 | 数据直接返回DataFrame |
| 实时更新 | 数据自动推送 |
安装方法:
bash
pip install tqsdk
重要提示:建议先使用模拟盘充分测试策略,确认无误后再考虑实盘交易。
三、威廉指标详解
3.1 计算公式
WR = (N周期最高价 - 当前收盘价) / (N周期最高价 - N周期最低价) × (-100)
| 参数 | 说明 |
|---|---|
| N | 通常取14,短线可用10 |
| WR范围 | -100 到 0 |
3.2 WR与RSI对比
| 对比项 | WR | RSI |
|---|---|---|
| 范围 | -100 ~ 0 | 0 ~ 100 |
| 超买区 | 0 ~ -20 | 70 ~ 100 |
| 超卖区 | -80 ~ -100 | 0 ~ 30 |
| 灵敏度 | 更高 | 较平滑 |
| 适用场景 | 短线交易 | 中短线 |
3.3 交易信号
| 信号 | 条件 | 操作 |
|---|---|---|
| 做多 | WR从超卖区上穿-80 | 超跌反弹 |
| 做空 | WR从超买区下穿-20 | 见顶回落 |
| 平多 | WR进入超买区 | 止盈离场 |
| 平空 | WR进入超卖区 | 止盈离场 |
四、基础版WR策略
4.1 完整代码
python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:威廉指标(WR)超买超卖策略
说明:本代码仅供学习参考
"""
from tqsdk import TqApi, TqAuth, TqSim
from tqsdk.lib import TargetPosTask
# ============ 策略参数 ============
SYMBOL = "SHFE.rb2510" # 交易合约
KLINE_PERIOD = 300 # K线周期(秒),300=5分钟
WR_PERIOD = 14 # WR周期
OVERBOUGHT = -20 # 超买阈值
OVERSOLD = -80 # 超卖阈值
VOLUME = 1 # 每次交易手数
# ============ 初始化 ============
api = TqApi(TqSim(), auth=TqAuth("快期账户", "快期密码"))
klines = api.get_kline_serial(SYMBOL, KLINE_PERIOD, WR_PERIOD + 30)
target_pos = TargetPosTask(api, SYMBOL)
position = api.get_position(SYMBOL)
print(f"威廉指标策略启动")
print(f"交易合约: {SYMBOL}")
print(f"WR周期: {WR_PERIOD}, 超买: {OVERBOUGHT}, 超卖: {OVERSOLD}")
print("-" * 50)
def calc_wr(df, period):
"""计算威廉指标"""
high = df["high"]
low = df["low"]
close = df["close"]
highest = high.rolling(window=period).max()
lowest = low.rolling(window=period).min()
wr = (highest - close) / (highest - lowest) * (-100)
return wr
prev_wr = None
while True:
api.wait_update()
if api.is_changing(klines.iloc[-1], "datetime"):
current_price = klines["close"].iloc[-1]
# 计算WR
wr = calc_wr(klines, WR_PERIOD)
current_wr = wr.iloc[-1]
current_pos = position.pos_long - position.pos_short
# 状态显示
if current_wr > OVERBOUGHT:
status = "🔴超买"
elif current_wr < OVERSOLD:
status = "🟢超卖"
else:
status = "⚪中性"
print(f"{status} | WR={current_wr:.1f} | 价格={current_price:.0f}")
if prev_wr is not None:
# 无持仓
if current_pos == 0:
# 做多信号:WR上穿超卖线
if current_wr > OVERSOLD and prev_wr <= OVERSOLD:
print(f" ★ WR上穿{OVERSOLD},超卖反弹,开多")
target_pos.set_target_volume(VOLUME)
# 做空信号:WR下穿超买线
elif current_wr < OVERBOUGHT and prev_wr >= OVERBOUGHT:
print(f" ★ WR下穿{OVERBOUGHT},超买回落,开空")
target_pos.set_target_volume(-VOLUME)
# 持有多单:WR进入超买区则平仓
elif current_pos > 0:
if current_wr > OVERBOUGHT:
print(f" ✖ WR进入超买区,多单止盈")
target_pos.set_target_volume(0)
# 持有空单:WR进入超卖区则平仓
elif current_pos < 0:
if current_wr < OVERSOLD:
print(f" ✖ WR进入超卖区,空单止盈")
target_pos.set_target_volume(0)
prev_wr = current_wr
4.2 代码解析
| 代码 | 说明 |
|---|---|
high.rolling(window=period).max() |
计算N周期最高价 |
(highest - close) / (highest - lowest) |
WR核心公式 |
* (-100) |
转换为-100~0范围 |
4.3 运行效果
威廉指标策略启动
交易合约: SHFE.rb2510
WR周期: 14, 超买: -20, 超卖: -80
--------------------------------------------------
⚪中性 | WR=-52.3 | 价格=3280
⚪中性 | WR=-65.8 | 价格=3268
🟢超卖 | WR=-88.5 | 价格=3255
⚪中性 | WR=-72.1 | 价格=3262
★ WR上穿-80,超卖反弹,开多
...
五、增强版(双周期WR策略)
5.1 策略思路
使用两个不同周期的WR指标,增强信号可靠性:
| 指标 | 周期 | 作用 |
|---|---|---|
| 短周期WR | 6 | 提供交易信号 |
| 长周期WR | 14 | 确认趋势方向 |
5.2 完整代码
python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:双周期威廉指标策略
说明:本代码仅供学习参考
"""
from tqsdk import TqApi, TqAuth, TqSim
from tqsdk.lib import TargetPosTask
import datetime
# ============ 策略参数 ============
SYMBOL = "SHFE.rb2510"
KLINE_PERIOD = 300
WR_SHORT = 6 # 短周期
WR_LONG = 14 # 长周期
OVERBOUGHT = -20
OVERSOLD = -80
VOLUME = 1
# ============ 初始化 ============
api = TqApi(TqSim(), auth=TqAuth("快期账户", "快期密码"))
klines = api.get_kline_serial(SYMBOL, KLINE_PERIOD, max(WR_SHORT, WR_LONG) + 30)
target_pos = TargetPosTask(api, SYMBOL)
position = api.get_position(SYMBOL)
print("=" * 60)
print("双周期威廉指标策略")
print("=" * 60)
print(f"交易合约: {SYMBOL}")
print(f"短周期WR: {WR_SHORT}, 长周期WR: {WR_LONG}")
print("-" * 60)
def calc_wr(df, period):
"""计算威廉指标"""
high = df["high"]
low = df["low"]
close = df["close"]
highest = high.rolling(window=period).max()
lowest = low.rolling(window=period).min()
wr = (highest - close) / (highest - lowest) * (-100)
return wr
prev_wr_short = None
prev_wr_long = None
while True:
api.wait_update()
if api.is_changing(klines.iloc[-1], "datetime"):
current_price = klines["close"].iloc[-1]
# 计算双周期WR
wr_short = calc_wr(klines, WR_SHORT)
wr_long = calc_wr(klines, WR_LONG)
curr_wr_short = wr_short.iloc[-1]
curr_wr_long = wr_long.iloc[-1]
current_pos = position.pos_long - position.pos_short
now = datetime.datetime.now().strftime("%H:%M:%S")
if prev_wr_short is not None and prev_wr_long is not None:
# 无持仓
if current_pos == 0:
# 双周期共振做多:短周期上穿-80,且长周期在超卖区
if (curr_wr_short > OVERSOLD and prev_wr_short <= OVERSOLD and
curr_wr_long < -50):
print(f"[{now}] 短WR={curr_wr_short:.1f} 长WR={curr_wr_long:.1f}")
print(f" ★ 双周期共振,开多")
target_pos.set_target_volume(VOLUME)
# 双周期共振做空:短周期下穿-20,且长周期在超买区
elif (curr_wr_short < OVERBOUGHT and prev_wr_short >= OVERBOUGHT and
curr_wr_long > -50):
print(f"[{now}] 短WR={curr_wr_short:.1f} 长WR={curr_wr_long:.1f}")
print(f" ★ 双周期共振,开空")
target_pos.set_target_volume(-VOLUME)
# 持有多单
elif current_pos > 0:
if curr_wr_short > OVERBOUGHT and curr_wr_long > OVERBOUGHT:
print(f"[{now}] ✖ 双周期超买,平多")
target_pos.set_target_volume(0)
# 持有空单
elif current_pos < 0:
if curr_wr_short < OVERSOLD and curr_wr_long < OVERSOLD:
print(f"[{now}] ✖ 双周期超卖,平空")
target_pos.set_target_volume(0)
prev_wr_short = curr_wr_short
prev_wr_long = curr_wr_long
六、策略回测
python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
功能:威廉指标策略回测
说明:本代码仅供学习参考
"""
from tqsdk import TqApi, TqAuth, TqSim, TqBacktest, BacktestFinished
from tqsdk.lib import TargetPosTask
from datetime import date
SYMBOL = "SHFE.rb2501"
START_DATE = date(2024, 1, 1)
END_DATE = date(2024, 6, 30)
WR_PERIOD = 14
OVERBOUGHT = -20
OVERSOLD = -80
VOLUME = 1
acc = TqSim(init_balance=100000)
backtest = TqBacktest(start_dt=START_DATE, end_dt=END_DATE)
def calc_wr(df, period):
high = df["high"]
low = df["low"]
close = df["close"]
highest = high.rolling(window=period).max()
lowest = low.rolling(window=period).min()
return (highest - close) / (highest - lowest) * (-100)
try:
api = TqApi(acc, backtest=backtest, auth=TqAuth("快期账户", "快期密码"))
klines = api.get_kline_serial(SYMBOL, 300, WR_PERIOD + 30)
target_pos = TargetPosTask(api, SYMBOL)
position = api.get_position(SYMBOL)
prev_wr = None
trade_count = 0
while True:
api.wait_update()
if api.is_changing(klines.iloc[-1], "datetime"):
wr = calc_wr(klines, WR_PERIOD)
current_wr = wr.iloc[-1]
current_pos = position.pos_long - position.pos_short
if prev_wr is not None:
if current_pos == 0:
if current_wr > OVERSOLD and prev_wr <= OVERSOLD:
target_pos.set_target_volume(VOLUME)
trade_count += 1
elif current_wr < OVERBOUGHT and prev_wr >= OVERBOUGHT:
target_pos.set_target_volume(-VOLUME)
trade_count += 1
elif current_pos > 0 and current_wr > OVERBOUGHT:
target_pos.set_target_volume(0)
elif current_pos < 0 and current_wr < OVERSOLD:
target_pos.set_target_volume(0)
prev_wr = current_wr
except BacktestFinished:
print("=" * 60)
print("威廉指标策略回测结果")
print("=" * 60)
stat = acc.tqsdk_stat
print(f"回测区间: {START_DATE} ~ {END_DATE}")
print(f"WR参数: 周期{WR_PERIOD}, 超买{OVERBOUGHT}, 超卖{OVERSOLD}")
print("-" * 60)
print(f"交易次数: {trade_count}")
print(f"收益率: {stat['ror']*100:.2f}%")
print(f"最大回撤: {stat['max_drawdown']*100:.2f}%")
print(f"夏普比率: {stat['sharpe_ratio']:.2f}")
print(f"胜率: {stat['winning_rate']*100:.2f}%")
print("=" * 60)
api.close()
七、参数优化建议
| 市场类型 | WR周期 | 超买/超卖 | 说明 |
|---|---|---|---|
| 震荡市 | 10-14 | -20/-80 | 标准参数 |
| 趋势市 | 14-21 | -10/-90 | 更极端才反转 |
| 日内短线 | 6-10 | -20/-80 | 快速反应 |
八、总结
| 要点 | 内容 |
|---|---|
| WR特点 | 比RSI更灵敏,适合短线 |
| 超卖信号 | WR上穿-80,考虑做多 |
| 超买信号 | WR下穿-20,考虑做空 |
| 增强方法 | 双周期共振确认 |
| 注意事项 | 震荡市效果好于趋势市 |
免责声明:本文仅供学习交流使用,不构成任何投资建议。期货交易有风险,入市需谨慎。
更多资源: