Momentum:INERTIA(惯量指标)技术指标详解
一、INERTIA的定义
INERTIA(惯量指标) 是由技术分析师Donald Dorsey于1995年9月在《股票与商品期货技术分析》杂志上正式发表的一种趋势指标。该指标的名称源于物理学中的“惯性”(Inertia)概念——物体在不受外力作用时,保持原有运动状态的性质。
核心思想
Dorsey对趋势的解释是:趋势是市场惯性的外在表现。根据惯性原理,市场要改变方向需要比维持原方向消耗更多的能量,因此趋势一旦形成,就具有一定的“延续性”。
在实际金融市场中,趋势的方向是容易定义的(上涨或下跌),但“质量”或“惯性大小”却难以量化。Dorsey认为,波动率(Volatility)可能是衡量市场惯性最简单也最准确的指标。基于这一理论,他选择使用相对波动率指数(Relative Volatility Index, RVI) 作为惯量指标的计算基础,然后通过线性回归(Least Squares Moving Average)对RVI进行平滑处理,最终得到INERTIA指标。
INERTIA的核心特征
| 理论基础 | 物理学的惯性原理 + 波动率是惯性度量 |
| 数值范围 | 0 到 100(与RSI同尺度) |
| 多空分界 | 50为中心线 |
| 开发者 | Donald Dorsey(1995年) |
| 指标类型 | 趋势跟随指标(Trend Following) |
| 核心组件 | RVI(相对波动率指数)+ LSQRMA(最小二乘移动平均) |
INERTIA与RVI的关系
INERTIA是在RVI基础上构建的指标:
| 基础层 | RVI(相对波动率指数) | 衡量市场波动率的方向性偏向 |
| 平滑层 | LSQRMA(线性回归移动平均) | 对RVI进行平滑,消除噪声,凸显趋势 |
Dorsey之所以选择这种两层结构,是因为单纯使用RVI作为趋势指标可能存在较多噪声,通过线性回归平滑后,可以更清晰地识别长期趋势的方向。
二、INERTIA的计算方法
1. 核心计算公式
INERTIA的标准计算公式为:
INERTIA=LSQRMAlength(RVIrvi_length)
\\mathrm{INERTIA} = \\mathrm{LSQRMA}_{\\mathrm{length}}(\\mathrm{RVI}_{\\mathrm{rvi\\_length}})
INERTIA=LSQRMAlength(RVIrvi_length)
其中:
- RVIrvi_length\\mathrm{RVI}_{\\mathrm{rvi\\_length}}RVIrvi_length:指定周期的相对波动率指数值
- LSQRMAlength\\mathrm{LSQRMA}_{\\mathrm{length}}LSQRMAlength:指定周期的最小二乘移动平均(线性回归移动平均)
2. 详细计算步骤
INERTIA 的计算分为两个主要阶段:先计算 RVI,再对 RVI 应用线性回归平滑。
第一阶段:计算RVI(相对波动率指数)
RVI 的计算公式为:
RVI=SMA(U,n)SMA(U,n)+SMA(D,n)×100
\\mathrm{RVI} = \\frac{\\mathrm{SMA}(U,n)}{\\mathrm{SMA}(U,n) + \\mathrm{SMA}(D,n)} \\times 100
RVI=SMA(U,n)+SMA(D,n)SMA(U,n)×100
其中:
- Ut=StdDev(Closet−n+1..t)U_t = \\mathrm{StdDev}(\\mathrm{Close}_{t−n+1..t})Ut=StdDev(Closet−n+1..t) 的上涨部分
- Dt=StdDev(Closet−n+1..t)D_t = \\mathrm{StdDev}(\\mathrm{Close}_{t−n+1..t})Dt=StdDev(Closet−n+1..t) 的下跌部分
RVI 的计算逻辑与 RSI 类似,但使用波动率(标准差) 替代了价格变化作为输入,反映的是波动率的方向性偏向。
第二阶段:计算线性回归移动平均
LSQRMAt=LinearRegression(RVIt−length+1..t)
\\mathrm{LSQRMA}_t = \\mathrm{LinearRegression}(\\mathrm{RVI}_{t-\\mathrm{length}+1..t})
LSQRMAt=LinearRegression(RVIt−length+1..t)
LSQRMAt=LinearRegression(RVIt−length+1…t)LSQRMAt=LinearRegression(RVIt−length+1…t)
LSQRMA(也称为时间序列移动平均 TSMA)通过对指定窗口内的RVI值进行线性回归拟合,取回归线在当前时刻的预测值作为输出。
3. INERTIA的简化等价形式
将上述步骤合并,INERTIA的完整计算可表示为:
INERTIAt=β0(t)+β1(t)×length
\\mathrm{INERTIA}_t = \\beta_{0}^{(t)} + \\beta_{1}^{(t)} \\times \\mathrm{length}
INERTIAt=β0(t)+β1(t)×length
其中 β0(t)\\beta_{0}^{(t)}β0(t) 和 β1(t)\\beta_{1}^{(t)}β1(t) 是RVI值在窗口[t−length+1,t][t − \\mathrm{length} + 1,t][t−length+1,t] 上的线性回归系数。
4. pandas_ta中的参数
根据pandas_ta源码,INERTIA包含多种计算模式:
| length | int | 20 | 线性回归平滑周期(LSQRMA周期) |
| rvi_length | int | 14 | RVI计算周期 |
| scalar | float | 100 | 放大倍数(转换为0-100范围) |
| refined | bool | False | 是否使用改进版RVI计算 |
| thirds | bool | False | 是否使用三分法RVI计算 |
| mamode | str | “ema” | RVI计算中的移动平均类型 |
refined和thirds参数说明:
- refined=False, thirds=False:使用标准RVI计算(仅基于收盘价)
- refined=True:使用改进版RVI(同时使用OHLC数据)
- thirds=True:使用三分法RVI(介于标准和改进版之间)
5. RVI计算详解(补充说明)
由于INERTIA建立在RVI基础上,理解RVI的计算有助于更好地使用INERTIA:
RVI的计算逻辑与RSI完全平行,区别仅在于输入数据:
| 输入数据 | 价格变化(ΔClose) | 波动率(标准差) |
| 上涨度量 | 正价格变化 | 波动率上升期 |
| 下跌度量 | 负价格变化绝对值 | 波动率下降期 |
| 计算公式 | 100 × U/(U+D) | 100 × U/(U+D) |
换言之,RVI衡量的是“波动率的方向性偏向”,而INERTIA则是对RVI的进一步平滑。
6. 计算示例(简化)
假设已计算出某段周期的RVI值序列如下(使用默认参数length=20, rvi_length=14):
| t-19 | 45 |
| t-18 | 47 |
| … | … |
| t-1 | 52 |
| t | 54 |
对这些RVI值进行线性回归拟合,得到回归线的终点预测值。如果回归线呈上升趋势,INERTIA值将高于50;如果回归线呈下降趋势,INERTIA值将低于50。
三、INERTIA的使用方法
1. 50线多空分界——最核心用法
INERTIA在0-100范围内波动,以50为中心线:
| INERTIA > 50 | 正惯量(Positive Inertia) | 市场处于长期上涨趋势中,多头惯性占据主导 | 顺势做多 |
| INERTIA < 50 | 负惯量(Negative Inertia) | 市场处于长期下跌趋势中,空头惯性占据主导 | 顺势做空 |
| INERTIA = 50 | 中性 | 多空力量平衡,趋势不明确 | 观望 |
核心逻辑:INERTIA高于50表示市场具有“向上惯性”,价格更倾向于继续上涨而非反转;低于50则表示具有“向下惯性”。
2. 趋势强度判断
INERTIA偏离50的程度可以反映趋势的强度:
| > 70 | 强上升趋势 | 上涨惯性很强,多头动能充足 |
| 60 – 70 | 中等上升趋势 | 上涨惯性明显,趋势健康 |
| 50 – 60 | 弱上升趋势 | 上涨惯性初显,趋势可能刚形成 |
| 50 – 40 | 弱下降趋势 | 下跌惯性初显 |
| 40 – 30 | 中等下降趋势 | 下跌惯性明显 |
| < 30 | 强下降趋势 | 下跌惯性很强,空头动能充足 |
3. 零轴穿越 vs 50线穿越
与传统震荡指标不同,INERTIA的中心线是50而非0,因此信号应基于50线穿越:
| 看涨穿越 | INERTIA从下方上穿50线 | 市场从负惯量转为正惯量,长期趋势可能由跌转涨 | 考虑建立多头仓位 |
| 看跌穿越 | INERTIA从上方下穿50线 | 市场从正惯量转为负惯量,长期趋势可能由涨转跌 | 考虑平仓或建立空头 |
4. 耐心——使用INERTIA的关键
根据文献记载,正确使用INERTIA最重要的一点是保持耐心(patience)。该指标专为捕捉长期趋势而设计,信号频率较低,不适合短线交易者。
正确的心态:
- INERTIA不是用来捕捉每一个市场波动的工具
- 当INERTIA给出方向信号后,应顺应其方向持仓,直到信号改变
- 频繁进出会削弱INERTIA的有效性
5. 背离信号
与价格走势的背离可以提供额外的交易参考:
| 顶背离 | 价格创出新高 | INERTIA未能创出新高(形成更低高点) | 上涨惯性减弱,可能见顶 |
| 底背离 | 价格创出新低 | INERTIA未能创出新低(形成更高低点) | 下跌惯性减弱,可能见底 |
6. 与其他指标的配合策略
| 移动平均线 | 确认价格位置 | INERTIA > 50 + 价格在MA200上方 → 长期多头趋势确认 |
| ADX | 验证趋势强度 | INERTIA与ADX同时指示强趋势时信号更可靠 |
| 成交量 | 验证动能 | INERTIA转向时伴随成交量放大 → 信号可靠性提升 |
| 支撑/阻力位 | 确认关键位置 | INERTIA信号出现在关键价位时胜率更高 |
7. 注意事项与局限性
使用INERTIA前需了解以下要点:
| 信号频率低 | INERTIA是长期趋势指标,信号出现频率低,不适合短线交易者 |
| 滞后性质 | 基于RVI和线性回归双重平滑,存在一定滞后性 |
| 需要耐心 | 指标使用的首要原则是“保持耐心”,频繁操作会削弱其有效性 |
| 参数敏感 | length和rvi_length两个参数需要根据交易周期优化 |
| 不能单独使用 | 建议作为趋势确认工具,与其他指标配合使用 |
四、使用pandas_ta计算INERTIA(示例代码)
1. pandas_ta中的INERTIA函数
pandas_ta库内置了INERTIA指标的完整实现,函数位于momentum模块中。
2. 函数完整参数
pandas_ta.momentum.inertia(
close, # 收盘价序列
high=None, # 最高价序列(refined/thirds模式需要)
low=None, # 最低价序列(refined/thirds模式需要)
length=None, # 线性回归周期(默认20)
rvi_length=None,# RVI周期(默认14)
scalar=None, # 放大倍数(默认100)
refined=None, # 是否使用改进版RVI(默认False)
thirds=None, # 是否使用三分法RVI(默认False)
mamode=None, # 移动平均类型(默认"ema")
drift=None, # 价格变化步长(默认1)
offset=None, # 结果偏移周期数
**kwargs
)
参数详解:
| close | pd.Series | 必需 | 收盘价序列 |
| high | pd.Series | None | 最高价序列(refined/thirds=True时需要) |
| low | pd.Series | None | 最低价序列(refined/thirds=True时需要) |
| length | int | 20 | 线性回归平滑周期 |
| rvi_length | int | 14 | RVI计算周期 |
| scalar | float | 100 | 放大倍数(转换为0-100范围) |
| refined | bool | False | 是否使用改进版RVI |
| thirds | bool | False | 是否使用三分法RVI |
| mamode | str | “ema” | RVI中的移动平均类型 |
返回值:pd.Series——INERTIA值序列(范围0-100)。
3. 示例代码
import pandas as pd
import pandas_ta as ta
import numpy as np
import matplotlib.pyplot as plt
# ========== 第一步:准备数据 ==========
np.random.seed(42)
dates = pd.date_range(start='2020-01-01', end='2024-12-31', freq='D')
n = len(dates)
# 生成带长期趋势和周期波动的价格序列
long_trend = np.linspace(0, 60, n)
cycle = np.sin(np.linspace(0, 4 * np.pi, n)) * 15
noise = np.random.randn(n) * 3
price_series = 100 + long_trend + cycle + noise
df = pd.DataFrame(index=dates)
df['close'] = price_series
df['high'] = df['close'] + np.abs(np.random.randn(n)) * 3 + 2
df['low'] = df['close'] – np.abs(np.random.randn(n)) * 3 – 2
df['volume'] = np.random.randint(1000000, 20000000, n)
print("=" * 60)
print("数据预览:")
print(df.head())
print("\\n" + "=" * 60 + "\\n")
# ========== 第二步:计算INERTIA(基础用法) ==========
# 使用默认参数 length=20, rvi_length=14
df['INERTIA'] = ta.inertia(df['close'])
print("INERTIA计算结果(最近10行):")
print(df[['close', 'INERTIA']].tail(10))
print("\\n" + "=" * 60 + "\\n")
# ========== 第三步:不同计算模式的INERTIA ==========
# 标准模式(仅收盘价)
df['INERTIA_std'] = ta.inertia(df['close'], refined=False, thirds=False)
# 改进模式(使用OHLC数据)
# df['INERTIA_refined'] = ta.inertia(df['close'], high=df['high'], low=df['low'], refined=True)
# 三分法模式
# df['INERTIA_thirds'] = ta.inertia(df['close'], high=df['high'], low=df['low'], thirds=True)
print("不同模式INERTIA对比(最近5行):")
print(df[['close', 'INERTIA_std']].tail())
print("\\n" + "=" * 60 + "\\n")
# ========== 第四步:自定义参数 ==========
# 短线参数
df['INERTIA_short'] = ta.inertia(df['close'], length=10, rvi_length=9)
# 标准参数
df['INERTIA_std_param'] = ta.inertia(df['close'], length=20, rvi_length=14)
# 长线参数
df['INERTIA_long'] = ta.inertia(df['close'], length=30, rvi_length=21)
print("不同参数INERTIA对比(最近5行):")
print(df[['close', 'INERTIA_short', 'INERTIA_std_param', 'INERTIA_long']].tail())
print("\\n" + "=" * 60 + "\\n")
# ========== 第五步:生成50线穿越信号 ==========
OVERBOUGHT = 70
OVERSOLD = 30
df['inertia_above_50'] = df['INERTIA'] > 50
df['cross_above_50'] = (df['inertia_above_50'] == True) & (df['inertia_above_50'].shift(1) == False)
df['cross_below_50'] = (df['inertia_above_50'] == False) & (df['inertia_above_50'].shift(1) == True)
df['signal'] = ''
df.loc[df['cross_above_50'], 'signal'] = '买入(上穿50线)'
df.loc[df['cross_below_50'], 'signal'] = '卖出(下穿50线)'
print("50线穿越信号(最近10个):")
signals = df[df['signal'] != ''].tail(10)
if not signals.empty:
print(signals[['close', 'INERTIA', 'signal']])
else:
print("近期无穿越信号")
print("\\n" + "=" * 60 + "\\n")
# ========== 第六步:趋势强度信号 ==========
df['strength_signal'] = ''
df.loc[df['INERTIA'] > 70, 'strength_signal'] = '强正惯量(强劲上涨趋势)'
df.loc[(df['INERTIA'] > 50) & (df['INERTIA'] <= 70), 'strength_signal'] = '中等正惯量(上涨趋势)'
df.loc[(df['INERTIA'] < 50) & (df['INERTIA'] >= 30), 'strength_signal'] = '中等负惯量(下跌趋势)'
df.loc[df['INERTIA'] < 30, 'strength_signal'] = '强负惯量(强劲下跌趋势)'
print("趋势强度信号统计:")
print(df['strength_signal'].value_counts())
print("\\n" + "=" * 60 + "\\n")
# ========== 第七步:背离检测(简化版) ==========
# 计算20日价格变化和INERTIA变化
df['price_change_20d'] = df['close'].diff(20)
df['inertia_change_20d'] = df['INERTIA'].diff(20)
# 检测潜在背离
df['potential_bearish_div'] = (df['price_change_20d'] > 0) & (df['inertia_change_20d'] < 0)
df['potential_bullish_div'] = (df['price_change_20d'] < 0) & (df['inertia_change_20d'] > 0)
print("潜在背离信号统计(20日尺度):")
print(f"潜在顶背离(价格涨INERTIA跌)数量:{df['potential_bearish_div'].sum()}")
print(f"潜在底背离(价格跌INERTIA涨)数量:{df['potential_bullish_div'].sum()}")
print("注:完整背离需结合局部高/低点分析,此处为方向对比")
print("\\n" + "=" * 60 + "\\n")
# ========== 第八步:策略回测(50线穿越策略) ==========
# 策略:INERTIA > 50 时持仓多头
df['position'] = (df['INERTIA'] > 50).astype(int)
# 计算收益
df['returns'] = df['close'].pct_change()
df['strategy_returns'] = df['position'].shift(1) * df['returns']
total_return_buyhold = (1 + df['returns']).prod() – 1
total_return_strategy = (1 + df['strategy_returns']).prod() – 1
# 计算年化收益率
years = len(df) / 252
annual_return_buyhold = (1 + total_return_buyhold) ** (1 / years) – 1 if years > 0 else 0
annual_return_strategy = (1 + total_return_strategy) ** (1 / years) – 1 if years > 0 else 0
print("=" * 60)
print("策略绩效统计(INERTIA 50线穿越策略 – 长线回测):")
print(f"回测周期:{years:.1f}年")
print(f"买入持有策略总收益率:{total_return_buyhold:.2%}")
print(f"买入持有策略年化收益率:{annual_return_buyhold:.2%}")
print(f"INERTIA策略总收益率:{total_return_strategy:.2%}")
print(f"INERTIA策略年化收益率:{annual_return_strategy:.2%}")
print("\\n注意:此为简化回测,仅供参考;INERTIA是长线指标,建议使用周线或月线数据")
print("=" * 60 + "\\n")
# ========== 第九步:可视化 ==========
plt.figure(figsize=(14, 12))
# 子图1:价格走势
plt.subplot(3, 1, 1)
plt.plot(df.index, df['close'], label='Close Price',
linewidth=1.2, color='black')
plt.title('Price Chart (Long-term Trend Analysis)', fontsize=14)
plt.ylabel('Price')
plt.legend()
plt.grid(True, alpha=0.3)
# 子图2:INERTIA指标(含50线)
plt.subplot(3, 1, 2)
plt.plot(df.index, df['INERTIA'], label='INERTIA (length=20, rvi=14)',
linewidth=1.5, color='blue')
plt.axhline(y=50, color='red', linestyle='-', linewidth=1.5, label='中心线 (50)')
plt.axhline(y=70, color='orange', linestyle='–', linewidth=1, label='超买线 (70)', alpha=0.7)
plt.axhline(y=30, color='green', linestyle='–', linewidth=1, label='超卖线 (30)', alpha=0.7)
# 填充区域
plt.fill_between(df.index, 70, 100, alpha=0.1, color='red', label='强正惯量区')
plt.fill_between(df.index, 0, 30, alpha=0.1, color='green', label='强负惯量区')
# 标记50线穿越信号
buy_signals = df[df['cross_above_50']]
sell_signals = df[df['cross_below_50']]
plt.scatter(buy_signals.index, buy_signals['INERTIA'],
color='green', marker='^', s=60, label='买入信号(上穿50)', alpha=0.8)
plt.scatter(sell_signals.index, sell_signals['INERTIA'],
color='red', marker='v', s=60, label='卖出信号(下穿50)', alpha=0.8)
plt.title('INERTIA Indicator – Long-term Trend Following', fontsize=14)
plt.ylabel('INERTIA Value')
plt.ylim(0, 100)
plt.legend(loc='upper left')
plt.grid(True, alpha=0.3)
# 子图3:持仓状态
plt.subplot(3, 1, 3)
plt.fill_between(df.index, 0, df['position'],
color='green', alpha=0.5, label='持仓状态 (INERTIA>50)')
plt.axhline(y=0.5, color='gray', linestyle='–', linewidth=0.8)
plt.title('Strategy Position (Long when INERTIA > 50)', fontsize=14)
plt.xlabel('Date')
plt.ylabel('Position')
plt.ylim(–0.1, 1.1)
plt.legend(loc='upper left')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# ========== 第十步:不同参数对比 ==========
plt.figure(figsize=(14, 6))
plt.plot(df.index[–200:], df['INERTIA_short'][–200:], label='INERTIA (10,9) – Fast',
linewidth=1, alpha=0.7)
plt.plot(df.index[–200:], df['INERTIA_std_param'][–200:], label='INERTIA (20,14) – Standard',
linewidth=1.5, color='blue')
plt.plot(df.index[–200:], df['INERTIA_long'][–200:], label='INERTIA (30,21) – Slow',
linewidth=1.5, color='green')
plt.axhline(y=50, color='red', linestyle='-', linewidth=1)
plt.title('INERTIA: Different Parameters Comparison', fontsize=14)
plt.xlabel('Date')
plt.ylabel('INERTIA Value')
plt.ylim(0, 100)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# ========== 第十一步:数据清洗提示 ==========
nan_count = df['INERTIA'].isna().sum()
print(f"\\nINERTIA初始NaN数量:{nan_count}")
print("原因:INERTIA需要至少 max(length, rvi_length) 个周期的数据才能计算")
print(f"建议:丢弃前 {max(20, 14)} = 20 个交易日的数据")
print("处理建议:df_clean = df.iloc[20:].copy()")
print("\\n" + "=" * 60)
print("INERTIA使用提示:")
print("1. 该指标专为长期趋势设计,建议在周线或月线上使用")
print("2. 50线是核心分界线——上穿做多,下穿做空")
print("3. 使用该指标最重要的一点是:保持耐心(Patience)")
print("=" * 60)
五、总结
INERTIA(惯量指标)是一种基于波动率方向性和线性回归平滑的长期趋势指标,其核心价值与定位如下:
| 核心创新 | 将物理学惯性概念引入技术分析,用波动率衡量市场惯性 |
| 核心公式 | LSQRMA(RVI) |
| 数值范围 | 0 到 100,50为中心线 |
| 核心信号 | 50线穿越、趋势强度判断 |
| 开发者 | Donald Dorsey(1995年) |
| 最佳应用场景 | 长期趋势识别、趋势确认 |
| 主要局限 | 信号频率低、滞后性、需要耐心 |
实战使用三原则:
最后提醒:INERTIA的核心价值在于帮助交易者回答一个关键问题:“当前市场是否具有延续当前趋势的惯性?” 当INERTIA大于50时,市场具有向上惯性,价格更倾向于继续上涨而非反转;当INERTIA小于50时,市场具有向下惯性。Dorsey通过将波动率作为惯性的度量,创造性地将物理概念转化为可量化的技术指标。然而,正如文献所述,正确使用INERTIA最重要的一点是保持耐心——它是长线趋势交易者的工具,而非短线投机者的利器。



