LLM alpha 与非结构化金融数据挖掘
Read in English读懂管理层说了什么——以及市场遗忘得有多快
🔊 收听本文(中文朗读)
⚠️ 现实检验
Two Sigma Research 与 Point72 旗下的 Cubist Systematic Strategies 会在 SEC 文件和电话会议记录发布后几分钟内,对全市场范围的文本跑一遍大语言模型(LLM)推理,并与它们用十年时间积累的专有历史语调基准做交叉比对。 你没有它们的基础设施、它们的延迟水平,也没有它们标注好的训练数据。本文要讲的是:市场为文本语调定价这件事在结构上到底成立在哪里,以及散户规模的版本真正能捕捉到什么:
- 现成的 FinBERT 模型可以免费获取,在标准基准上的情绪打分几乎不输给专有微调模型
- 财报电话会的问答环节没有讲稿,结构上比准备好的发言信息密度更高——这是公开有据可查的,不是什么内部秘密
- 情绪的预测力衰减很快——大部分在几天内就消失了,这决定了散户交易者必须换一种方式来落地这个信号
- 我们是把已公开的语调提取框架改造成适合更慢的散户执行周期,而不是去复制毫秒级延迟的机构流水线
🎯 你将学到什么
每个季度都有数千页的 10-K、10-Q 和财报电话会议记录涌入市场——在下一个数据点到来之前,其中大部分从来没有被人完整读过。你将学到:
- 为什么非结构化文本被定价不足: 申报文件和会议记录的数量,比分析师的阅读能力高出好几个数量级
- 准备发言与问答环节对比: 为什么电话会中照稿念的部分,信号含量远低于没有讲稿的分析师问答
- 情绪衰减半衰期: 为什么语调信号的预测价值会在数小时到数天内崩塌,以及这对入场时机意味着什么
- 卫星与网络抓取信号: 另类数据如何印证或反驳管理层的说法
- Python 实现: 一条完整的基于 FinBERT 的流水线——文件摄取、章节切分、情绪打分、按衰减加权构建信号
- 现实的散户落地方式: 散户的延迟究竟落在衰减曲线的哪一段,以及如何围绕这个现实而不是对抗它来搭建策略
目录
非结构化数据难题
文本多到没人读得完
每家美国上市公司每年申报一份 10-K、每季度申报一份 10-Q,多数大盘股还会在发布当天或一两天内召开财报电话会。 放到罗素 3000 指数的成分股上,这意味着每个财报季都有数千份文件和会议记录在相互重叠的时间窗口里落地——每一份都是几十页到几百页。无论规模多大的研究部门,都不可能在市场对数字做出反应之前把这些内容全部细读一遍。
Two Sigma Research 和 Point72 旗下的 Cubist Systematic Strategies 都公开谈过它们如何把这看作一种结构性的低效: 文本是公开的,但真正制造出机会的,是认真读完它的边际成本——对每一只标的、每一个季度、都在发布后几分钟内完成。 LLM 不会疲劳,不会跳过无聊的段落,给当天第四十份文件打分时和给第一份时一样仔细。
"价值不在于读到别人没读过的文本,而在于把全部文本都读一遍,标准始终如一,速度快到任何人工研究流程都追不上。"
——对 Two Sigma Research 与 Point72/Cubist Systematic Strategies 就 NLP 驱动的另类数据研究发表的公开评论的概括性描述
变化在哪里:LLM 与传统 NLP 的差别
词袋模型和基于词典的情绪打分(比如 Loughran-McDonald 词表)从 2000 年代起就用在学术金融研究里,但它们很粗糙——分不出"不令人失望"和"令人失望"。 在金融文本上微调过的 Transformer 模型(FinBERT 及其后继者)能理解否定、模糊措辞和上下文,这是数词频的方法永远做不到的。机构交易台如今大规模跑的,正是这一项具体的能力升级。
传统方法与基于 LLM 的语调打分对比
| 方法 | 典型失效方式 | LLM 的处理方式 |
|---|---|---|
| 词典词频统计 | "这不是一个令人失望的季度"被打成负面(因为命中了"令人失望") | 正确读出否定,判为正面/中性 |
| 词典词频统计 | 识别不出模糊措辞("我们保持谨慎乐观,不过……") | 把模糊措辞与明确表态放在一起权衡 |
| 词典词频统计 | 不管位置和上下文,所有句子一视同仁 | 注意力机制会在整段范围内权衡上下文 |
关键洞察: 这不是准确率上的边际改善——在真正含糊的公司措辞上(而公司措辞大部分都是含糊的),这是"噪音代理指标"和"可用信号"之间的差别。
准备发言与问答环节:信号藏在哪里
照稿念的部分能告诉你的比你以为的少
财报电话会开头的"准备发言"部分是写好的,经过法务和投资者关系部门审核,在 CEO 和 CFO 开口之前就演练过了。 无论这个季度实际表现如何,它都被打磨得听起来自信、口径统一。关于财报电话会语言学的学术研究(延续 2010 年代初以来会计与金融文献中流行起来的工作)反复发现, 没有讲稿的分析师问答环节所携带的增量信息要多得多 相比准备好的部分——因为高管无法为自己控制不了的问题事先写好答案。
准备发言与问答环节:结构性差异
| 维度 | 准备发言 | 分析师问答 |
|---|---|---|
| 撰写方式 | 事先写好并经法务审核 | 现场即兴回答,没有讲稿 |
| 主导权 | 公司完全掌控话题和叙述框架 | 分析师把话题引向他们担心的方向 |
| 模糊措辞密度 | 较低——被审核流程抹平了 | 较高——迟疑、口头禅、回避在现场更难掩饰 |
| 对语调模型的信噪比 | 增量信号较低 | 增量信号较高 |
关键洞察: 把整份会议记录当成不加区分的一整块来打分,等于用最弱的信号稀释最强的信号。打分之前先把记录切分成章节不是可选项——这是整条流水线里杠杆率最高的一步。
看变化量,而不只是看绝对水平
单场电话会的语调绝对分数,远不如它相对于同一管理团队自身历史基准的差值、以及相对于同一场会议中准备发言语调的差值来得重要。 自信的准备发言与充满模糊措辞的问答回答之间出现巨大的负向落差——有时被称为"语调背离"——比单独读任何一个环节都更具体:它说明管理层对写好的叙事很自在,但在没有讲稿的追问下明显没那么自在地为它辩护。
⚠️ 行业基准和管理层说话风格基准很重要
有些高管天生就比别人说话更留余地,有些行业(比如正在等临床数据的生物科技公司)不管基本面健康与否,模糊措辞在结构上就是更多。如果没有针对具体公司和具体行业的基准,单纯的横截面语调分数会把天性谨慎的发言者季季都误判为看空。
10-Q/10-K 语调提取:MD&A 与风险因素
信号在申报文件中集中在哪里
10-K 或 10-Q 大部分是套话——会计披露、标准法律措辞、SEC 规则要求的条目编号。 机构 NLP 研究始终盯住的是两个章节: 管理层讨论与分析(MD&A),这里管理层用自己的话解释业绩;以及 风险因素 章节,这里逐年新增、删除和改写的内容会被当成独立于情绪分数之外的另一种信号来跟踪。
值得打分的申报文件章节
| 章节 | 它揭示什么 | 信号类型 |
|---|---|---|
| MD&A | 管理层用自己的叙述解释业绩 | 语调/情绪分数 |
| 风险因素(新增/删除) | 新披露的风险,或被悄悄拿掉的风险 | 结构性变化检测,而非情绪 |
| 风险因素(改写) | 既有风险的措辞被软化或加重 | 编辑距离/相似度差值 |
关键洞察: 一条全新的风险因素首次出现——尤其是关于流动性、客户集中度或债务契约的——往往比任何情绪分数都更可执行,因为它是一次披露事件,而不是一种解读。
同比相似度本身就是一个信号
用文本相似度指标把本季度的 MD&A 和风险因素文本与去年同期的申报文件做比对(对句向量算余弦相似度是散户可及的标准做法),能暴露出单看情绪分数会漏掉的实质性变化。 一份文本上与去年相似度超过 95%(含套话在内)的申报文件,说明管理层觉得没必要多说什么新东西——这本身就有信息含量,尤其是在经营层面确实发生了变化的季度。
情绪衰减曲线:半衰期难题
为什么"判断正确"的情绪还不够
一个语调信号方向可以是对的,但如果等你能动手时它已经过期,那它对交易毫无价值。 关于财报电话会和申报文件情绪的公开学术与业界研究一致发现,市场对文本语调的价格反应是前置的——大部分增量信息在发布后数小时(而不是数天)内就被吸收进价格,之后留下一条又长又薄的残余漂移尾巴,在随后几个交易日里逐渐消退。
情绪信号衰减曲线示意
| 距发布时间 | 已兑现价格影响占比(约) | 实际含义 |
|---|---|---|
| 0-3 小时(电话会现场/当日申报) | ~40-55% | 低延迟的机构交易台吃掉了这个窗口的大部分 |
| 3 小时至 1 个交易日 | 累计约 65-80% | 卖方研报和分析师的初步反应跟上来 |
| 1-3 天 | 累计约 85-95% | 较慢的资金调仓带来的剩余漂移 |
| 3 天以上 | 接近 100%,只剩很薄的残余尾巴 | 信号基本被消耗殆尽;剩下的部分由噪音主导 |
关键洞察: 常被引用的原始情绪信号"半衰期"——也就是其最终价格影响兑现一半所需的时间——对于大盘、流动性好、覆盖度高的标的落在几小时到大约一天的区间;对于市值较小、覆盖较少、分析师跟进较慢的标的,则可能拉长到区间中"数天"那一端。这是从公开的市场微观结构和事件研究文献中得出的结构性估计,不是某只基金披露的具体数字,并且会随标的、行业和市场环境而变。
把衰减建模成指数函数
把衰减曲线落地的标准做法,是把信号的可用权重当成"距发布经过时间"的指数函数,这样交易系统就能决定对一个"变旧但还没死"的信号还该给多少信心,而不是把它当成非黑即白的二选一(可交易/不可交易):
weight(t) = 2^(-t / half_life)
其中:
t = 距申报文件/电话会发布已经过的小时数
half_life = 信号损失一半价值所需的估计小时数
(示意:3-24 小时,取决于标的/流动性)
⚠️ 半衰期不是一个放之四海皆准的常数
给所有代码套用同一个半衰期是常见的建模捷径,代价是实实在在的准确率。大盘、覆盖度高的标的定价很快,因为盯着它的资金更多;分析师覆盖稀薄的中小盘股则能把可用信号保留更久,仅仅因为快速读完申报文件的参与者更少。生产级系统应当按流动性/覆盖度分档分别估计半衰期,而不是全市场套一个数字。
卫星与网络抓取的印证信号
当文本语调与现实世界数据吻合时,它更有力
Two Sigma Research 和 Point72/Cubist 都谈到过使用另类数据——卫星影像、抓取来的网页价格和招聘信息、应用使用遥测数据——它们不是独立信号,而是用来印证或反驳语调模型从文本中提取出的结论。 一段自信的 MD&A 加上与之吻合的卫星停车场车流数据或招聘岗位增长,合起来比任何一方单独出现都更强;而一段自信的 MD&A 配上相互矛盾的现实世界数据,本身也是信息——它标记出一份语调可能与现实不符的申报文件。
另类数据印证的类别
| 数据类型 | 它代表什么 | 印证/反驳的对象 |
|---|---|---|
| 卫星停车场/客流量计数 | 零售和餐饮的到店客流趋势 | 同店销售相关表述的语调 |
| 招聘信息抓取(招聘量、岗位结构) | 扩张还是收缩的意图 | MD&A 中关于增长或冻结招聘的措辞 |
| 抓取的电商价格/库存数据 | 需求和打折促销的压力 | 关于毛利率和定价权的表述 |
| 应用商店评论数量/情绪、下载排名 | 消费产品的用户参与趋势 | 关于用户增长表述的语调 |
关键洞察: 这些另类信号单拎出来没有一个是可靠的——卫星覆盖时有时无,抓取脚本会失效,样本量相对公司真实的经营版图来说很小。它们的价值在于叠加在文本语调之上做交叉印证,而不是取而代之。
⚠️ 散户确实能拿到另类数据,但很有限
机构交易台购买的是覆盖数千个地点和 SKU 的完整卫星与网络抓取数据面板。散户能拿到的对应版本是存在的(有些卫星影像供应商提供有限的免费额度;招聘信息和应用排名数据可以小规模抓取),但覆盖的标的只是很小一部分,更新频率也低得多。把散户能拿到的另类数据当成对少数几只你本来就密切跟踪的标的做抽查印证的工具——而不是一个可规模化的独立信号。
Python 实现:完整的 NLP 打分流水线
完整实现: 会议记录/申报文件摄取、章节切分(准备发言与问答、MD&A 与风险因素)、FinBERT 情绪打分、同比相似度、按衰减加权的信号汇总。
完整 Python 代码
"""
LLM alpha:非结构化金融数据挖掘流水线
面向散户改造的 FinBERT 语调提取,用于申报文件与财报电话会
作者:Plan My Retire
日期:2026 年 3 月
"""
import re
import numpy as np
import pandas as pd
from datetime import datetime
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch
from sklearn.metrics.pairwise import cosine_similarity
from sentence_transformers import SentenceTransformer
class FinancialTextScorer:
"""
使用 FinBERT 系列模型为金融文本(会议记录、申报文件)打情绪分,
并按章节做加权。
"""
def __init__(self, model_name="ProsusAI/finbert"):
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModelForSequenceClassification.from_pretrained(model_name)
self.model.eval()
self.embedder = SentenceTransformer("all-MiniLM-L6-v2")
self.labels = ["positive", "negative", "neutral"]
def score_passage(self, text, max_length=512):
"""
为一段文本返回 [-1, 1] 区间内的带符号情绪分数。
过长的段落会被切块后取分数平均。
"""
chunks = self._chunk_text(text, max_length)
if not chunks:
return 0.0
scores = []
for chunk in chunks:
inputs = self.tokenizer(chunk, return_tensors="pt", truncation=True,
max_length=max_length)
with torch.no_grad():
logits = self.model(**inputs).logits
probs = torch.softmax(logits, dim=1).numpy()[0]
# 正面减负面,忽略中性部分的概率质量
signed = probs[self.labels.index("positive")] - probs[self.labels.index("negative")]
scores.append(signed)
return float(np.mean(scores))
def _chunk_text(self, text, max_length):
words = text.split()
chunk_size = max_length - 20 # 为特殊 token 预留空间
return [" ".join(words[i:i + chunk_size])
for i in range(0, len(words), chunk_size)] if words else []
def embedding_similarity(self, text_a, text_b):
"""两段文本之间的余弦相似度,用于申报文件的同比对比。"""
emb = self.embedder.encode([text_a, text_b])
return float(cosine_similarity([emb[0]], [emb[1]])[0][0])
class EarningsCallSplitter:
"""
利用标准的会议记录标记,把原始的财报电话会记录切分成
准备发言和分析师问答两个部分。
"""
QA_MARKERS = [
r"question-and-answer session",
r"questions? and answers?",
r"we will now (begin|open) the (question|q&a)",
r"first question",
]
def split(self, transcript_text):
lower = transcript_text.lower()
split_idx = None
for pattern in self.QA_MARKERS:
match = re.search(pattern, lower)
if match:
split_idx = match.start()
break
if split_idx is None:
# 兜底:如果找不到标记,就假定最后三分之一是问答环节
split_idx = int(len(transcript_text) * 0.66)
return {
"prepared_remarks": transcript_text[:split_idx],
"qa_section": transcript_text[split_idx:]
}
class FilingSectionExtractor:
"""
利用 SEC 标准的条目编号标题,从 10-K/10-Q 文本中
抽取 MD&A 和风险因素章节。
"""
SECTION_PATTERNS = {
"risk_factors": r"item\s+1a\.?\s+risk factors(.*?)item\s+1b",
"mda": r"item\s+7\.?\s+management.s discussion(.*?)item\s+7a",
}
def extract(self, filing_text):
lower = filing_text.lower()
sections = {}
for name, pattern in self.SECTION_PATTERNS.items():
match = re.search(pattern, lower, re.DOTALL)
sections[name] = filing_text[match.start():match.end()] if match else ""
return sections
class DecayWeightedSignal:
"""
把原始语调分数与一个基于"距发布经过小时数"的指数衰减权重结合起来,
避免把变旧的信号当成和新鲜信号一样可交易。
"""
def __init__(self, half_life_hours=8.0):
self.half_life = half_life_hours
def weight(self, hours_elapsed):
if hours_elapsed < 0:
return 0.0
return 2 ** (-hours_elapsed / self.half_life)
def weighted_score(self, raw_score, release_time, as_of_time=None):
as_of_time = as_of_time or datetime.now()
hours_elapsed = (as_of_time - release_time).total_seconds() / 3600
return raw_score * self.weight(hours_elapsed)
class TonePipeline:
"""
端到端流水线:输入原始的会议记录/申报文件文本,
输出按衰减加权的综合语调分数。
"""
def __init__(self, half_life_hours=8.0):
self.scorer = FinancialTextScorer()
self.call_splitter = EarningsCallSplitter()
self.filing_extractor = FilingSectionExtractor()
self.decay = DecayWeightedSignal(half_life_hours)
def score_earnings_call(self, transcript_text, release_time, as_of_time=None):
sections = self.call_splitter.split(transcript_text)
prepared_score = self.scorer.score_passage(sections["prepared_remarks"])
qa_score = self.scorer.score_passage(sections["qa_section"])
# 问答环节权重更高——增量信息含量更大
composite_raw = 0.35 * prepared_score + 0.65 * qa_score
divergence = prepared_score - qa_score
return {
"prepared_remarks_score": prepared_score,
"qa_score": qa_score,
"tone_divergence": divergence,
"composite_raw": composite_raw,
"composite_decay_weighted": self.decay.weighted_score(
composite_raw, release_time, as_of_time
),
}
def score_filing(self, filing_text, prior_year_filing_text, release_time,
as_of_time=None):
sections = self.filing_extractor.extract(filing_text)
prior_sections = self.filing_extractor.extract(prior_year_filing_text)
mda_score = self.scorer.score_passage(sections["mda"])
risk_similarity = self.scorer.embedding_similarity(
sections["risk_factors"], prior_sections["risk_factors"]
)
return {
"mda_score": mda_score,
"risk_factors_yoy_similarity": risk_similarity,
"risk_factors_changed": risk_similarity < 0.85, # 经验阈值
"composite_decay_weighted": self.decay.weighted_score(
mda_score, release_time, as_of_time
),
}
# 用法示例
if __name__ == "__main__":
pipeline = TonePipeline(half_life_hours=8.0)
sample_transcript = """
Thank you for joining us today. We are pleased to report strong
results this quarter, with revenue growth accelerating...
[prepared remarks continue]
Question-and-Answer Session
Analyst: Can you walk us through the margin pressure in the segment?
CFO: Well, I think, um, there are some puts and takes there, and
we're cautiously monitoring the situation going into next quarter...
"""
release_time = datetime(2026, 3, 12, 16, 30) # 下午 4:30 的电话会
as_of = datetime(2026, 3, 12, 20, 0) # 3.5 小时后打分
result = pipeline.score_earnings_call(sample_transcript, release_time, as_of)
print(f"Prepared remarks score: {result['prepared_remarks_score']:.3f}")
print(f"Q&A score: {result['qa_score']:.3f}")
print(f"Tone divergence (prepared - Q&A): {result['tone_divergence']:.3f}")
print(f"Decay-weighted composite: {result['composite_decay_weighted']:.3f}")
⚠️ 散户面临的数据与延迟局限
这条流水线需要 及时拿到会议记录和申报文件 ——免费来源(SEC EDGAR 全文检索、一些免费的会议记录聚合站)通常比现场事件滞后几分钟到几小时不等,考虑到上面那条衰减曲线,这一点影响极大。要想在当日窗口里争夺哪怕一部分,生产版本需要实时的会议记录数据流和 EDGAR 申报提醒服务;现实中散户在衰减曲线上的位置比机构交易台靠后得多,这改变的是策略的设计方式,而不是让它失效。
散户落地:你实际落在曲线的哪一段
别再去抢头三个小时
拥有直连会议记录数据流和专用推理基础设施的低延迟机构交易台,占据了发布后的头几个小时——对一条跑在延迟数据和消费级算力上的散户流水线来说,衰减曲线的这一段不是一个现实的目标。 这个策略中散户可行的版本,瞄准的是 持续数天的残余漂移尾部,在这一段里,行动较慢的资金还在调仓,信号虽然更小,但延迟状态下更容易够得着。
散户可行的信号窗口
| 时间窗口 | 谁在这里竞争 | 散户可行性 |
|---|---|---|
| 发布后 0-3 小时 | 低延迟的机构交易台 | 不可行——数据获取和速度差距太大 |
| 当日收盘后至次日开盘前 | 卖方分析师、动作较快的主观基金 | 勉强可行——需要当日拿到 EDGAR 文件/会议记录 |
| 1-3 个交易日 | 行动较慢的量化和基本面资金 | 散户最现实的入场窗口 |
关键洞察: 一个想用延迟数据去交易头三个小时的散户策略,捕捉到的不是机构优势的缩小版——它是在真正的信号已被套利抹平之后交易噪音。把策略的规模围绕 1-3 天的残余尾部来设定,才是这笔交易诚实且可执行的版本。
聚焦覆盖不足的标的
由于分析师覆盖稀薄的标的衰减半衰期更长,散户做语调提取在中小盘股上的风险回报,在结构上要好于覆盖最密集的超大盘股,在后者身上,第一个小时的机构反应通常已经在散户流水线动手之前吃掉了大部分可用的价格影响。
示意性业绩
下面的数字是对一个瞄准 1-3 天残余窗口、按衰减加权的语调背离策略收益形态的假设性示意 ——它们不是业绩记录,也不承诺能取得类似结果。列出它们是为了把风险回报的形态说具体,而不是暗示这件事可以预测。
财报后语调背离方案示意(覆盖不足的标的,持有 1-3 天)
- 胜率: 约 55-60% 的交易方向判断正确(优势很温和,单独看不是高信心信号)
- 平均盈利: 持有期内 +1.5% 至 +3%
- 平均亏损: 持有期内 -1% 至 -2.5%
- 表现最好的子集: 大幅负向语调背离(准备发言自信、问答环节充满模糊措辞)叠加一个相互矛盾的另类数据信号
关键结论: 这是一个温和的统计性优势,需要跨很多标的、很多个季度地跑下去才会稳定显现——而不是一个让你把组合集中押在少数几只高信心个股上的信号。
🚨 这个优势很小,而且很快就变拥挤
基于文本的情绪 alpha 在学术金融界已经是公开知识超过十年,如今被资金雄厚的交易台大量套利。这个策略的任何散户版本,拿到的都是一个早已被抢过一轮的信号中更薄、到得更晚的那一片。把分散的一篮子标的上温和而稳定的优势当作成功——而不是指望在任何单只标的上拿到很大的优势。
抹掉这个优势的常见错误
错误清单
- 把整份会议记录当成一整块打分: 用低信号的准备发言部分稀释了高信号的问答部分。
- 忽略针对具体管理层的基准: 把天性谨慎的发言者、或模糊措辞本来就多的行业(生物科技、早期阶段公司)季季标记为看空。
- 不管过了多久都把信号当新鲜的用: 用对待一小时前文件的同等信心去交易本周内的旧文件,完全无视衰减曲线。
- 在错误的窗口里竞争: 用延迟的散户数据去抢发布后头几个小时,而那个窗口属于低延迟的机构交易台。
- 对单个另类数据点赋予过高权重: 把一个时断时续的卫星或抓取信号当成确证,而不是当成若干个嘈杂输入中的一个。
- 没有跨财报周期做样本外验证: 用一两个季度的数据拟合出衰减半衰期或打分阈值,就假定它能推广。
你的行动计划
第 1 阶段:搭建并验证打分流水线(4-8 周)
时间安排: 在投入任何资金之前,先确认这条流水线产出的分数合理且稳定。
- 装好 FinBERT(Hugging Face,免费),拿它跑一批历史会议记录 这些记录之后的价格反应是已知的
- 搭好准备发言/问答的切分器 并人工抽查一部分切分结果的准确性
- 为每只标的计算并记录一条语调基准线 跨若干个季度积累,之后再把任何单次读数当成信号
第 2 阶段:小规模、考虑衰减的落地(2-4 个月)
时间安排: 从可交易的最小仓位起步,并且只做 1-3 天这个窗口。
- 只交易残余尾部这个窗口 ——彻底跳过当日反应;你没有装备去争夺它
- 优先选择覆盖不足的中小盘股 它们的衰减半衰期更长,散户的延迟影响更小
- 要求语调背离与另类数据相互吻合 之后再决定仓位大小——绝不要仅凭文本语调就下满仓
- 记录每一笔交易实际的衰减表现 以便按流动性分档细化你的半衰期估计
第 3 阶段:系统性扩大规模(6 个月以上)
时间安排: 必须先完整走过一个(或更多)财报周期的小仓位验证执行之后再说。
- 把申报文件/会议记录的摄取自动化 对接实时的 EDGAR 提醒数据流和付费的会议记录供应商
- 分散到一篮子标的上 而不是集中押注少数几只高信心个股
- 每个财报季都重新验证一次衰减半衰期的估计 ——市场环境和覆盖格局会随时间变化
推荐阅读
- 机构研究:
- Two Sigma Research——关于系统化投资中 NLP 与非结构化数据的公开评论
- Point72 / Cubist Systematic Strategies——关于机器学习与另类数据流水线的公开评论
- PMR 相关文章:
- Goldman Sachs 另类数据(配套文章,讲 FinBERT 与卫星/社交信号的集成)
- Point72 Cubist 机器学习流水线(配套文章,讲这个语调信号将要接入的更完整的机器学习生产流水线)
🎯 最后的思考
非结构化文本是少数几种原材料完全公开且免费的数据源之一——优势完全在于比市场上较慢的参与者读得更快、更稳定、更懂上下文。 这和专有数据源带来的优势是真正不同的一类:它是处理能力上的优势,而不是获取渠道上的优势。
活下来的关键: 诚实面对你究竟能在衰减曲线的哪一段竞争,把信号分散到很多标的上而不是集中在少数几只,并且永远不要让一个温和的统计性语调倾斜取代一个真正分散、低成本的退休核心组合。这是叠加在那个核心之上的卫星战术——永远不是核心本身。
先从给历史数据打分开始,而不是实时申报文件。在你交易任何一个新鲜信号之前,先拿已知结果校准这条流水线。