4. 标签定义与分类:监督学习标签、无监督学习标签、时序预测标签、事件驱动标签的定义与适用场景
在量化回测系统中,标签(Label)是将原始市场数据转化为可学习目标的核心桥梁。不同的回测任务和模型架构需要不同类型的标签。本章将系统定义四大类标签:监督学习标签、无监督学习标签、时序预测标签和事件驱动标签,并明确各自的适用场景与构建约束。
核心原则:标签的构建必须与回测的“未来信息禁止”原则严格对齐。任何标签在时间
t 的计算只能使用 t 时刻及之前的数据,严禁引入未来数据(Look-ahead Bias)。
4.1 监督学习标签
定义:监督学习标签是带有明确“正确答案”的标注数据,用于训练模型学习从特征到目标的映射关系。在量化回测中,通常表现为离散的分类标签或连续的回归标签。
| 子类型 | 典型标签示例 | 适用场景 | Kafka 流处理要点 |
|---|---|---|---|
| 分类标签 | 涨/跌/平(三分类);买入/卖出/持有 | 方向性预测、信号生成 | 使用滑动窗口聚合未来 N 根 K 线的收益率符号 |
| 回归标签 | 未来 N 日收益率;波动率预测值 | 收益率预测、风险度量 | 需在 Kafka Streams 中维护状态存储以对齐时间戳 |
| 排序标签 | 截面排名分位数(Rank IC) | 因子有效性评估、多空组合构建 | 需要全局窗口或 Session 窗口进行截面归一化 |
构建示例(Kafka Streams DSL):
// 以未来5分钟收益率作为回归标签
KStream<String, MarketTick> ticks = builder.stream("market.ticks");
KStream<String, LabeledTick> labeled = ticks
.groupByKey()
.windowedBy(TimeWindows.of(Duration.ofMinutes(5)).grace(Duration.ZERO))
.aggregate(
() -> new TickWindow(),
(key, tick, window) -> window.add(tick),
Materialized.<String, TickWindow, WindowStore<ByteArray, byte[]>>as("tick-window-store")
)
.toStream()
.map((windowedKey, window) -> {
double futureReturn = window.getFutureReturn(); // 窗口内最后价格 / 当前价格 - 1
return new KeyValue<>(windowedKey.key(), new LabeledTick(window.getCurrentTick(), futureReturn));
});
4.2 无监督学习标签
定义:无监督学习标签并非人工标注的“正确答案”,而是通过数据内在结构自动生成的聚类标签或异常分数。这类标签常用于市场状态划分、异常检测和特征降维。
- 聚类标签:基于 K-Means、DBSCAN 等算法将市场状态划分为“高波动震荡”、“趋势上涨”、“低波动盘整”等类别。
- 异常分数标签:基于 Isolation Forest、Autoencoder 重构误差等计算每个样本的异常程度,用于识别闪崩、操纵或数据错误。
- 降维标签:通过 PCA、t-SNE 将高维因子映射到低维空间,生成“潜在因子”作为标签。
| 标签类型 | 生成方式 | Kafka 流处理适配 | 典型回测用途 |
|---|---|---|---|
| 市场状态聚类 | 滑动窗口特征 + 离线训练模型 → 在线预测 | 使用 Kafka 模型推理(如 PMML/ONNX 集成) | 动态仓位管理、策略切换 |
| 异常检测分数 | 实时计算重构误差或局部离群因子 | Kafka Streams 中嵌入轻量级统计模型 | 风控过滤、数据清洗 |
注意:无监督标签在回测中容易产生“未来信息”陷阱。例如,使用全量历史数据训练的聚类模型,在回测时已经“看到”了未来的市场结构。正确的做法是:在回测的每个时间点,仅使用该时间点之前的数据训练或更新模型。
4.3 时序预测标签
定义:时序预测标签专门针对时间序列的序列依赖结构设计,通常以“未来一段时间的序列片段”作为预测目标,而非单一标量值。
- 多步预测标签:预测未来 N 个时间步的价格序列或收益率序列。
- 概率预测标签:预测未来序列的分布参数(如均值、方差、分位数)。
- 事件序列标签:预测未来事件发生的时刻和类型(如“未来 1 小时内出现 3 次大单买入”)。
时序标签构建示例(滑动窗口对齐):
// 假设当前时间 t,构建输入窗口 [t-20, t] 和标签窗口 [t+1, t+10]
// 使用 Kafka Streams 的 SessionWindow 或自定义 Transformer
public class SequenceLabelTransformer implements Transformer<String, Tick, KeyValue<String, SequencePair>> {
private StateStore store;
@Override
public KeyValue<String, SequencePair> transform(String key, Tick value) {
// 将当前 tick 追加到环形缓冲区
store.put(key, value);
List<Tick> history = store.get(key); // 最近 30 个 tick
if (history.size() == 30) {
List<Double> inputSeq = history.subList(0, 20).stream().map(Tick::getPrice).collect(toList());
List<Double> labelSeq = history.subList(20, 30).stream().map(Tick::getPrice).collect(toList());
return new KeyValue<>(key, new SequencePair(inputSeq, labelSeq));
}
return null;
}
}
| 标签类型 | 输出维度 | 适用模型 | Kafka 流处理挑战 |
|---|---|---|---|
| 多步预测 | N×1 向量 | LSTM、Transformer、TCN | 需要精确的时间对齐和状态存储管理 |
| 概率预测 | 分布参数(如 μ, σ) | DeepAR、Gaussian Process | 需要批量推理和模型版本管理 |
| 事件序列 | 事件类型 + 时间戳 | Hawkes Process、Seq2Seq | 需要复杂的事件时间窗口和模式匹配 |
4.4 事件驱动标签
定义:事件驱动标签以离散、非均匀时间间隔的事件为核心,标签本身即为事件的发生、属性或影响。这类标签天然适合 Kafka 的事件流架构。
- 二元事件标签:是否发生特定事件(如“财报超预期”、“高管增持”)。
- 事件影响标签:事件发生后资产价格的累计异常收益(CAR)。
- 事件序列标签:多个事件之间的因果关系或时序关系(如“新闻 A 发布后 5 分钟内出现大单 B”)。
Kafka 原生优势:事件驱动标签可以直接利用 Kafka 的 Key-Value 语义和事件时间(Event Time)语义。每个事件本身就是一个标签载体,无需额外对齐时间窗口。
| 标签类型 | 数据源 | 构建方式 | 回测注意事项 |
|---|---|---|---|
| 二元事件 | 新闻、公告、社交媒体 | NLP 分类 + 实体链接 | 避免事件泄露(如新闻发布时间戳不准确) |
| 事件影响 | 事件 + 行情 | 事件窗口内累计收益率 | 窗口长度需根据事件类型动态调整 |
| 因果事件链 | 多源事件流 | Kafka Streams 的 Join + 时间约束 | 需要处理事件乱序和延迟到达 |
4.5 四类标签对比总览
4.6 标签选择决策流程
在实际回测项目中,选择合适的标签类型需要综合考虑以下因素:
- 回测目标:是预测方向(分类)、预测幅度(回归)、还是识别市场状态(无监督)?
- 数据特性:数据是均匀采样的 tick/bar 数据(时序标签),还是非均匀的事件流(事件驱动标签)?
- 模型架构:传统 ML 模型适合监督标签;深度学习模型更适合时序标签;图神经网络适合事件因果标签。
- Kafka 流处理能力:状态存储大小、窗口类型(Tumbling/Sliding/Session)、序列化开销等。
实践建议:在 Kafka 数据流架构下,推荐优先使用事件驱动标签和时序预测标签,因为它们与 Kafka 的事件流和窗口语义天然契合。监督学习标签适合作为离线回测的基准,无监督学习标签则适合作为辅助特征或风险控制信号。