# 机器学习标签 (/zh/features/indicators/machine-learning-labels)

如何为交易模型创建目标，又如何回测它的预测？VBT 在 Python
中生成机器学习标签，包括固定期限收益、三重障碍结果、趋势和拐点，并使用与其他信号相同的回测引擎运行模型预测，同时明确保留标签中的前视性质。

```python title="Label barrier outcomes, train a classifier walk-forward, and backtest its predictions"
>>> from sklearn.ensemble import RandomForestClassifier

>>> data = vbt.YFData.pull("BTC-USD", start="2018-01-01", end="2025-01-01")
>>> labels = vbt.BOLB.run(  # (1)
...     data.high, data.low, window=10, up_th=0.05, down_th=0.05
... ).labels.rename("label")
>>> labels.value_counts(dropna=False).sort_index()
label
-1.0    1089
 0.0     151
 1.0    1317
Name: count, dtype: int64

>>> returns = data.close.pct_change()
>>> features = pd.DataFrame({  # (2)
...     "rsi": vbt.RSI.run(data.close, window=14).rsi,
...     "ret_5": data.close.pct_change(5),
...     "ret_20": data.close.pct_change(20),
...     "vol_20": returns.rolling(20).std(),
...     "dist_sma_50": data.close / data.close.rolling(50).mean() - 1,
... })

>>> proba = pd.Series(np.nan, index=data.index)
>>> for year in [2021, 2022, 2023, 2024]:  # (3)
...     test = data.index.year == year
...     train_end = data.index[test][0] - pd.Timedelta(days=10)
...     train = (
...         (data.index < train_end)
...         & features.notna().all(axis=1)
...         & labels.notna()
...         & (labels != 0)
...     )
...     model = RandomForestClassifier(n_estimators=200, max_depth=4, random_state=42)
...     model.fit(features[train], labels[train] == 1)
...     proba[test] = model.predict_proba(features[test].fillna(0))[:, 1]

>>> kwargs = dict(
...     price="nextopen",  # (4)
...     tp_stop=0.05,
...     sl_stop=0.05,
...     td_stop=10,
...     time_delta_format="rows",
...     fees=0.001,
... )
>>> test_data = data.loc["2021":]
>>> model_pf = vbt.PF.from_signals(test_data, (proba > 0.55).loc["2021":], **kwargs)
>>> always_pf = vbt.PF.from_signals(test_data, True, **kwargs)  # (5)
>>> metrics = ["total_trades", "win_rate", "total_return", "sharpe_ratio"]
>>> pd.DataFrame({
...     "model": model_pf.stats(metrics),
...     "every bar": always_pf.stats(metrics),
... }).round(2)
                      model  every bar
Total Trades            145        302
Win Rate [%]          51.03      47.84
Total Return [%]       9.14     -42.96
Sharpe Ratio           0.24       0.02
```

1.  扫描未来 10 根 K 线，寻找从当前最低价上涨 5%（1）或从当前最高价下跌 5%（-1）。零表示未找到明确突破。这些价格和时间障碍构成标签目标。
2.  特征仅使用截至各根 K 线收盘的数据。
3.  使用此前所有年份训练，但排除每个测试年份前的最后 10 天，避免任何训练标签看到测试年。
4.  在 K 线收盘时作出的预测，于下一开盘交易。止损止盈使用相同的 5% 距离和 10 根 K 线限制，但从模拟交易衡量，而非标签的最高价和最低价。
5.  基线不使用模型，执行障碍允许的每笔交易。

模型入场胜率为 51%，而每根 K 线都入场为 48%，并在四个样本外年份将亏损转为小幅盈利。这是诚实衡量的微弱优势：标签来自未来，特征来自过去，预测只用于模型从未见过的年份。

分类器在上涨和下跌结果上训练，排除零标签。概率阈值选择入场，投资组合模拟则衡量扣费后这些入场实际赚取多少。您可以更换目标、模型或阈值，同时保留相同研究流程。

## 选择模型应预测什么 \[#choose-what-the-model-should-predict]

标签定义您希望模型回答的问题。重视变动幅度时使用未来收益，重视价格移动先后顺序时使用障碍结果，研究更广泛市场移动时使用趋势标签。这些目标可服务于您选择的 Python 框架中的回归或分类模型。

## 标签生成器 \[#label-generators]

每个标签生成器都是向前而非向后看的指标：

| 指标            | 标签                       | 用途            |
| ------------- | ------------------------ | ------------- |
| `vbt.FIXLB`   | 从每根 K 线到固定数量 K 线之后的收益率   | 比较预测期限        |
| `vbt.MEANLB`  | 到未来窗口平均价格的收益率            | 预测未来平均价格水平    |
| `vbt.BOLB`    | 未来窗口中先达到上涨还是下跌阈值         | 对未来突破方向分类     |
| `vbt.PIVOTLB` | 根据事后信息判断每根 K 线是否为高点或低点拐点 | 学习转折点目标       |
| `vbt.TRENDLB` | 拐点间趋势，可表示方向、变动中的位置或收益率   | 对趋势分类，或预测变动进度 |

与其他指标一样，它们接受参数列表，因此期限或阈值网格产生标签网格，并可叠加在价格上快速检查。`vbt.PIVOTLB` 和 `vbt.TRENDLB` 读取最高及最低价，接受两个正阈值：`up_th`
为确认谷底所需的上涨幅度，`down_th` 为从峰值下跌的幅度。相同百分比并不对称，因为恢复 50% 跌幅需要上涨 100%。

对于突破目标，`BOLB` 提供两种参考选择。默认 `"swing"` 模式从当前最低价衡量上涨，从当前最高价衡量下跌。`"range"` 模式将阈值放在当前最高价和最低价之外，适合研究突破当前 K
线范围的问题。阈值也可随观测变化，例如使用根据历史数据算出的波动率序列。

## 比较预测期限 \[#compare-prediction-horizons]

期限是研究问题的一部分。这个虚构序列在未来一根和三根 K 线上产生不同收益目标，下面以百分比显示：

```python title="Build one-bar and three-bar return targets together"
>>> close = pd.Series([100.0, 110.0, 105.0, 120.0, 108.0],
...                   index=pd.date_range("2025-01-01", periods=5))
>>> labels = vbt.FIXLB.run(close, n=[1, 3]).labels
>>> (labels * 100).round(2)
fixlb_n         1      3
2025-01-01  10.00  20.00
2025-01-02  -4.55  -1.82
2025-01-03  14.29    NaN
2025-01-04 -10.00    NaN
2025-01-05    NaN    NaN
```

所需未来价格不可用时，`FIXLB` 将目标留空。选择希望建模的期限，并在目标与特征均可用的行上训练。

!!! warning "标签使用未来信息"
    标签使用未来观测。请将其用于训练目标或事后分析，而非当作交易决策时可获知的信息。排除未来观测与测试期重叠的训练标签。上例通过间隔覆盖固定期限，而拐点和趋势标签需要考虑其结果变为已知的时间。请参阅[前向滚动与交叉验证](/zh/features/optimization/time-series-cross-validation/)。

## 前向统计 \[#forward-statistics]

`vbt.FMEAN`、`vbt.FMAX`、`vbt.FMIN` 和 `vbt.FSTD` 计算未来窗口的均值、最大值、最小值和标准差，可在窗口开始前等待 `wait`。它们回答“未来 20
天价格涨了多少”等问题，并可作为连续目标。

## 元标签 \[#meta-labeling]

模型不必独立发现交易。在元标签方法中，基于规则的策略提出交易，按每笔交易的结果标注标签，例如扣费后是否盈利，再由第二个模型学习哪些建议应接受，或应投入多少。标签来自策略自身交易记录，例如
`pf.trades.returns`；模型决策成为入场过滤器或每笔交易的规模。让特征与原始入场机会对齐，再在相同手续费和规模规则下比较过滤后策略与原策略。[交易分析](/zh/features/analytics/trade-analytics/)帮助检查过滤器接受和拒绝了哪些交易。

## 回测预测 \[#backtesting-predictions]

预测也是与其他输入相同的数组。经过阈值处理的概率成为入场和退出信号，预测收益或评分成为规模，多资产预测权重成为 `from_orders` 的目标配置。在 GPU
或其他框架训练的模型，只需将输出转换为 NumPy 或 pandas，再传入运行于 CPU 的模拟器。

!!! info "教程"
    会员专属的[交叉验证（英文）](https://members.vectorbt.pro/tutorials/cross-validation/applications/)教程将切分器用于模型和参数搜索，避免未来信息泄漏到训练中。
