# 技术指标 (/zh/features/indicators/technical-indicators)

可以使用哪些技术指标，又能否同时跨多个标的和参数运行？VBT 在 Python 中通过统一接口运行 TA-Lib、pandas-ta、ta、Technical、Smart Money Concepts
和 WorldQuant 101 Alphas 的指标，以及自身的编译指标。每个指标都接受参数列表，并返回带标签的列。

```python title="Compute RSI with 10 window lengths on 5 ETFs in one call"
>>> symbols = ["SPY", "QQQ", "IWM", "TLT", "GLD"]
>>> data = vbt.YFData.pull(symbols, start="2024-01-01", end="2025-01-01")
>>> rsi = vbt.talib("RSI").run(data.close, timeperiod=np.arange(5, 55, 5))  # (1)
>>> rsi.real.shape
(252, 50)
>>> rsi.real.columns[:3]
MultiIndex([(5, 'SPY'),
            (5, 'QQQ'),
            (5, 'IWM')],
           names=['rsi_timeperiod', 'symbol'])

>>> rsi.real.iloc[-1].unstack("symbol").round(1).head(4)  # (2)
symbol           GLD   IWM   QQQ   SPY   TLT
rsi_timeperiod
5               51.2  32.5  29.0  29.5  32.7
10              47.6  33.9  40.7  37.8  33.1
15              47.4  37.7  45.7  42.4  35.7
20              47.9  40.9  48.4  45.5  37.5
```

1.  十个窗口乘以五个标的产生 50 列，一次调用完成计算。
2.  每列最后一个值，按窗口和标的排列。

## 指标库 \[#indicator-libraries]

各库指标均可通过带前缀名称访问：`vbt.talib("RSI")`、`vbt.pandas_ta("SUPERTREND")`、`vbt.ta("RSIIndicator")`，以及用于 Smart
Money Concepts 的 `vbt.indicator("smc:...")` 或用于 WorldQuant 101 Alphas 的 `"wqa101:..."`。每个指标都封装为与 VBT
自身指标相同的类，接受参数列表、标注输出、提供 `crossed_above` 等信号辅助方法并支持绘图。库本身为可选依赖，VBT
只使用您已安装的库。`vbt.IF.list_indicators("*vwap*")` 按名称搜索所有库，例如安装 pandas-ta 后会返回
`['vbt:VWAP', 'pandas_ta:VWAP']`。TA-Lib 还提供蜡烛形态和抛物线 SAR
等指标，详见其[函数目录](https://ta-lib.org/functions/)。许多 WorldQuant alpha
跨资产排名，因此需一次传入多个标的：单个资产的横截面排名总是相同。一些公式还使用行业或产业分组，适合研究带分类的标的池。

运行指标返回的是指标对象，而非 DataFrame。输出通过同名属性访问，例如 `vbt.RSI` 的 `.rsi` 和大多数 TA-Lib 指标的 `.real`，`output_names`
列出输出名称。下方功能介绍展示
[Smart Money Concepts](#smart-money-concepts)、[WorldQuant Alphas](#worldquant-alphas) 和 Freqtrade 的
[Technical](#technical-indicators) 库。

## 内置指标 \[#built-in-indicators]

VBT
自带编译指标：移动平均线（`vbt.MA`）、标准差（`vbt.MSD`）、布林带（`vbt.BBANDS`）、RSI（`vbt.RSI`）、随机指标（`vbt.STOCH`）、MACD（`vbt.MACD`）、ATR（`vbt.ATR`）、ADX（`vbt.ADX`）、能量潮（`vbt.OBV`）、VWAP（`vbt.VWAP`）、SuperTrend（`vbt.SUPERTREND`），以及带
ZigZag 线的拐点检测（`vbt.PIVOTINFO`）。VWAP 默认每天重置，可用 `anchor` 参数指定其他周期。这些指标在 Numba
中运行，无需额外依赖。如果速度比指标类更重要，`vbt.talib_func` 可直接调用 TA-Lib
函数，同时支持广播、缺失值处理和时间周期，如[轻量 TA-Lib](#lightweight-ta-lib)功能介绍所示。

移动平均线通过 `wtype` 提供简单、加权、指数、Wilder 和 VIDYA 平滑。布林带还提供带宽和百分比 B，用于研究波动收缩或价格在带内的位置。SuperTrend
除线条外还返回趋势方向，可作为其他指标入场的过滤器。

## 比较参数并生成信号 \[#compare-parameters-and-generate-signals]

参数列表让您无需逐项编写循环即可比较设置。存在多个参数时，列表默认配对。设置 `param_product=True` 测试全部组合。输出保留参数和标的标签，交叉辅助方法生成列结构相同的布尔信号。

这里使用两个虚构价格序列、两个回看窗口和两种带宽。结果为八列布林带，以及每种设置的上轨突破次数：

```python title="Compare Bollinger Band breakout settings"
>>> close = pd.DataFrame({
...     "A": [10, 11, 10, 10, 14, 11, 10, 15, 12, 11, 16, 12],
...     "B": [20, 19, 20, 20, 16, 19, 20, 15, 18, 19, 14, 18],
... }, index=pd.date_range("2025-01-01", periods=12))
>>> close.columns.name = "symbol"
>>> bands = vbt.BBANDS.run(close, window=[3, 5], alpha=[1.0, 1.5], param_product=True)
>>> entries = bands.close_crossed_above(bands.upper)
>>> bands.upper.shape
(12, 8)
>>> entries.sum().unstack("symbol")
symbol              A  B
bb_window bb_alpha
3         1.0       3  0
          1.5       0  0
5         1.0       2  0
          1.5       0  0
```

在这些价格上，较宽布林带产生更少突破。将信号用作入场条件，结合趋势或成交量过滤器，再在[信号回测](/zh/features/backtesting/signal-backtesting/)中添加退出规则。更大规模搜索和跨设置策略比较，请参阅[参数优化](/zh/features/optimization/strategy-optimization/)。

## 统计指标 \[#statistical-indicators]

`vbt.HURST` 估计 Hurst 指数，帮助区分趋势与均值回归行为；`vbt.OLS` 对两个序列进行滚动回归，是许多配对交易策略的基础。`vbt.PATSIM`
衡量与形态的相似度，详见[形态与事件研究](/zh/features/analytics/patterns-and-event-studies/)页面。下方
[Hurst 指数](#hurst-exponent)和[滚动 OLS](#rolling-ols)功能介绍展示前两者。如果研究需要其他统计量，[指标工厂](/zh/features/indicators/indicator-development/)可将自己的
Python 或 Numba 计算封装为具有相同参数和输出接口的指标。

## 另类图表 \[#alternative-charts]

Renko 砖块将价格序列转换为固定幅度移动，忽略时间，从而过滤噪声。下方 [Renko 图](#renko-chart)功能介绍根据收盘价构建砖块，并重采样为 OHLC K 线。对于
Heikin-Ashi
等自定义蜡烛变换，也可通过[指标工厂](/zh/features/indicators/indicator-development/)封装计算，保留独立开盘、最高、最低和收盘输出。

## 运行指标 \[#running-indicators]

指标可在一列或多列上运行，`data.run("rsi")` 从数据对象选择正确输入。TA-Lib 指标可设置 `skipna=True` 跳过缺失值，避免较晚上市资产的整列剩余部分都为空。

不同库对同一指标的初始值可能不同，因为平滑初始化方式不同。这个 RSI 比较中，经过预热期后数值趋于一致：

```python title="Compare TA-Lib's RSI with VBT's RSI"
>>> btc = vbt.YFData.pull("BTC-USD", start="2024-01-01", end="2025-01-01")
>>> talib_rsi = vbt.talib("RSI").run(btc.close, timeperiod=14).real
>>> vbt_rsi = vbt.RSI.run(btc.close, window=14).rsi
>>> pd.DataFrame({"talib": talib_rsi, "vbt": vbt_rsi}).iloc[[14, 15, 100, -1]].round(2)
                           talib    vbt
Date
2024-01-15 00:00:00+00:00  44.24  58.19
2024-01-16 00:00:00+00:00  46.80  60.27
2024-04-10 00:00:00+00:00  56.07  56.08
2024-12-31 00:00:00+00:00  43.51  43.51
```

需要匹配其他平台数值时，请加载比分析区间更多的历史，让预热在区间开始前完成。也要匹配输入价格、时间周期和平滑设置。

如果只需数组供后续计算，`return_raw="outputs"` 返回 NumPy
输出，而不构建最终指标对象和带标签输出列。其他计算周期上的指标见[多时间周期分析](/zh/features/data/multi-timeframe-analysis/)。随新 K
线更新计算，见[流式指标](/zh/features/indicators/streaming-indicators/)。

## Hurst 指数 \[#hurst-exponent]

新增于 v2024.6.19

✅ 估计 Hurst 指数可以洞察数据的持续性和均值回归行为。VBT 提供五种（！）不同实现。

```python title="Plot rolling Hurst exponent by method"
>>> data = vbt.YFData.pull("BTC-USD", start="12 months ago")
>>> hurst = vbt.HURST.run(data.close, method=["standard", "logrs", "rs", "dma", "dsod"])
>>> fig = vbt.make_subplots(specs=[[dict(secondary_y=True)]])
>>> data.plot(plot_volume=False, ohlc_trace_kwargs=dict(opacity=0.3), fig=fig)
>>> fig = hurst.hurst.vbt.plot(fig=fig, add_trace_kwargs=dict(secondary_y=True))
>>> fig = fig.select_range(start=hurst.param_defaults["window"])
>>> fig.show()
```

在 BTC-USD 市场数据上按不同方法计算的滚动 Hurst 指数. [Figure data (JSON)](/assets/figures/features/indicators/hurst.78d7278fc132.json)

## Smart Money Concepts \[#smart-money-concepts]

新增于 v2024.6.19

✅ VBT 集成了 [Smart Money Concepts（SMC）](https://github.com/joshyattridge/smart-money-concepts)
库的大多数指标。

```python title="Plot previous high and low"
>>> data = vbt.YFData.pull("BTC-USD", start="6 months ago")
>>> phl = vbt.smc("previous_high_low").run(  # (1)
...     data.open,
...     data.high,
...     data.low,
...     data.close,
...     data.volume,
...     time_frame=vbt.Default("7D")
... )
>>> fig = data.plot()
>>> phl.previous_high.rename("previous_high").vbt.plot(fig=fig)
>>> phl.previous_low.rename("previous_low").vbt.plot(fig=fig)
>>> (phl.broken_high == 1).rename("broken_high").vbt.signals.plot_as_markers(
...     y=phl.previous_high,
...     trace_kwargs=dict(marker=dict(color="limegreen")),
...     fig=fig
... )
>>> (phl.broken_low == 1).rename("broken_low").vbt.signals.plot_as_markers(
...     y=phl.previous_low,
...     trace_kwargs=dict(marker=dict(color="orangered")),
...     fig=fig
... )
>>> fig.show()
```

1.  每个 SMC 指标都需要 OHLCV。

BTC-USD OHLCV、前一周最高与最低价，以及水平突破标记. [Figure data (JSON)](/assets/figures/features/indicators/smart-money-concepts.2c91e487d04e.json)

## 轻量 TA-Lib \[#lightweight-ta-lib]

新增于 1.14.0

✅ 由指标工厂封装的 TA-Lib 函数非常强大：与官方 TA-Lib 实现不同，它们支持广播、DataFrame、跳过缺失值，甚至重采样到其他时间周期。虽然 TA-Lib
函数本身很快，指标工厂封装仍会带来一些开销。为了兼顾 TA-Lib 速度与 VBT 能力，新增功能已独立为轻量函数，可像普通 TA-Lib 函数一样调用。

```python title="Run and plot an RSI resampled to the monthly timeframe"
>>> data = vbt.YFData.pull("BTC-USD")
>>> run_rsi = vbt.talib_func("rsi")
>>> rsi = run_rsi(data.close, timeperiod=12, timeframe="M")  # (1)
>>> rsi
Date
2014-09-17 00:00:00+00:00          NaN
2014-09-18 00:00:00+00:00          NaN
2014-09-19 00:00:00+00:00          NaN
2014-09-20 00:00:00+00:00          NaN
2014-09-21 00:00:00+00:00          NaN
                                   ...
2024-01-18 00:00:00+00:00    64.210811
2024-01-19 00:00:00+00:00    64.210811
2024-01-20 00:00:00+00:00    64.210811
2024-01-21 00:00:00+00:00    64.210811
2024-01-22 00:00:00+00:00    64.210811
Freq: D, Name: Close, Length: 3415, dtype: float64

>>> plot_rsi = vbt.talib_plot_func("rsi")
>>> plot_rsi(rsi).show()
```

1.  参数应用于目标时间周期。

重采样至月频的 BTC-USD RSI. [Figure data (JSON)](/assets/figures/features/indicators/native-ta-lib.d96222a6f261.json)

## 技术指标 \[#technical-indicators]

新增于 1.7.0

✅ VBT 集成了 freqtrade 的 [technical](https://github.com/freqtrade/technical) 库中大多数指标与共识类。

```python title="Compute and plot the summary consensus with a one-liner"
>>> vbt.YFData.pull("BTC-USD").run("sumcon", smooth=100).plot().show()
```

BTC-USD 平滑后的技术指标买卖汇总共识. [Figure data (JSON)](/assets/figures/features/indicators/summary-consensus.0a262862e34f.json)

## Renko 图 \[#renko-chart]

新增于 1.7.0

✅
与常规图表不同，[Renko 图](https://www.investopedia.com/terms/r/renkochart.asp)根据价格变动构建。价格每变化指定幅度，就出现一块“砖”。由于输出时间间隔不规则，每次只能处理一列。与其他功能一样，借助
Numba，VBT 实现能够快速转换海量数据点。

```python title="Resample closing price into a Renko format"
>>> data = vbt.YFData.pull("BTC-USD", start="2021", end="2022")
>>> renko_ohlc = data.close.vbt.to_renko_ohlc(1000, reset_index=True)  # (1)
>>> renko_ohlc.vbt.ohlcv.plot().show()
```

1.  比特币波动较大，因此砖块大小设为 1000。

将 BTC-USD 收盘价重采样为 Renko OHLC 图. [Figure data (JSON)](/assets/figures/features/indicators/renko-chart.4982a9891b2d.json)

## 滚动 OLS \[#rolling-ols]

新增于 1.3.0

✅ 滚动回归用于分析变量关系随时间的变化。VBT 将其实现为指标，接受两个时间序列，并在每个时间步返回斜率、截距、预测、误差、R 平方和误差 z
分数。可在配对研究中使用回归及残差，例如构建价差并测试入场或再平衡规则。它还比 statsmodels 对应的
[RollingOLS](https://www.statsmodels.org/dev/generated/statsmodels.regression.rolling.RollingOLS.html)
快数百倍 🔥

```python title="Determine the spread between BTC and ETH"
>>> data = vbt.YFData.pull(
...     ["BTC-USD", "ETH-USD"],
...     start="2022",
...     end="2023",
...     missing_index="drop"
... )
>>> ols = vbt.OLS.run(
...     data.get("Close", "BTC-USD"),
...     data.get("Close", "ETH-USD")
... )
>>> ols.plot_zscore().show()
```

2022 年 BTC 与 ETH 之间的滚动 OLS 价差 z 分数. [Figure data (JSON)](/assets/figures/features/indicators/rolling-ols.4b021c8f0823.json)

## TA-Lib 绘图 \[#ta-lib-plotting]

新增于 1.0.9

✅ 每个 TA-Lib 指标都能完全根据输出标志自行绘图！

```python
>>> data = vbt.YFData.pull("BTC-USD", start="2020", end="2021")

>>> vbt.talib("MACD").run(data.close).plot().show()
```

2020 年 BTC-USD 的 TA-Lib MACD、信号线和直方图. [Figure data (JSON)](/assets/figures/features/indicators/ta-lib.ce381192f226.json)

## WorldQuant Alphas \[#worldquant-alphas]

新增于 1.0.8

✅ [WorldQuant 的 101 个公式化 Alpha](https://arxiv.org/pdf/1601.00991.pdf)现在全部可以作为指标使用 👀

```python title="Run the first alpha"
>>> data = vbt.YFData.pull(["BTC-USD", "ETH-USD", "XRP-USD"], missing_index="drop")

>>> vbt.wqa101(1).run(data.close).out
symbol                      BTC-USD   ETH-USD   XRP-USD
Date
2017-11-09 00:00:00+00:00  0.166667  0.166667  0.166667
2017-11-10 00:00:00+00:00  0.166667  0.166667  0.166667
2017-11-11 00:00:00+00:00  0.166667  0.166667  0.166667
2017-11-12 00:00:00+00:00  0.166667  0.166667  0.166667
2017-11-13 00:00:00+00:00  0.166667  0.166667  0.166667
...                             ...       ...       ...
2023-01-31 00:00:00+00:00  0.166667  0.166667  0.166667
2023-02-01 00:00:00+00:00  0.000000  0.000000  0.500000
2023-02-02 00:00:00+00:00  0.000000  0.000000  0.500000
2023-02-03 00:00:00+00:00  0.000000  0.500000  0.000000
2023-02-04 00:00:00+00:00 -0.166667  0.333333  0.333333

[1914 rows x 3 columns]
```
