3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
溃疡指数(Ulcer Index,简称 UI)是由 Peter Martin 在 1987 年提出的一种技术指标,用于衡量投资组合或资产的下行风险(即回撤的深度和持续时间)。与标准差不同,溃疡指数只关注价格下跌带来的波动,而不考虑价格上涨的波动,因此更能反映投资者在持仓亏损期间的心理压力。
计算溃疡指数通常基于一个特定的回顾周期(例如 14 天),步骤如下:
公式表示为:
$$UI = \sqrt{\frac{\sum_{i=1}^{N} R_i^2}{N}}$$
以下是在聚宽(JoinQuant)研究环境中计算溃疡指数的 Python 代码示例。该代码使用了 pandas 库来处理滚动窗口计算。
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
from jqdata import *
def calculate_ulcer_index(security, end_date, window=14):
"""
计算指定标的的溃疡指数 (Ulcer Index)
参数:
security: 标的代码,例如 '000300.XSHG'
end_date: 结束日期
window: 回顾周期,默认为14天
返回:
float: 溃疡指数值
"""
# 1. 获取历史收盘价数据
# 为了计算滚动窗口,我们需要获取比 window 稍多一点的数据,或者只获取 window 长度的数据计算单个值
# 这里演示获取一段历史数据并计算序列
df = get_price(security, end_date=end_date, count=window*2, fields=['close'])
if df.empty:
return None
# 2. 计算滚动最高价 (Rolling Max)
# min_periods=1 确保数据不足 window 时也能计算
df['rolling_max'] = df['close'].rolling(window=window, min_periods=1).max()
# 3. 计算回撤百分比 (Percentage Drawdown)
# 公式: (收盘价 - 最高价) / 最高价 * 100
df['drawdown_pct'] = (df['close'] - df['rolling_max']) / df['rolling_max'] * 100
# 4. 计算回撤的平方 (Squared Drawdown)
df['sq_drawdown'] = df['drawdown_pct'] ** 2
# 5. 计算平方的移动平均值 (Mean of Squared Drawdowns)
df['mean_sq_drawdown'] = df['sq_drawdown'].rolling(window=window, min_periods=1).mean()
# 6. 开平方根得到溃疡指数 (Square Root)
df['ulcer_index'] = np.sqrt(df['mean_sq_drawdown'])
# 返回最近一天的溃疡指数
current_ui = df['ulcer_index'].iloc[-1]
return current_ui
# --- 示例调用 ---
# 在研究环境中运行
security = '000300.XSHG' # 沪深300
date = '2023-01-01'
ui_value = calculate_ulcer_index(security, date, window=14)
print(f"标的 {security} 在 {date} 的 14日溃疡指数为: {ui_value:.4f}")
# 如果需要查看计算过程中的数据结构,可以修改函数返回 df
Q: 溃疡指数和最大回撤(Max Drawdown)有什么区别?
A: 最大回撤只衡量了历史上最糟糕的那一次下跌幅度(单点极值)。而溃疡指数考虑了所有的回撤幅度以及回撤持续的时间(平均下行波动)。如果一个资产频繁发生中等程度的回撤,最大回撤可能不大,但溃疡指数会较高。
Q: 为什么计算时要将回撤平方?
A: 平方操作是为了放大深度回撤的影响。就像标准差计算方差一样,较大的回撤在平方后对最终结果的贡献比小回撤大得多,这符合投资者对深度亏损更敏感的心理特征。
Q: 溃疡指数通常设置多少天的周期?
A: 最常见的设置是 14天,这与 RSI 等指标的默认周期一致。但在长期投资分析中,也可以使用更长的周期(如周线或月线数据)。