问题描述
解决方案
编写 UOS(Ultimate Oscillator,终极波动指标)交易策略的核心在于利用该指标综合短、中、长三个周期的特性,来捕捉市场的超买和超卖区域。
策略逻辑说明
UOS 指标由拉里·威廉姆斯(Larry Williams)开发,旨在解决单一周期震荡指标容易产生虚假信号的问题。
1. UOS 计算原理(本策略使用 TA-Lib 库计算):
- 通常使用三个周期:7日、14日、28日。
- 通过计算购买压力(Buying Pressure)与真实波幅(True Range)的比率,并加权平均得出。
- 数值范围在 0 到 100 之间,50 为中轴。
2. 交易信号设计:
本策略采用经典的超买超卖反转逻辑:
- 买入信号(做多): 当 UOS 指标低于 35(视为超卖区域)时,认为股价可能反弹,全仓买入。
- 卖出信号(平仓): 当 UOS 指标高于 65(视为超买区域)时,认为股价可能回调,清仓卖出。
3. 资金管理:
- 全仓买入,清仓卖出(仅作为示例,实盘建议配合风控模型)。
策略代码实现
以下是基于聚宽(JoinQuant)平台的完整策略代码。代码中使用了 talib 库来高效计算 UOS 指标。
# -*- coding: utf-8 -*-
import jqdata
import talib
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')
# 设定股票类每笔交易时的手续费
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'
# UOS指标的三个周期参数
g.p1 = 7
g.p2 = 14
g.p3 = 28
# 设定超买超卖阈值
g.buy_threshold = 35 # 低于此值视为超卖,买入
g.sell_threshold = 65 # 高于此值视为超买,卖出
# 每天开盘时运行
run_daily(market_open, time='09:30')
def market_open(context):
"""
每日交易逻辑
"""
security = g.security
# 获取计算UOS所需的历史数据
# UOS最大周期是28,我们需要比28更多的数据来确保计算稳定,这里取60天
# 包含 high, low, close
history_data = attribute_history(security, 60, '1d', ['high', 'low', 'close'])
# 确保数据长度足够
if len(history_data) < g.p3 + 1:
return
# 将数据转换为numpy数组,供talib使用
high_prices = history_data['high'].values
low_prices = history_data['low'].values
close_prices = history_data['close'].values
# 使用 talib 计算 UOS 指标
# 注意:talib.ULTOSC 返回的是一个数组,对应每一天的UOS值
uos_values = talib.ULTOSC(high_prices, low_prices, close_prices,
timeperiod1=g.p1,
timeperiod2=g.p2,
timeperiod3=g.p3)
# 获取最新的 UOS 值(数组的最后一个元素)
current_uos = uos_values[-1]
# 检查是否计算出有效值(剔除NaN)
if np.isnan(current_uos):
return
# 获取当前账户资金和持仓情况
cash = context.portfolio.available_cash
position = context.portfolio.positions[security]
# 记录 UOS 值到图表,方便回测查看
record(UOS=current_uos)
# --- 交易逻辑 ---
# 1. 买入逻辑:UOS 小于买入阈值 (超卖),且当前无持仓
if current_uos < g.buy_threshold and position.closeable_amount == 0:
# 全仓买入
order_value(security, cash)
log.info("买入信号触发:UOS值为 %.2f,低于阈值 %d,全仓买入 %s" % (current_uos, g.buy_threshold, security))
# 2. 卖出逻辑:UOS 大于卖出阈值 (超买),且有持仓
elif current_uos > g.sell_threshold and position.closeable_amount > 0:
# 清仓卖出
order_target(security, 0)
log.info("卖出信号触发:UOS值为 %.2f,高于阈值 %d,清仓卖出 %s" % (current_uos, g.sell_threshold, security))
def after_trading_end(context):
"""
盘后处理(可选)
"""
pass
常见问题 (Q&A)
Q1: 为什么使用 talib.ULTOSC 而不是自己写公式计算?
A: talib 是底层的 C 语言库,计算速度极快且经过了广泛验证,准确性高。自己编写公式容易在处理 NaN 值或边界条件(如除数为0)时出错。在量化交易中,推荐优先使用成熟的库。
Q2: 阈值 35 和 65 是固定的吗?
A: 不是。拉里·威廉姆斯最初建议的买入标准是 UOS < 30,卖出标准是 UOS > 70。但在 A 股市场或特定个股上,波动特性可能不同。您可以根据回测结果调整 g.buy_threshold 和 g.sell_threshold(例如调整为 30/70 或 40/60)以获得更优的收益。
Q3: 这个策略适合什么类型的行情?
A: UOS 是震荡指标,因此该策略最适合震荡市(股价在箱体上下波动)。在单边的大牛市或大熊市中,震荡指标可能会出现“钝化”现象(例如牛市中 UOS 长期高于 65,导致过早卖出踏空;熊市中长期低于 35,导致过早抄底被套)。建议结合均线(MA)等趋势指标进行过滤。
Q4: 如何对多只股票运行此策略?
A: 您可以将 g.security 修改为一个列表(例如 get_index_stocks('000300.XSHG')),然后在 market_open 函数中使用 for 循环遍历每只股票,分别计算 UOS 并独立进行买卖判断。同时需要调整下单资金分配逻辑(例如每只股票分配总资金的 1/N)。