1. 入坑前先看清:随机森林在量化交易中解决的到底是什么问题
我在量化交易里认真使用随机森林,是从一次很失败的预测开始的。当时我跟着网上的教程用各种机器学习模型去预测“明天涨还是跌”,回测曲线画出来相当漂亮,实盘却稳定亏损,手续费倒是贡献了不少。复盘了很久,最核心的问题不是模型选错了,而是我把一个本质上属于“市场结构状态识别”的问题,硬做成了“价格方向预测”。后来我换了个思路,让随机森林先去判断市场当前处在什么结构里——是趋势行情、震荡行情,还是波动率正在扩张——再由交易规则决定怎么做,这才真正体会到机器学习在量化里的定位。这篇文章把我用随机森林做市场结构预测的完整流程、代码结构和踩坑记录都整理出来,适合有一定Python基础、被“AI预测股价”忽悠过但还想认真把机器学习用在交易上的读者。
1.1 为什么“预测涨跌”这条路大多走不通
很多刚接触量化交易的人,第一步就是想用机器学习直接预测未来N根K线是上涨还是下跌。这个想法很自然,但金融时序数据有个残酷特点:价格变化里真正可以被提前预测的成分极低,绝大多数波动来自噪音。如果把日线收益率的信噪比量化一下,你会发现大部分品种的日收益中,可解释的方差占比经常只是个位数。也就是说,模型要在一片巨大的随机噪声里去抓那么一点点规律,还要面对市场参与者结构变化、政策冲击、突发事件等因素,很容易把噪声当成信号学进参数里。
所以你在回测时会看到一种典型现象:训练集上准确率轻松做到百分之七八十,一到样本外就掉到五十附近,跟抛硬币差不多。随机森林作为一种有监督模型,并不会天然绕开这个问题。如果任务本身定义得太“紧”——直接预测方向——即使换了更复杂的深度学习结构,结果也差不了太多,只是换一种方式过拟合而已。
1.2 市场结构预测:一套更接地气的任务定义
方向上难预测,不代表市场完全没有结构。趋势跟踪策略能赚钱,本质上就是在赚“市场存在持续性结构”的钱;波动率策略能赚钱,靠的是波动聚集效应。也就是说,价格未来走哪条路难以预测,但市场当前处于什么“运行模式”,有更强的自相关性和可学习性。
我提到的“市场结构预测”,通俗讲就是让模型回答几个问题:当前行情大概率处于趋势状态还是震荡状态?如果是趋势,是上涨趋势还是下跌趋势?未来一段时间波动率会维持在低位还是明显放大?这些问题判断错了,后果没有方向预测那么严重,容忍度更高;判断对了,却能直接改进交易逻辑的入场、过滤和仓位管理。用随机森林处理这类状态识别和区间预测任务,比硬predict涨跌靠谱得多。
1.3 为什么选随机森林而不是神经网络
从机器学习模型选型看,量化场景有几个现实约束:数据量通常有限,单品种日线数据哪怕看十年也就两千多根K线;特征之间往往存在较强的非线性关系;交易逻辑要求模型输出在一定程度上可解释。随机森林在这几个维度上都相对省心。
我并不是说神经网络不能用,而是说在起步阶段,先用随机森林把问题定义、特征工程、验证框架跑通,远比直接上深度网络靠谱。随机森林对数据尺度不敏感,不需要做复杂的归一化;能自动处理特征交互;有袋外误差和特征重要性做辅助诊断;模型输出概率也比较稳定。对刚入门的交易者来说,这些特性都是加分项。等后面你需要处理非结构化数据或者超大规模特征工程时,再引入深度学习也不迟。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 任务定义与数据准备:先解决“预测什么”再谈“怎么预测”
很多人拿到行情数据后第一件事就是写代码,四处找特征、试模型。我的习惯相反。我会先花大量时间把“预测目标”想清楚:模型到底要输出一个什么变量?这个变量怎么定义才算可交易?如果把这一步做错,后面所有代码都是浪费时间。
2.1 把市场结构拆成哪些可计算的状态
市场结构是个很抽象的词,落到编程层面必须变成可计算的类别或数值。我在实际项目中一般拆成两类问题:
一类是方向性结构,标签可能是“上涨趋势、下跌趋势、震荡区间”。这类结果适合直接指导趋势策略开多还是开空,或者决定要不要过滤掉无效信号。
另一类是波动性结构,标签可能是“高波动、低波动、波动放大中”。这类结果不适合告诉你方向,但可以指导仓位管理。因为无论做多还是做空,如果预测未来波动会显著放大,单位头寸的风险都会增加,需要提前调低仓位。
还有一个容易被忽略的状态是“结构切变”,也就是从震荡切换到趋势,或从趋势切换到震荡的临界区域。这类状态样本量少,但价值最大,我会单独构造特征进行监测。
2.2 标签构造:没有人工标注,就用滚动窗口“自动切片”
因为金融数据没有现成的人工标签,不像图像分类有“猫”和“狗”,我们需要自己设计规则去给历史行情标注结构状态。最基本的方法是拿“未来一段时间”的行情表现回推当前状态。
比如我用日线数据做实验时,会设定一个结构判断周期,常见的是20根K线。标签构造的核心思路是:用未来N根K线的涨跌幅和真实波幅来判断这段行情属于趋势还是震荡。
下面我给出一个可行的标签构造逻辑,它不是唯一方案,但你可以在此基础上调整阈值:
python复制import numpy as np
import pandas as pd
def label_market_structure(df, horizon=20, trend_threshold=1.0):
# 未来horizon根K线的收益率
df['fwd_ret'] = df['close'].shift(-horizon) / df['close'] - 1.0
# 用平均真实波幅ATR做标准化,更能适应不同
