第 5 章 · 02 反转与价值:BAB、账面市值比、F-score


文档摘要

第 5 章 · 02 反转与价值:BAB、账面市值比、F-score 本节摘要:本节精读 quant-wiki docs/repo/static/strategies 下三个「非动量」脚本: (BAB,做多低 beta、做空高 beta,并把两腿都缩放到 beta=1)、 (HML 价值因子,按市净率 PB 排序分 5 组)、 (F-score 基本面 9 分制叠加短期反转,多「基本面强 + 短期跌」、空「基本面弱 + 短期涨」)。三者代表了「反转与价值」这一族系的三个支点:低风险异常(BAB)、价值溢价(HML)、基本面质量叠加均值回归(F-score+反转)。本节讲清每个脚本的信号构造、关键代码与陷阱,重点是 BAB 的「零 beta 组合」杠杆缩放与 F-score 的 9 分制定义。

第 5 章 · 02 反转与价值:BAB、账面市值比、F-score

本节摘要:本节精读 quant-wiki docs/repo/static/strategies 下三个「非动量」脚本:betting-against-beta-factor-in-stocks.py(BAB,做多低 beta、做空高 beta,并把两腿都缩放到 beta=1)、value-book-to-market-factor.py(HML 价值因子,按市净率 PB 排序分 5 组)、combining-fundamental-fscore-and-equity-short-term-reversals.py(F-score 基本面 9 分制叠加短期反转,多「基本面强 + 短期跌」、空「基本面弱 + 短期涨」)。三者代表了「反转与价值」这一族系的三个支点:低风险异常(BAB)、价值溢价(HML)、基本面质量叠加均值回归(F-score+反转)。本节讲清每个脚本的信号构造、关键代码与陷阱,重点是 BAB 的「零 beta 组合」杠杆缩放与 F-score 的 9 分制定义。

内容来源:quant-wiki docs/repo/static/strategies,真实 Python 策略脚本,知识结构化整理。

⚠️ 学习提示:BAB 与价值因子都属于「反 CAPM 直觉」的异象——理论上高风险应有高收益,实证上却常是低风险/低估值股票长期跑赢。理解这些异象背后的行为金融解释(彩票偏好、杠杆约束),比记回测更重要。

学习目标

阅读完本节,你应当能够:

  1. 说清 BAB(Betting Against Beta)的「零 beta 组合」构造与杠杆缩放。
  2. 复现 HML 价值因子的 PB 排序分组的工程实现。
  3. 列举 F-score 的 9 个基本面信号及其计分规则。
  4. 解释为什么 F-score 要与短期反转叠加而非单独使用。
  5. 区分价值因子(慢变量)与短期反转(快变量)的信号频率差异。

一、反转与价值:三个支点

动量是「强者恒强」,反转与价值则是「弱者回归」与「便宜者跑赢」。本节三个脚本分别从三个角度切入:

脚本 信号 经济逻辑 信号频率
BAB 个股对市场的 beta 杠杆约束 + 彩票偏好 月频
账面市值比 HML 市净率 PB 风险补偿 + 行为偏差 月频(年频更新)
F-score + 反转 9 分基本面 + 1 个月反转 质量筛选 + 均值回归 月频(季频更新 F)

💡 心法:价值因子是「慢变量」(财报每季度才更新一次),短期反转是「快变量」(每日价格波动)。F-score 把慢变量当作「方向筛选」,把快变量当作「择时触发」,这是「基本面 + 量价」叠加的经典范式。

二、BAB:看空 beta 的零成本组合

2.1 低 beta 异常

CAPM 预测「beta 越高、预期收益越高」,但 Frazzini 与 Pedersen(2014)实证发现相反:风险调整后,低 beta 股票反而跑赢高 beta 股票。原因有二:(1) 杠杆约束——很多机构(养老金、共同基金)不能加杠杆,只能通过买高 beta 股票博取高收益,压低了高 beta 股的风险补偿;(2) 彩票偏好——散户偏爱高波动「彩票型」股票,推高其价格、压低其未来收益。

2.2 beta 的计算

脚本用 1 年(12×21 日)滚动窗口,对每只股票回归其对 SPY 的收益,得到 beta:

market_returns = (market_closes[:-1] - market_closes[1:]) / market_closes[1:] stock_returns = (stock_closes[:-1] - stock_closes[1:]) / stock_closes[1:] cov = np.cov(stock_returns[::-1], market_returns[::-1])[0][1] market_variance = np.var(market_returns) beta[symbol] = cov / market_variance

注意这里用 np.cov(...)[0][1] / np.var(...) 而不是 linregress,效果等价但更直接。[::-1] 是因为 RollingWindow 的数据是倒序的(最新在前),回归前需要反转成正序。

2.3 零 beta 组合的杠杆缩放

BAB 最巧妙的设计在于「缩放到 beta=1」。脚本把股票按 beta 升序排,取最低 decile 做多、最高 decile 做空,然后:

long_mean_beta = np.mean([x[1] for x in self.long]) short_mean_beta = np.mean([x[1] for x in self.short]) self.long_lvg = 1 / long_mean_beta # 低 beta 组加杠杆 self.short_lvg = 1 / short_mean_beta # 高 beta 组去杠杆 # 杠杆上限 2 倍 self.long_lvg = min(self.leverage_cap, self.long_lvg) self.short_lvg = min(self.leverage_cap, self.short_lvg)

直觉:低 beta 组的 beta 比如 0.5,要让它达到 beta=1,就得加 2 倍杠杆;高 beta 组的 beta 比如 1.5,要让它达到 beta=1,就得只持 2/3 仓位。这样多空两腿对市场的净 beta 都为 1,组合整体「赌的不是市场方向,而是低/高 beta 的相对强弱」。

⚠️ 陷阱:杠杆缩放是 BAB 的灵魂,但也放大了对 beta 估计误差的敏感性。1 年回看窗口的 beta 估计本身噪声很大,极端值(比如 beta 接近 0)会导致 1/beta 爆炸,所以脚本用 leverage_cap = 2 兜底。复现时务必检查 beta 的极端值处理。

三、账面市值比 HML:经典价值因子

3.1 HML 的定义

HML(High Minus Low)是 Fama-French 三因子里的「价值因子」:做多高账面市值比(低 PB)的股票、做空低账面市值比(高 PB)的股票。脚本用 QC 提供的 ValuationRatios.PBRatio 作为排序键:

sorted_by_pb = sorted(top_by_market_cap, key=lambda x: x.ValuationRatios.PBRatio, reverse=False) quintile = int(len(sorted_by_pb) / 5) self.long = [i.Symbol for i in sorted_by_pb[:quintile]] # 最低 PB(最便宜) self.short = [i.Symbol for i in sorted_by_pb[-quintile:]] # 最高 PB(最贵)

3.2 几个工程细节

要素 实现
宇宙 前 3000 大市值(NYSE/AMEX/NASDAQ)
排序键 ValuationRatios.PBRatio(PB,越低越便宜)
分组 5 分位(quintile)
多空 100% 多 + 100% 空(市场中性)
再平衡 月末,但脚本里用 self.month 计数器只在每年第 12 月触发一次

⚠️ 陷阱:脚本里的 self.month 计数器逻辑(12 月才设 selection_flag = True,其余月份跳过)实际上是季度/年度再平衡的工程实现——价值因子信号变化慢(财报每季度才更新 PB),没必要每月调仓。这与动量脚本的「每月必调」形成对照,体现了信号频率与再平衡频率的匹配。

💡 迁移提示:HML 的核心是「按 PB 排序分 5 组」这一行。你可以把 PB 换成 PE、PS、PCF、股息率,得到不同的价值因子变体。Fama-French 原版还区分了「小盘价值」与「大盘价值」,脚本里简化成了全市场 HML。

四、F-score + 短期反转:基本面与量价的叠加

4.1 F-score:9 分基本面

F-score 来自 Piotroski(2000),用 9 个二元信号(每项 0 或 1 分)衡量公司的基本面强弱,总分 0-9:

类别 信号 计分条件
盈利能力 ROA ROA > 0
经营现金流 CFO CFO > 0
ROA 变化 ROA 同比上升
应计项目 CFO > ROA(盈利质量)
财务状况 杠杆 长期负债/总资产同比下降
流动性 流动比率同比上升
股本发行 未发行新股
经营效率 毛利率 毛利率同比上升
资产周转率 总资产周转率同比上升

脚本用 StockData 类缓存「去年同期」的指标做同比对比,逻辑严谨。最终把公司分为「基本面强」(F-score ≥ 7)、「中」(4-6)、「弱」(≤ 3)三档。

4.2 叠加短期反转

F-score 单独作为选股信号太弱(财报每季度才更新一次,变化慢),所以脚本叠加了 1 个月的短期反转(过去 21 日收益)作为触发器:

# 多: 基本面强 + 短期跌(价值反弹) self.long = [x[0] for x in score_performance.items() if x[1][0] >= 7 and x[1][1] < 0] # 空: 基本面弱 + 短期涨(泡沫回归) self.short = [x[0] for x in score_performance.items() if x[1][0] <= 3 and x[1][1] > 0]

这一叠加体现了「基本面定方向、量价定时点」的范式:只在「基本面好但短期被错杀」的股票上做多,只在「基本面差但短期被炒作」的股票上做空。

4.3 数据过滤的严格性

这个脚本的 FineSelectionFunction 有一长串数据非空过滤(ROA、CFO、长期负债、总资产、流动比率、股本数、毛利率、营收等),任何一项缺失就剔除该股。这反映了基本面策略的痛点——财报字段缺失很常见,不严格过滤会导致 F-score 计算错误。

💡 心法:F-score + 反转的组合,本质是「质量因子 × 反转因子」的交互项。交互项的好处是降低了单纯反转的「价值陷阱」风险(基本面烂的股票短期跌可能是永久性下跌,不该做多)。

五、三个脚本的对照与启示

维度 BAB HML F-score+反转
信号类型 风险因子(beta) 价值因子(PB) 质量×反转
信号频率 月频 年频 月频(季频更新 F)
关键工程 零 beta 杠杆缩放 PB 排序分 5 组 9 分计分 + 同比对比
主要陷阱 beta 估计噪声 PB 极端值 财报字段缺失
经济逻辑 杠杆约束 风险补偿 质量 + 均值回归

⚠️ 共通陷阱:三个脚本都依赖 QC 的 FineFundamental 数据。复现到自己的框架时,财报数据的「时点性」(point-in-time)是最大坑——你不能用财报发布日之后才更新的数据回测当时的信号,否则会引入前视偏差。BAB 脚本因为只用价格数据,反而最容易复现。

本节要点回顾

  1. BAB:beta 升序排序,多低 beta / 空高 beta,两腿都缩放到 beta=1(杠杆 = 1/组内平均 beta),杠杆上限 2 倍。
  2. HML:按 PB 升序排序分 5 组,多最低 / 空最高,年频再平衡,100% 多 + 100% 空。
  3. F-score:9 个二元基本面信号(盈利/财务/经营效率),总分 0-9,≥7 为强、≤3 为弱。
  4. 叠加范式:F-score 定方向(质量),短期反转定时点(量价),交互项降低价值陷阱风险。
  5. 信号频率匹配:慢变量(价值、基本面)低频再平衡,快变量(反转、动量)高频再平衡。
  6. 核心心法:反转与价值是「反 CAPM 直觉」的异象,经济逻辑(杠杆约束、彩票偏好、风险补偿)比回测数字更值得记住。

下一节,我们看统计套利的核心——配对交易与 ETF 配对:协整、价差均值回归、配对切换。


发布者: 作者: 灏天文库 转发
评论区 (0)
U