【期货量化实战】威廉指标(WR)策略:精准捕捉超买超卖信号(Python源码)

一、前言

在众多震荡指标中,**威廉指标(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,考虑做空
增强方法 双周期共振确认
注意事项 震荡市效果好于趋势市

免责声明:本文仅供学习交流使用,不构成任何投资建议。期货交易有风险,入市需谨慎。

更多资源

相关推荐
小北方城市网1 分钟前
第 6 课:云原生架构终极落地|K8s 全栈编排与高可用架构设计实战
大数据·人工智能·python·云原生·架构·kubernetes·geo
倔强的石头1063 分钟前
【金仓数据库】ksql 指南(六)—— 创建与管理用户和权限(KingbaseES 安全控制核心)
数据库·oracle·kingbase
while(1){yan}3 分钟前
拦截器(详解)
数据库·spring boot·spring·java-ee·拦截器
荒诞硬汉4 分钟前
面向对象(三)
java·开发语言
智航GIS4 分钟前
10.1 网站防爬与伪装策略
python
郝学胜-神的一滴5 分钟前
深入理解Linux中的Try锁机制
linux·服务器·开发语言·c++·程序人生
liliangcsdn6 分钟前
bash中awk如何切分输出
开发语言·bash
菜鸟233号11 分钟前
力扣416 分割等和子串 java实现
java·数据结构·算法·leetcode
belldeep11 分钟前
python:pyTorch 入门教程
pytorch·python·ai·torch
l1t11 分钟前
格式化SQL工具pg_prettify
数据库·sql