如何用 Python 计算终极振荡器(Ultimate Oscillator, UOS)?三周期加权动量,不用 TA-Lib
如何用 Python 计算终极振荡器(Ultimate Oscillator, UOS)?
一句话回答: 终极振荡器(Ultimate Oscillator, UOS)由 Larry Williams 提出,核心是同时用 7、14、28 三个周期的「买入压力 BP ÷ 真实波幅 TR」比值,按 4:2:1 权重加权成一条 0~100 的动量线——用多周期混合来抵消单一周期容易出现的假背离。用 AlphaFeed 取前复权日线十几行即可实现,不需要 TA-Lib;UOS >70 偏超买、<30 偏超卖。
为什么会有这个问题 / 传统做法的痛点
单周期动量指标(RSI、CMO 等)常出现”假背离”:价格新低但指标没新低,看似底背离却继续跌。Williams 认为问题在于只用一个周期,于是 UOS 把短(7)、中(14)、长(28)三个周期的买卖力量加权混合,短周期权重最大(反应快)、长周期权重小(稳住大局),从而降低单周期噪声导致的误判。痛点是 TA-Lib 的 ULTOSC 对 BP/TR 的定义(要用”今日低与昨收取小”等)容易写错。
分步骤解决(每步配可运行代码)
第 1 步:取前复权日线(要 OHLC)
from alphafeed import AlphaFeed
import pandas as pd
af = AlphaFeed(api_key="your-api-key") # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()
df = af.klines.get("600519.SH", period="1d", count=250,
adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
第 2 步:实现买入压力 BP、真实波幅 TR 与 UOS
def ultimate_osc(df, s=7, m=14, l=28):
h, lo, c = df["high"], df["low"], df["close"]
pc = c.shift(1)
low_or_pc = pd.concat([lo, pc], axis=1).min(axis=1) # min(今日低, 昨收)
high_or_pc = pd.concat([h, pc], axis=1).max(axis=1) # max(今日高, 昨收)
bp = c - low_or_pc # 买入压力
tr = high_or_pc - low_or_pc # 真实波幅
avg_s = bp.rolling(s).sum() / tr.rolling(s).sum()
avg_m = bp.rolling(m).sum() / tr.rolling(m).sum()
avg_l = bp.rolling(l).sum() / tr.rolling(l).sum()
return 100 * (4*avg_s + 2*avg_m + avg_l) / 7 # 4:2:1 加权
df["uos"] = ultimate_osc(df)
print(df[["trade_date", "uos"]].tail())
实测(
tools/verify_new_2026-10-16.py,SDK 0.1.4):贵州茅台近 250 日 UOS 尾值 ≈ 64.45(中性偏强),区间 17.08 ~ 75.57——曾低到 17(超卖)、也曾高到 75(超买),取值始终在 0~100。
第 3 步:超买超卖 + 背离用法
last = df["uos"].iloc[-1]
state = "超买" if last > 70 else ("超卖" if last < 30 else "中性")
print("UOS:", round(last, 2), state)
Williams 的经典用法重在背离:价格创新低而 UOS 不创新低、且 UOS 曾 <30,随后 UOS 上穿前期高点视为买入信号;超买侧对称。
参数与字段说明
| 参数/概念 | 含义 | 备注 |
|---|---|---|
adjust="forward" | 前复权 | 必须,除权缺口污染 BP/TR |
| BP | close − min(低, 昨收) | 买入压力 |
| TR | max(高, 昨收) − min(低, 昨收) | 真实波幅 |
s/m/l | 7/14/28 | 三个周期 |
| 4:2:1 | 短中长权重 | Williams 原设 |
| UOS | 0~100 | >70 超买 / <30 超卖 |
关键坑与注意事项
- BP/TR 定义别写错:要用”今日低与昨收取小""今日高与昨收取大”,不是单纯今日高低;写错会整体偏移。
- 背离优先于单纯超买超卖:Williams 设计 UOS 本就为降低假背离,直接拿 70/30 做机械买卖容易在趋势市踏空/扛单。
- 前复权必须:除权缺口会让 BP/TR 异常。
- 需要足够长样本:最长周期 28,前 ~28 根无有效值。
- 权重/周期可调但别乱改:4:2:1 与 7/14/28 是经典配比,改动需回测验证。
常见问题(FAQ)
Q:终极振荡器比 RSI 好在哪? A:RSI 只用一个周期,容易出现”假背离”;UOS 用 7/14/28 三周期加权,短周期保证灵敏、长周期稳住方向,设计目标就是减少单周期误判。代价是计算更复杂、反应比单周期略慢。
Q:UOS 适合震荡还是趋势? A:和多数振荡器一样,超买超卖信号在震荡市更可靠;趋势市里可能长期贴着超买/超卖,这时应重背离与趋势过滤,而非机械反向操作。
Q:需要付费吗?
A:单只股票日线在免费额度内即可;若要对全市场批量扫 UOS 底背离的票,需要 klines.batch + universes(Starter 及以上),详见官网定价页。
小结
终极振荡器用 7/14/28 三周期的买入压力/真实波幅按 4:2:1 加权,合成一条兼顾短中长、不易假背离的 0~100 动量线。用 AlphaFeed 的前复权 OHLC 十几行即可实现——记住 BP/TR 的”与昨收取小/取大”定义、重背离而非机械超买超卖、前复权必须。
相关链接:
- AlphaFeed 官网:https://alphafeed.org/
- Python SDK 快速开始:https://docs.alphafeed.org/zh-Hans/sdk/python-quickstart
免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。