第 32 篇
Statsmodels 统计包之 OLS 回归
量化课堂第 32 篇(postId=1786,作者 Haozun、肖睿,编辑宏观经济算命师,难度入门、深度 level-0,2016-07-13 上线,v1.2 于 2016-09-09 修正公式)。一篇纯工具文:教你在 Python(statsmodels)里跑最常用的 OLS 回归——怎么喂数据、常数项从哪来、怎么取系数与摘要、高次项与哑变量怎么做,最后用「上证/深证日收益」做一个真数据演示。它是第 15 篇(协整残差回归)、第 19–21 篇(β 与 α 回归)背后的通用建模工具。素材见 raw/collections/jq-quant-classroom/32-32-statsmodels统计包之ols回归md.md。
这是什么
一篇「statsmodels 之 OLS 回归」的函数说明书式教程。它不推导统计理论(前置要求:已会回归分析 level-0),只讲 API 怎么用、每一步为什么这样写。核心口径:statsmodels.OLS 默认不含常数项,必须自己用 sm.add_constant() 加一列 1;调用 fit() 才真正计算;params 取系数、summary() 看摘要、fittedvalues 取拟合值。
核心要点
OLS 在做什么
- 模型:Y = β₀ + β₁X₁ + … + βₙXₙ + ε,有 k 组数据 (y(t), x₁(t), …, xₙ(t))。
- OLS 估计系数 b₀…bₙ,使误差平方和 Σ(y(t) − b₀ − b₁x₁(t) − … − bₙxₙ(t))² 最小。
- statsmodels 定位:在计量的简便性上远不及 Stata 等软件;优点是能与 Python 生态(NumPy、Pandas)有效结合、提高工作效率。
API 用法(五步)
import statsmodels.api as sm。sm.OLS(endog, exog):endog = 因变量 y(t)(长度 k 的 array);exog = 自变量,是 k×(n+1) 矩阵——它不假设有常数项,所以最左一列全 1(代表 β₀)。- 数据里通常没有现成的 1 列,用
sm.add_constant()在最左侧加一列 1。 - 构造出的
sm.OLS(...)只是个模型类、没算任何东西;调用.fit()才做回归,得到结果对象。 results.params取系数 b₀…bₙ;results.summary()打印完整摘要(表中间偏下的 coef 列是系数);results.fittedvalues取拟合的 y。
三个演示
- 一元线性(Y = 1 + 10X):nsample=100;x = np.linspace(0,10,100);X = sm.add_constant(x);beta=[1,10];y = np.dot(X,beta) + 正态噪声。结果 params ≈ [1.045, 9.972],很接近真实 [1,10]。
- 高次多项式(Y = 1 + 0.1X + 10X²):关键思想——Y 对 X 非线性没关系,只要知道所有幂次,把 X、X² 当作两个自变量(np.column_stack((x, x**2)))就还是线性回归(对参数线性)。结果 params ≈ [0.951, 0.102, 9.9998]。反例:若真实关系里有 X^2.5 而你不知道,线性回归就拟合不准。
- 哑变量:分类变量(性别/婚姻/行业)只有有限取值、本身构不成线性关系,映射到「{0,1} 向量」后就能线性表达。d 种取值 → d 元组,所在类别位置为 1(a→(1,0,0,0)…)。
sm.categorical(groups, drop=True)直接把类别转成哑变量。示例:Y = 10 + X + Z₁ + 3Z₂ + 8Z₃,nsample=50(前 20 个 a、20–39 个 b、后 10 个 c),beta=[10,1,1,3,8]。
真数据演示:上证对深证的日收益
- 假设 y(深证成指日收益率)= β₀ + β₁·x(上证指数日收益率)。
get_price(['000001.XSHG','399001.XSHE'], start_date='2015-01-01', end_date='2016-01-01', frequency='daily', fields=['close'])['close']取一年收盘价。- 收益率逐个算:x_pct.append(x_price[i]/x_price[i-1]−1)。
sm.add_constant(x)后sm.OLS(y,X).fit()→ 结果 y = 0.002 + 0.9991x,作者说「合情合理,四舍五入就是 y=x」——大盘与深市日收益高度同步、斜率接近 1。
结语口径
- 线性回归应用极广;量化课堂应用类策略里「相当多」用到线性回归,未来会在相关应用文里挂回本文链接,形成体系。
机制 / 论证
- 为什么 exog 要加一列 1:statsmodels 不自动假设常数项;模型 Y = β₀X₀ + β₁X₁ + … 里令 x₀(t)=1,β₀ 才有落点。漏掉 add_constant 会把常数项并进误差、系数整体偏移——这是本工具最常见的坑。
- 为什么「高次多项式」仍叫线性回归:线性回归的「线性」指对参数 β 线性,不是对变量 X 线性。把 X² 当新变量 X₂,Y 与 (X, X², …) 就是高元线性关系;前提是幂次清单已知。
- 为什么哑变量是「并行影响因素」不是「选择器」:哑变量与连续变量同时进同一回归,一次 fit 完成;初学者易误以为它在「选段」,实际图中三段式台阶是一次高维回归投影到平面上的结果,不是分了 3 段各回归一次。
- 为什么加噪声再回归:三个演示都用「真实系数生成 y + 正态噪声」再回归——回归结果逼近真实系数,说明方法能还原生成关系(params 接近 beta 就是证据)。
可操作
- statsmodels OLS 最小模板:
import statsmodels.api as sm;X = sm.add_constant(自变量矩阵)(无常数项时必做);model = sm.OLS(y, X);res = model.fit();res.params(系数)、res.summary()(表)、res.fittedvalues(拟合值)。
- 哑变量:
sm.categorical(groups, drop=True);drop=True 表示去掉原始类别取值列。输出 k×d(drop=False 则 k×(d+1))。 - 高次/交互项:
X = np.column_stack((x, x**2, x1*x2))手动造列即可,只要幂次已知。 - 本量化课堂系列里 OLS 的三个用途:协整残差回归(第 15 篇 lnF₂=A+B·lnF₁)、CAPM β 与 α 回归(第 19–21 篇)、以及对冲比率的估计。
- get_price 数据口径:frequency='daily'、fields=['close'],返回多股票 DataFrame(研究/策略两用,见 聚宽行情与财务数据获取 API)。
术语
- OLS:ordinary least square,普通最小二乘——让误差平方和最小的系数估计。
- endog / exog:因变量 / 自变量(explanatory variable)。
- 常数项(截距 β₀):模型里不随 X 变的基线项。
- 拟合值 fittedvalues:回归线(超平面)给每个样本的预测 y。
- 哑变量(dummy variable):把分类变量转成的 {0,1} 指示向量。
- 多项式回归:把 X 的各次幂当多个自变量做的(参数)线性回归。
不确定 / 待验证
- 本文是 API 教程,不含推断统计(系数显著性、p 值、置信区间)、多重共线性、稳健标准误等内容——summary() 输出里的统计量本文没解释 [需要验证]。
- 文中错误拼写照录不纠(「matplotlib.pyploft」「gradiet」等),不影响语义。
- 一元例子的随机噪声没设 seed,数字每次运行略不同;文中给的 params ≈ [1.0451, 9.9724] 是某次运行结果。
- get_price 一年区间取的是 2015-01-01~2016-01-01(含 2015 年股灾),「y≈x」是这一年的样本结论,不是跨期普适规律。
- statsmodels 版本语境为 2016–2017;API 主流程(add_constant/OLS/fit/params)至今稳定,细节以官方文档为准。
相关
- OLS 线性回归(最小二乘建模) — OLS 共享概念页(本篇 API + 量化场景用途的提炼)
- 股指期货跨期套利策略 — 协整残差回归的直接应用(第 15 篇,postId=4296)
- 协整(非平稳序列的平稳线性组合) — 用回归残差检验协整的完整思路(第 31 篇 + 15 篇)
- 聚宽行情与财务数据获取 API — get_price 等聚宽取数 API(本篇演示用)
- CAPM+APT 多因子模型 — 用回归做因子对历史 α 的建模(第 21 篇)
- 聚宽量化课堂(低频量化策略 43 篇) — 量化课堂 43 篇总览
更新 2026-09-06