3. 线性回归的经典视角:最小二乘法(OLS)及其局限性
聊到因子模型,咱们绕不开一个老朋友——最小二乘法,也就是 OLS。说实话,这玩意儿是每个做量化的人入行就得学的工具。我当年刚接触多因子模型时,第一反应就是:拿历史收益率对因子暴露跑个 OLS 不就行了?
嗯,后来发现事情没那么简单。但咱们还是得先把 OLS 讲透,才能理解它为什么不够用。
3.1 OLS 的核心思想:让误差平方和最小
OLS 的逻辑其实特别朴素。你有一堆数据点,想画一条直线穿过它们。怎么画才算「好」?
我的理解是这样的:每个数据点到直线的距离,就是预测误差。把这些误差的平方加起来,让这个总和最小——这就是 OLS 的直觉。
用数学表达就是:
minimize Σ (yᵢ - ŷᵢ)²
其中 ŷᵢ = β₀ + β₁x₁ + ... + βₖxₖ,是咱们的预测值。
你想想看,为什么用平方而不是绝对值?因为平方对大误差更敏感。说白了,OLS 特别讨厌那些偏离很远的点,会拼命把线往它们那边拉。
核心公式:OLS 的解有闭式表达式
β̂ = (XᵀX)⁻¹Xᵀy
这个公式看着简单,但背后藏着不少坑。
3.2 OLS 在因子模型中的典型用法
在量化里,我们经常用 OLS 来估计因子载荷。比如经典的 CAPM 模型:
Rᵢ - R_f = α + β(R_m - R_f) + ε
跑个 OLS 回归,β 就出来了。我刚开始做股票多因子时,就是这么干的。拿过去 60 个月的收益率,对市场因子、规模因子、价值因子跑回归,得到每只股票的因子暴露。
代码实现也很直接:
import numpy as np
import statsmodels.api as sm
# 假设 X 是因子暴露矩阵,y 是收益率
X = sm.add_constant(X) # 加截距项
model = sm.OLS(y, X)
results = model.fit()
print(results.summary())
跑完你会得到一堆统计量:R²、t 统计量、p 值、F 检验……看着挺全的,对吧?
但这里有个问题——这些统计量都建立在一些很强的假设之上。
3.3 OLS 的五大经典假设
我列个表,你看看 OLS 到底要求什么:
| 假设 | 含义 | 量化场景中常见问题 |
|---|---|---|
| 线性关系 | y 与 X 是线性关系 | 因子与收益可能非线性 |
| 误差独立 | εᵢ 之间不相关 | 时间序列数据常有自相关 |
| 同方差性 | εᵢ 的方差恒定 | 波动率聚集导致异方差 |
| 误差正态 | εᵢ ~ N(0, σ²) | 金融收益有厚尾特征 |
| 无多重共线性 | X 的列满秩 | 因子之间常高度相关 |
说实话,在真实的金融市场里,这些假设几乎一条都站不住脚。我做过一个测试:拿 A 股数据跑多因子回归,残差的自相关检验 p 值小于 0.001,异方差检验也显著——两条核心假设全崩了。
3.4 OLS 的第一个硬伤:过拟合
过拟合这事儿,我估计每个做量化的都吃过亏。OLS 在因子数量多的时候特别容易过拟合。
为什么?因为 OLS 的目标是让训练集上的误差最小。你加的因子越多,模型就越能「记住」训练数据中的噪声。结果就是:
- 训练集上 R² 高得离谱
- 一到样本外测试,表现一塌糊涂
我记得有一次,我往模型里加了 20 多个技术因子,训练集 R² 干到 0.85,心里美滋滋。结果回测时发现,样本外 R² 直接掉到 0.12——说白了,模型学到的全是历史巧合。
避坑指南:我曾经犯过一个错误,用 OLS 在 100 只股票、20 个因子上做回归。样本量才 100,参数却有 21 个(含截距)。这本质上是在用 5:1 的数据参数比做估计,结果可想而知——过拟合得一塌糊涂。
3.5 OLS 的第二个硬伤:不确定性缺失
这个点我觉得更重要,但很多人会忽略。OLS 给我们的是一组点估计——每个因子一个固定的 β 值。
但你想过没有:这个 β 真的就那么确定吗?
实际上,β 的估计是有不确定性的。OLS 虽然能给出标准误和置信区间,但这些都依赖于前面说的那些假设。一旦假设不成立,这些不确定性度量就不可靠了。
更关键的是,OLS 无法自然地告诉我们:β 可能取哪些值?每个值的概率有多大?
在量化交易中,这种不确定性信息其实特别重要。比如你判断一个因子是否有效,不能只看 β 的符号和 p 值,还得知道 β 的完整分布。如果 β 有 30% 的概率是负的,你敢重仓押注吗?
我的经验:在做因子择时的时候,我习惯把 OLS 的估计结果和贝叶斯方法做个对比。你会发现,OLS 给出的置信区间往往偏窄——因为它没有考虑参数本身的不确定性。说白了,OLS 过于「自信」了。
3.6 一个具体的例子:看看 OLS 的局限
咱们用个简单例子来说明。假设你有一个因子 X,真实的关系是:
y = 0.5x + ε, ε ~ N(0, 1)
但你只有 20 个样本点。跑 OLS 会得到什么?
import numpy as np
import statsmodels.api as sm
np.random.seed(42)
x = np.random.randn(20)
y = 0.5 * x + np.random.randn(20)
X = sm.add_constant(x)
model = sm.OLS(y, X)
results = model.fit()
print(results.params) # 估计的系数
print(results.conf_int()) # 95% 置信区间
你会发现,每次运行得到的 β 估计都不一样。有时候是 0.3,有时候是 0.7。OLS 虽然给了置信区间,但这个区间是建立在「模型正确」的前提下的。
如果真实关系是非线性的呢?如果误差有自相关呢?OLS 的置信区间就完全不准了。
3.7 小结:为什么我们需要贝叶斯视角
说了这么多 OLS 的局限,我不是要否定它。OLS 简单、快速、有闭式解,作为 baseline 非常有用。我到现在做任何因子分析,第一件事还是跑个 OLS 看看大概情况。
但它的两个硬伤——过拟合和不确定性缺失——在量化金融这种信噪比极低的领域,确实是个大问题。
你想想看,金融数据里信号本来就弱,噪声占主导。OLS 这种「把所有赌注押在一个点上」的做法,很容易被噪声带偏。
而贝叶斯方法呢?它给每个参数一个分布,而不是一个点。它能自然地引入先验知识来对抗过拟合,也能给出完整的不确定性量化。这就是为什么在因子模型中,贝叶斯线性回归越来越受欢迎。
嗯,下一节咱们就正式进入贝叶斯的世界。不过在那之前,建议你把 OLS 的代码多跑几遍,感受一下它的「自信」和「脆弱」——这样对比起来会更有感觉。
公众号:蓝海资料掘金营,微信deep3321