🚀 AI 一键生成 qmt 策略代码

如何使用威廉指标 (Williams %R) 捕捉超买超卖信号?(附 Python 源码)

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

问题描述

请帮我写一个威廉指标(%R)的交易策略,当指标低于-80时买入,高于-20时卖出。

解决方案

这是一个基于威廉指标(Williams %R)的 QMT 量化交易策略。

策略逻辑

  1. 指标定义:威廉指标(%R)用于判断市场的超买超卖状态,取值范围为 -100 到 0。
  2. 买入条件:当 %R 低于 -80 时,视为超卖状态,看涨,执行买入。
  3. 卖出条件:当 %R 高于 -20 时,视为超买状态,看跌,执行卖出(清仓)。
  4. 资金管理:买入时满仓(目标仓位 100%),卖出时空仓(目标仓位 0%)。

策略代码

# -*- coding: gbk -*-
import pandas as pd
import numpy as np
import talib

def init(ContextInfo):
    """
    初始化函数,策略启动时执行一次
    """
    # 1. 设置策略参数
    ContextInfo.N = 14              # 威廉指标周期,通常为14
    ContextInfo.buy_threshold = -80 # 买入阈值
    ContextInfo.sell_threshold = -20 # 卖出阈值
    
    # 2. 设置股票池(示例使用浦发银行,实盘请在界面设置或此处修改)
    ContextInfo.stock_code = '600000.SH' 
    ContextInfo.set_universe([ContextInfo.stock_code])
    
    # 3. 设置资金账号 (请替换为您真实的资金账号)
    ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 
    ContextInfo.account_type = 'STOCK' # 账号类型:STOCK股票,FUTURE期货
    ContextInfo.set_account(ContextInfo.account_id)

    print("策略初始化完成,监控标的: {}, 周期: {}".format(ContextInfo.stock_code, ContextInfo.N))

def handlebar(ContextInfo):
    """
    K线处理函数,每根K线执行一次
    """
    # 获取当前正在处理的K线对应的股票代码
    # 如果是回测模式,ContextInfo.stockcode 会自动随主图变化
    # 如果是实盘,建议明确指定代码
    stock_code = ContextInfo.stock_code
    
    # 1. 获取历史行情数据
    # 我们需要 High, Low, Close 价格来计算威廉指标
    # 获取数量 count 需要比 N 大,以确保有足够数据计算指标
    count = ContextInfo.N + 5 
    
    # 使用 get_market_data_ex 获取数据 (推荐使用 ex 接口)
    # period='1d' 表示日线,也可以改成 '1m', '5m' 等
    data_map = ContextInfo.get_market_data_ex(
        ['high', 'low', 'close'], 
        [stock_code], 
        period='1d', 
        count=count, 
        dividend_type='front' # 前复权
    )
    
    # 数据校验:如果没取到数据,直接返回
    if stock_code not in data_map or data_map[stock_code].empty:
        return

    df = data_map[stock_code]
    
    # 确保数据长度足够
    if len(df) < ContextInfo.N:
        return

    # 2. 计算威廉指标 (Williams %R)
    # 转换数据为 numpy 数组,talib 需要 float 类型
    high_prices = df['high'].values.astype(float)
    low_prices = df['low'].values.astype(float)
    close_prices = df['close'].values.astype(float)
    
    # 调用 talib 库计算 WILLR
    # 公式: %R = (Highest High - Close) / (Highest High - Lowest Low) * -100
    wr_values = talib.WILLR(high_prices, low_prices, close_prices, timeperiod=ContextInfo.N)
    
    # 获取最新的 WR 值 (数组最后一个)
    current_wr = wr_values[-1]
    
    # 打印当前指标值 (方便调试)
    # print(f"时间: {df.index[-1]}, WR: {current_wr:.2f}")

    # 3. 交易逻辑判断
    # 获取当前持仓
    positions = ContextInfo.get_trade_detail_data(ContextInfo.account_id, ContextInfo.account_type, 'POSITION')
    current_holding = 0
    for pos in positions:
        if pos.m_strInstrumentID + '.' + pos.m_strExchangeID == stock_code:
            current_holding = pos.m_nVolume
            break

    # 信号判断
    # 只有在 K 线走完或者是最新一根 K 线时才进行交易判断
    if not np.isnan(current_wr):
        
        # --- 买入信号:WR < -80 (超卖) ---
        if current_wr < ContextInfo.buy_threshold:
            # 如果当前没有持仓,则买入
            # 这里使用 order_target_percent 调整仓位到 100% (即满仓买入)
            # 注意:实盘中请根据风控需求调整比例,例如 0.1 (10%)
            if current_holding == 0:
                print(f"触发买入信号: WR={current_wr:.2f} < {ContextInfo.buy_threshold}")
                order_target_percent(stock_code, 1.0, ContextInfo, ContextInfo.account_id)

        # --- 卖出信号:WR > -20 (超买) ---
        elif current_wr > ContextInfo.sell_threshold:
            # 如果有持仓,则卖出
            # 调整仓位到 0% (即清仓)
            if current_holding > 0:
                print(f"触发卖出信号: WR={current_wr:.2f} > {ContextInfo.sell_threshold}")
                order_target_percent(stock_code, 0.0, ContextInfo, ContextInfo.account_id)

代码关键点说明

  1. # -*- coding: gbk -*-:

    • QMT 的 Python 编辑器默认使用 GBK 编码,这行代码必须放在第一行,否则中文注释会导致报错。
  2. 数据获取 (get_market_data_ex):

    • 我们使用了 get_market_data_ex 接口,这是 QMT 推荐的新版数据接口。
    • dividend_type='front' 设置为前复权,这对于技术指标计算非常重要,可以避免分红派息导致的价格跳空影响指标准确性。
  3. 指标计算 (talib.WILLR):

    • QMT 内置了 talib 库,直接调用 WILLR 函数计算威廉指标,效率最高且准确。
    • 输入数据必须转换为 float 类型的 numpy 数组。
  4. 交易函数 (order_target_percent):

    • order_target_percent(stock_code, target_percent, ...) 是一个非常方便的函数。
    • 设置为 1.0 代表买入直到该股票占账户总资产的 100%(满仓)。
    • 设置为 0.0 代表卖出直到持仓为 0(清仓)。
    • 注意:在实盘中,建议将 1.0 改为较小的比例(如 0.10.2)以控制风险。
  5. 账号设置:

    • 代码中的 ContextInfo.account_id = 'YOUR_ACCOUNT_ID' 需要替换为您实际的资金账号,否则无法下单。

Q&A

Q: 为什么威廉指标是负数?
A: 威廉指标的公式设计决定了其值域为 0 到 -100。0 代表收盘价处于过去 N 天的最高价(超买),-100 代表收盘价处于过去 N 天的最低价(超卖)。

Q: 如何在回测中查看效果?
A: 在 QMT 界面点击“模型回测”,设置好回测区间、基准和费率,然后点击“开始回测”。代码中的 print 语句会在日志中输出买卖信号。

Q: 这个策略可以直接实盘吗?
A: 代码逻辑是完整的,但实盘前请务必:

  1. 填写真实的资金账号。
  2. 确保 QMT 客户端已登录交易账号。
  3. order_target_percent 的比例调整为合理的仓位控制(不要直接满仓)。
  4. 在“模型交易”界面将策略运行模式设置为“实盘”。