Jikipedia
第 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。

量化statsmodelsOLS线性回归哑变量回归分析

这是什么

一篇「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 用法(五步)

  1. import statsmodels.api as sm
  2. sm.OLS(endog, exog):endog = 因变量 y(t)(长度 k 的 array);exog = 自变量,是 k×(n+1) 矩阵——它不假设有常数项,所以最左一列全 1(代表 β₀)。
  3. 数据里通常没有现成的 1 列,用 sm.add_constant() 在最左侧加一列 1。
  4. 构造出的 sm.OLS(...) 只是个模型类、没算任何东西;调用 .fit() 才做回归,得到结果对象。
  5. 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 最小模板:
    1. import statsmodels.api as sm
    2. X = sm.add_constant(自变量矩阵)(无常数项时必做);
    3. model = sm.OLS(y, X)
    4. 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)至今稳定,细节以官方文档为准。

相关

更新 2026-09-06

检索知识库

按标题、类型或正文检索