
用 Python 揭秘均值回归策略:你的收益从何而来?
2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含 500 篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
最近读到一篇很有意思的量化实验文章,作者从一则"限制夜间配送"的新闻出发,最终用 SEC 10-K 财报文本挖掘 + 图论分析,构建了一套能跑赢"便宜股策略"超过 25 个百分点的投资模型。
作为 Python 学习者,这个项目几乎涵盖了我们想练手的所有技能:网络爬虫、文本挖掘、图论算法(NetworkX)、数据可视化(Matplotlib)、金融数据分析(Pandas + yfinance)。
今天就带大家拆解这个项目的核心思路,并附上可运行的 Python 代码案例。
作者提出了一个关键问题:一家公司真正的"技术潜力"该如何量化?
答案是:看它在多少其他公司的官方财报(10-K)里被提到为"供应商""合作伙伴""核心基础设施"。被提及越多,说明它越是整个生态系统离不开的"卡脖子"环节。
作者把这个指标定义为 Bottleneck Score(瓶颈分数),公式如下:
Bottleneck_Score = (归一化入度 + 0.1) × (相关性 + 1) / (P/E 比率 / 10)
简单理解:结构性垄断地位 ÷ 估值贵贱,本质是 GARP(合理价格成长)策略的升级版。
整个数据管道分为 3 步:
import requests
import time
# SEC EDGAR 强制要求带 User-Agent,否则会被防火墙拦截
headers = {
"User-Agent": "Your Name your_email@example.com"
}
def fetch_10k_text(cik: str) -> str:
"""
根据公司 CIK 编号获取最新 10-K 财报文本
cik: 公司在 SEC 的唯一标识,需补齐 10 位
"""
cik_padded = cik.zfill(10)
# 第一步:获取公司提交记录
url = f"https://data.sec.gov/submissions/CIK{cik_padded}.json"
resp = requests.get(url, headers=headers)
data = resp.json()
# 第二步:筛选 10-K 类型的文件
recent = data["filings"]["recent"]
for form, accession in zip(recent["form"], recent["accessionNumber"]):
if form == "10-K":
# 拼接出原始文本的 URL
acc_clean = accession.replace("-", "")
doc_url = f"https://www.sec.gov/Archives/edgar/data/{int(cik)}/{acc_clean}/"
return doc_url
return None
# 示例:获取微软(CIK = 789019)的 10-K 链接
msft_url = fetch_10k_text("789019")
print(f"微软 10-K 文档地址:{msft_url}")
time.sleep(0.5) # SEC 限制每秒最多 10 次请求,务必加延迟import re
def extract_supply_relations(text: str, target_companies: list, keywords: list) -> list:
"""
从 10-K 文本中提取供应链关系
text: 财报全文
target_companies: 目标公司名称列表,比如 ["Microsoft", "NVIDIA"]
keywords: 供应链关键词,比如 ["customer", "supplier", "partner"]
"""
edges = [] # 存储 (源公司, 目标公司) 关系对
# 把文本统一转小写,方便匹配
text_lower = text.lower()
for keyword in keywords:
# 找出所有关键词出现的位置
for match in re.finditer(rf"\b{keyword}\b", text_lower):
start = match.end()
# 取关键词后面 150 字符作为搜索窗口
window = text_lower[start:start + 150]
# 在窗口内查找目标公司
for company in target_companies:
if company.lower() in window:
edges.append(company)
return edges
# 示例文本(实际中是几万字的 10-K 全文)
sample_text = """
Our key customers include Microsoft and Apple. We also partner
with NVIDIA for GPU infrastructure to support our cloud platform.
"""
keywords = ["customer", "partner", "supplier"]
targets = ["Microsoft", "Apple", "NVIDIA", "Google"]
relations = extract_supply_relations(sample_text, targets, keywords)
print(f"提取到的关系:{relations}")
# 输出:['Microsoft', 'Apple', 'NVIDIA']import networkx as nx
import pandas as pd
# 假设我们已经收集到的边数据(源公司 → 目标公司)
edges = [
("AAPL", "MSFT"), ("GOOGL", "MSFT"), ("META", "MSFT"),
("AAPL", "NVDA"), ("MSFT", "NVDA"), ("META", "NVDA"),
("MSFT", "PTC"), ("ORCL", "PTC"),
]
# 构建有向图
G = nx.DiGraph()
G.add_edges_from(edges)
# 计算入度(被多少家公司提及)
in_degree = dict(G.in_degree())
print("入度统计(被提及次数):")
for ticker, degree in sorted(in_degree.items(), key=lambda x: -x[1]):
print(f" {ticker}: {degree}")
# 计算瓶颈分数(简化版)
def bottleneck_score(in_deg: int, correlation: float, pe_ratio: float) -> float:
"""
in_deg: 入度
correlation: 与大盘 CapEx 的相关性
pe_ratio: 市盈率
"""
# 归一化入度(这里简单除以最大值)
max_deg = max(in_degree.values())
norm_in = in_deg / max_deg if max_deg > 0 else 0
return (norm_in + 0.1) * (correlation + 1) / (pe_ratio / 10)
# 模拟计算 MSFT 的瓶颈分数
score = bottleneck_score(in_deg=11, correlation=0.965, pe_ratio=21.80)
print(f"\nMSFT 瓶颈分数:{score:.4f}")作者用 2025 年 5 月的数据选出 Top 6 股票(HPE、MSFT、PTC、AMAT、QCOM、AAPL),与"最便宜的 6 只 IT 股"基准对比一年回测:
| 超额 Alpha | +25.47% |
最关键的洞察是 3 个阶段:
networkx 库不到 100 行代码就能跑出投资逻辑time.sleep()这个项目最妙的地方在于:它把"技术潜力"这种玄学概念,变成了一个可计算的网络指标。
对我们 Python 学习者来说,它示范了一套完整的数据科学流水线:
如果你正在学 Python,强烈建议把这个项目当作综合练手题,跑一遍下来收获绝对超过 10 个 leetcode。
记住作者的核心结论:忽略账面噪音,挖掘 SEC 披露中的隐藏网络,远离便宜的垂死企业,把资金部署到真实需求集中的地方。
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!
好文推荐
1. 用 Python 打造股票预测系统:Transformer 模型教程(一)
2. 用 Python 打造股票预测系统:Transformer 模型教程(二)
3. 用 Python 打造股票预测系统:Transformer 模型教程(三)
4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)
6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用
9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解
好书推荐