先说个场景:我以前做个股研究,大部分时间不是在思考,而是在复制粘贴财报数字。一份季度财报动辄几十上百页,真正有用的核心指标可能就那三五项,但你不逐页扫一遍,根本不敢下结论。后来我开始搭一套LLM增强的基本面分析系统,把财报读取、收入报表多指标评分、回测验证全部串起来,总算把自己从“人肉OCR”里解放出来。这篇文章会把整套流程完整拆开,覆盖指标和权重怎么定、Prompt怎么设计、LLM怎么落地,以及回测验证里头那些容易踩的坑。文末附上能直接跑的Python代码和一份模拟财报数据集,方便你照着搭自己的版本。
1. 为什么我决定用LLM重写基本面筛选流程
1.1 传统基本面分析的低效环节
过去我每周都要处理一份又一份的季度财报,几家公司还能靠人海战术覆盖,一旦把观察池扩大到上百只股票,效率立刻崩盘。传统财务数据库能给你现成的营收、利润、现金流字段,但财报里最值钱的信息往往不在主表里:管理层的语气、风险因素的变化、数字背后的业务解释,这些非结构化内容常年被忽略。我后来统计过,一份常规季度财报中,真正对投资判断有增量价值的信息约占两成,但为了找到这两成,必须读完全部文本,这个时间成本在自下而上的研究中几乎是纯消耗。
LLM能改变这个局面,核心原因是它同时擅长两件事:把非结构化文本转成结构化字段,以及理解上下文语义。我可以用一份财报的原始文本作为输入,让模型先按固定Schema抽取收入报表相关指标,再输出针对异常项的自然语言风险提示。这样就把原本需要两小时的手工阅读压缩到两分钟,还更不容易漏项。当然可靠性不是天然保证的,后面我会专门讲怎么抑制幻觉和校验数字。
1.2 这套方案的架构设计
整套系统的流程可以画成五层:财报原始文本先进LLM抽取层,模型按固定的输出Schema吐出标准化JSON,JSON里的数字再进入多指标评分模块,按照行业中性化的百分位打分法生成综合评分;接下来按综合评分排序构建组合,最后交给回测引擎校验收益与风险。任何一层出了问题,都会在回测阶段表现为某一段区间的异常回撤,所以调试的时候我会把各层中间结果都落盘,逐层排查。
| 模块 | 解决什么问题 | 关键产出 |
|---|---|---|
| 财报获取与解析 | 数据从哪来 | PDF/HTML/文本格式的财报原始内容 |
| LLM抽取与理解 | 非结构化文本转结构化 | 带原文依据的标准化JSON指标 |
| 多指标评分 | 不同指标怎么合成一个数 | 每家企业0到100的综合分 |
| 组合构建 | 评分怎么变成持仓 | 调仓日排名前N的股票池 |
| 回测验证 | 信号是否真的有超额收益 | 收益曲线、回撤、夏普比率等指标 |
1.3 模型选型的现实标准
很多朋友一上来就问用什么LLM,我的建议是先别急着追最强榜单。公开榜单如Open LLM Leaderboard、各类评测集只能做初筛,真正要看的指标是:长文档稳定性、数字抽取准确率、输出JSON的格式遵循率。我只在意三个测试用例:一篇五十页的年度财报能否抽出所有收入报表字段;抽出的数字能否和原文正则匹配;连续跑十次,结果是否稳定。基于这组测试再决定用闭源API还是开源模型,而不是单纯看谁的分数高。
选型时另外要注意上下文长度与成本的关系。财报原文经常超出普通模型的默认上下文长度,强行截断会丢掉关键数字;为了省Token把表格去掉,又会让“营业成本”和“研发费用”字段失去边界。我的经验是先做一个几百Token的“财报片段抽取”测试,再逐步加大文本量,观察数字召回率下降的拐点。这个拐点才决定模型能不能上生产,榜单排名只是参考。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 收入报表多指标评分:从指标选型到权重设计
2.1 核心指标选择:营收、利润、现金流与预期差
我最后固定用的收入报表指标有六个:营收同比增长率、毛利率、营业利润率、净利润同比增速、EPS超预期幅度、自由现金流/净利润。这套组合的逻辑是覆盖三个不同侧面:营收增速代表扩张速度,毛利率与营业利润率代表赚钱效率,EPS超预期代表市场共识与实际业绩的差值,自由现金流占比则用来检验利润的含金量。
如果只选一个指标,营收增速最直观,但很容易被“增收不增利”带到沟里。我见过不少公司营收两位数增长,净利润反而下滑,单看增速会误判成高成长。所以毛利率和营业利润率必须跟上,用来过滤低质量扩张。净利润增速是结果指标,放进来负责校正前面的经营效率。EPS超预期这个指标不是严格的财报主表项目,而是实际值和分析师一致预期的比较,属于市场预期差,放在多指标组合里能让策略更贴近交易逻辑。最后用自由现金流/净利润做兜底,防止应收账款堆积导致纸面利润膨胀。
2.2 评分算法:百分位排名和行业中性化
打分我一开始用的是绝对阈值,比如营收增速大于20%得80分、10%到20%得60分。跑了两个月回测发现不行,因为不同行业增速基线完全不同,成熟行业平均3%就算优秀,高科技行业30%可能倒数。绝对阈值会把少数行业霸榜,组合行业集中度极高。后来改成横截面百分位排名:每个指标在当前时点所有可比公司中排名,得分在0到100之间分布,彻底消除行业基线差异。
准确的流程是先把公司按一级行业分类,在行业内部做百分位排名,再映射到0到100分。跨行业直接比较百分位排名等于没有中性化。举个例子:银行股的营业利润率会被公允价值变动干扰,和零售股直接比较没有意义;但同一行业内部的相对位置,可以直接用于排序。行业中性化之后的评分结果,组合的行业分布会明显更均衡,回测最大回撤也小了不少。下面这个函数就是核心评分逻辑,可以直接跑:
python复制import pandas as pd
import numpy as np
EARNING_COLUMNS = [
'revenue_yoy', 'gross_margin', 'operating_margin',
'net_income_yoy', 'eps_surprise', 'fcf_to_ni'
]
def percentile_rank(series):
"""对序列做百分位排名,返回0~100分"""
return series.rank(pct=True) * 100
def industry_neutral_score(df):
"""输入的df必须包含company, industry和EARNING_COLUMNS字段"""
for col in EARNING_COLUMNS:
df[col + '_score'] = df.groupby('industry')[col].transform(percentile_rank)
score = 0
score += 0.25 * df['revenue_yoy_score'] # 成长性
score += 0.20 * df['gross_margin_score'] # 定价权
score += 0.20 * df['operating_margin_score'] # 经营效率
score += 0.15 * df['net_income_yoy_score'] # 盈利结果
score += 0.10 * df['eps_surprise_score'] # 预期差
score += 0.10 * df['fcf_to_ni_score'] # 盈利含金量
return score
权重不是拍脑袋拍出来的,我先后用了两个办法验证:第一是信息系数IC分析,算每个指标和未来一期收益的秩相关,把IC均值高、波动低的指标放在前面;第二是行业轮动观察,看权重调整后组合能不能在风格切换时不出现单边大亏。最终上面这组权重在多数年份都相对稳定,所以保留下来。
2.3 缺失值、极端值处理与权重修正
财务数据天然有缺失,比如刚上市的公司没有去年同期EPS,银行股没有自由现金流。我的默认处理是:先看该指标缺失比例,超过30%就直接从模型中剔除;比例不高则按行业中位数值填充,再补一个惩罚项。这样做比直接填0温和,又不会把缺失当成真实低分。极端值同样不能直接进排名,我会做MAD(中位数绝对偏差)截尾,把超过五倍MAD的值替换到边界,防止一家公司因为一次性资产处置把分数拉到极端。
在季报场景下,我还会对现金流类指标做权重修正。因为自由现金流/净利润在很多公司的季度报表里更新得很慢,甚至不披露,十几家公司这个字段全是空值。真到调仓日,这些空值如果用中位数填充,实际效果等于把指标权重稀释掉了。所以我的建议是:季度评分时把现金流权重压到5%,全年报披露后恢复正常权重。这个调整表面上是处理缺失值,实际上解决的是信息时效性,效果比强行补数好得多。
3. LLM在财报分析中的落地:抽取、校验与评分
3.1 用固定Schema让LLM输出结构化JSON
LLM抽取财务数字的Prompt,我踩过不少坑,最后总结出一条铁律:永远不要让模型自由发挥。如果你的Prompt只是说“帮我提取营业收入和毛利率”,模型会按照自己的理解返回各种格式,后面解析代码会被逼疯。我的做法是在Prompt里给出完整JSON模板,连字段名、单位、是否允许为空都写死,并要求模型只输出JSON,不要附带任何解释文字。模板和约束条件大概长这样:
text复制你是一名财务数据抽取引擎。请从以下财报文本中提取字段,并严格按JSON结构返回:
{
"company": "公司名",
"fiscal_period": "如2024Q2",
"revenue_yoy": {"value": 12.3, "unit": "percent", "source_sentence": "原文依据句"},
"gross_margin": {"value": 42.5, "unit": "percent", "source_sentence": "原文依据句"},
"operating_margin": {"value": 18.2, "unit": "percent", "source_sentence": "原文依据句"},
"net_income_yoy": {"value": 8.7, "unit": "percent", "source_sentence": "原文依据句"},
"eps_surprise": {"value": 3.2, "unit": "percent", "source_sentence": "原文依据句"},
"fcf_to_ni": {"value": 0.85, "unit": "ratio", "source_sentence": "原文依据句"}
}
约束:
1. 不要输出JSON以外的任何内容;
2. 所有百分比统一为百分数,如12.3表示12.3%;
3. 金额统一为百万美元;
4. 如果原文没有提到某字段,value置为null,不要猜测;
5. source_sentence必须是从原文中逐字复制出的依据句子;
6. 遇到“同比增长”、“环比增长”务必按原文口径区分,不得自行换算。
这套Schema解决了三个问题:字段对齐、单位混乱、以及幻觉追责。尤其是source_sentence字段,它在模型抽取每个指标时强制附带原文依据,后期任何数字对不上账,我能直接回溯到文本原句,而不是靠模型说“我看到了”。解析端只要用JSONSafetyChecks或者Pydantic做一次类型校验,字段缺失和类型错误就会在进入评分模块前被拦截。
3.2 两层数字校验:正则提取与LLM交叉验证
我建议至少做两层校验。第一层是数值层面:用正则表达式把原文里的数字直接抠出来,和LLM返回的数值比对,允许四舍五入误差。第二层是语义层面:用另一个LLM当裁判,检查每个source_sentence是否真的能支撑这个数值,并把可疑项标记出来。第二层不查不知道,一查吓一跳:模型经常把“环比下降15%”理解为“同比下降”,两个口径差了一倍,这种错误纯靠正则发现不了。
口径混淆是我最头疼的问题。所以我在提取Prompt里专门加了一条“同比与环比必须按原文区分”,但模型仍有概率犯低级错误。后来我把校验Prompt也模板化,输入是“字段定义 + 抽取结果 + 原始文本片段”,输出只有三个选项:一致、不一致、无法判断。不一致的字段自动降级为缺失值,不参与评分。用LLM做裁判本身也有成本,我只对得分排名前30的公司做第二层校验,普通公司只保留正则校验,这样成本可控。
3.3 为什么我不让LLM直接输出综合评分
曾经我图省事,让LLM在抽取完指标后顺便给公司综合基本面打个0到100分。效果看起来不错,Prompt里给一点评分标准,它能把非结构化信息比如管理层语调也融进去,但问题是不稳定:同一份财报跑五次,分数可能波动10分以上;换一个模型版本,排序逻辑全变。更严重的是不可解释,你不知道80分到底是哪个指标贡献的。后来我还是把主干评分放回规则函数,LLM只做两件事:抽取结构化字段,输出风险提示摘要。评分时给语义分最多留10%的权重,既保留语义信息,又不至于让黑箱逻辑主导交易决策。
这个10%的语义分具体怎么加?我在规则评分的基础上,让LLM对“风险因素”“管理层讨论”“竞争优势”三个段落分别输出一个评分等级,然后把三级评分映射成-5到+5的调整项,累加到综合分上。风险提示多且明确的,给负分;管理层语气积极但保持克制,给正分。注意调整项的波动范围要远小于规则分,否则又回到黑箱主导。我做过对比实验:去掉语义分后,策略年化收益略降,但最大回撤也略降,整体夏普比率几乎不变。也就是说,这10%语义分主要改善的不是收益,而是组合的“样本内逻辑解释”,方便我复盘为什么某个股票会被选中。
3.4 Token预算与Query/Key/Value的工程直觉
工程化场景里,LLM成本主要花在token上。我常用一套比喻:把Prompt里的问题看作Query,财报文本的段落看作Key,段落实实在在的数字和结论看作Value。系统要做的是在Key空间里快速定位与Query相关的段落,再提取Value,而不是把整个Key空间无脑塞进上下文。落到实操,就是先做章节切分,只把“经营讨论与分析”和“财务报表附注”两段交给LLM,其他高管人员名录、风险披露模板全部裁掉。这样token预算能省一半以上,抽取准确率还更高,因为模型注意力更集中。
这个Query/Key/Value的比喻不是注意力机制的严格定义,只是我用来管理Prompt上下文的工程直觉。真正省钱要靠更细的文档切分:我会先把财务报表部分用表格识别工具解析成DataFrame,再让LLM直接基于表格字段名做数值映射;非结构化部分才交给LLM做语义理解和风险提示摘要。两条路径分开,结构化数据走的还是确定性函数,非结构化语义才用模型能力,Token成本能压到每次调用几千Token,而不是几万Token。
4. 回测验证:如何把评分信号变成可验证的策略
4.1 Point-in-Time数据是防止未来函数的地基
回测基本面策略最容易犯的错是未来函数。很多人用财报截止日当信号生效日,比如2024年3月31日截止的季报,直接让策略在4月1日开始交易。实际上这份财报可能4月25日才公告,4月1日你根本拿不到数据,整个回测等于作弊。正确做法是用财报公告日作为信号更新的时间点,且保证回测时期只用当时已经公开的信息。不同市场对披露节奏的要求不一样,我处理的时候会单独维护一张披露时间表,把每个公司的财报周期和实际公告日期关联起来。
光有披露时间表还不够,还要处理数据修订问题。公司发布财报后,偶尔会发布修订稿,修正某些字段。回测时必须只使用最初发布的版本,而不是修订后的版本,否则同样会引入未来信息。我的做法是在数据存储层为每个报告周期保留多版本快照,字段读取时默认取公告日当天发布版本。这样做很笨,但却是基本面回测无法绕过的硬约束。评分模块和回测模块都基于同一个快照表,才不会出现“评分时用了A版本,回测时却用了B版本”的错位。
4.2 一个可运行的轻量回测骨架
我早期用现成的回测库,后来发现对股票池、调仓日、手续费的自定义要求太多,干脆写了一个轻量的季度调仓回测函数。核心逻辑很简单:在每个调仓日,取当前时点已经发布的评分数据,按综合分排序,买入排名前N的公司,卖出不在名单内的公司,计算换手成本和下一周期的组合收益。为了让你能直接复现流程,我写了一个mock数据生成器,随机生成评分和收益,方便在本地跑通回测逻辑,再换成真实数据使用:
python复制import pandas as pd
import numpy as np
def generate_mock_data(n_companies=50, periods=12):
"""生成模拟的评分-未来收益宽表,仅用于演示回测骨架"""
rng = np.random.default_rng(42)
dates = pd.period_range('2021-09', periods=periods, freq='Q')
companies = [f'C{i:02d}' for i in range(n_companies)]
rows = []
for period in dates:
for company in companies:
rows.append({
'period': period,
'company': company,
'score': rng.uniform(0, 100),
'forward_return': rng.normal(0.02, 0.12)
})
return pd.DataFrame(rows)
def quarterly_rebalance(df, top_n=10, cost=0.001):
"""每个季度按score选前top_n,按等权持有下一期,cost为单边换手成本"""
df = df.sort_values(['period', 'score'], ascending=[True, False])
prev_holdings = set()
equity = 1.0
for period, grp in df.groupby('period'):
holdings = set(grp.head(top_n)['company'])
turnover = len(holdings - prev_holdings) / top_n
portfolio_return = grp[grp['company'].isin(holdings)]['forward_return'].mean()
equity *= (1 + portfolio_return - cost * turnover)
prev_holdings = holdings
return equity
mock_data = generate_mock_data()
print(f'模拟数据的期末净值: {quarterly_rebalance(mock_data):.2f}')
上面的mock数据里,评分是随机生成的,所以期末净值没有参考意义,它只是让你理解回测函数的数据流。换成真实场景时,score列换成第二步算出的综合分,forward_return列换成下一个调仓区间内股票的实际收益率就行。另外要注意,真实换仓不可能不考虑买卖价差和流动性,我通常会在组合构建时限制单只股票在调仓日的可交易比例,避免小市值公司冲击成本过高导致收益失真。
4.3 回测指标要看哪些数
只看收益曲线不够,我会同时记录五个指标:年化收益率、最大回撤、夏普比率、月度胜率、年换手率。下面这张表是我在某脱敏数据集上得到的示例结果,目的是展示指标怎么解读。它不代表任何真实产品收益,也绝对不能当成实盘预期,但数据结构能帮你看明白回测报告里每行数字的含义。
| 指标 | 示例结果 | 我的关注点 |
|---|---|---|
| 年化收益率 | 14.8% | 必须跑赢基准,否则策略没有存在价值 |
| 最大回撤 | 18.3% | 超过15%我就要仔细检查回撤来源 |
| 夏普比率 | 1.32 | 大于1算及格,大于1.5算可接受 |
| 月度胜率 | 62.1% | 胜率低说明收益靠少数月份撑起来 |
| 年换手率 | 168% | 换手率越高,成本侵蚀越重,越危险 |
年化收益率高但最大回撤大的策略很难拿住,实盘过程中只要遇到一两次大回撤,人就会开始乱改参数。夏普比率是把波动成本计入后的综合性价比,我更多用它做横向比较。月度胜率这个指标很诚实,如果长期只有55%胜率,意味着两个月赚一次亏一次,策略持有体验极差;胜率高的策略更可能靠稳定alpha,而不是靠几次大行情。换手率要结合交易成本看,单边成本按千分之一的话,168%的年换手率对应的成本损耗约3.3%,如果超额收益不到5%,基本等于白做。
4.4 参数灵敏度和样本外检验
回测好看不一定有效,最常见的陷阱是权重和阈值在样本内反复调。我建议这样检验:把排名数量从5改成10、20,权重整体上下浮动20%,调仓频率从季度改成半年,观察收益排名是否保持靠前。如果任何一组调整都让超额收益消失,那说明策略只是在拟合噪音。真正能做样本外测试的,是把前三年当训练期,后一年当验证期,LLM的评分规则一旦锁定就不再改动。
我还习惯把每个调仓周期的评分记录保存下来,事后画出“高分组-低分组累计收益差”的曲线。这本质上是检验评分是否有单调性:如果最高分组和最低分组的收益差长期大于0,说明信号有效;如果曲线经常穿越零轴,说明评分和收益没有稳定关系,任何漂亮的净值曲线都可能是偶然。这个动作成本极低,但能避免大部分自欺欺人的回测。
5. 实战避坑:数据源、幻觉与回测陷阱
5.1 财报数据版本不一致
同一家公司同一份财报,不同数据商给出来的数字可能不一样,最常见是口径差异:有的用GAAP营业收入,有的用non-GAAP;有的把非经常性损益剔除,有的不剔除。遇到这种情况我以最原始的财报PDF为准,在LLM抽取时明确标注GAAP还是non-GAAP,评分时保持全市场一致口径。混用口径是回测崩盘的隐蔽原因,你会看到某些公司的分数莫名偏高,而且很难排查。
数据商还会出现重复记录问题。同一季度财报可能因为字段更新在数据库里出现多条记录,如果直接按最新记录去重,又会把“历史快照”和“修订稿”混在一起。我的做法是用“公告ID + 字段名 + 版本号”唯一标识,读取历史数据时强制限定版本号小于等于调仓日最大版本号。这个规则看起来麻烦,但它把一个模糊的数据问题变成了确定性存储问题,排查起来容易得多。
5.2 数字幻觉的三个高发场景
LLM在财务数字上容易犯三类错误:同比环比搞混、单位弄错、把重组费用当作经营亏损。第一类靠Prompt约束和裁判模型双重校验;第二类需要在Prompt中要求统一货币单位,并且校验时对金额做数量级检测;第三类最坑,因为模型对“一次性费用”和“持续经营成本”的语义边界本来就模糊,一旦混入经营利润率,整个评分都会失真。
我排查幻觉有一招:对每个数值字段都要求返回source_sentence,然后写一个带强约束的校验Prompt,让另一个LLM判断source_sentence与数值是否一致。这样把LLM当裁判用,准确率提高非常明显。如果发现某个字段的幻觉率超过5%,我会干脆把它从评分模型里移除,而不是继续依赖校验逻辑。因为校验只能发现一部分错误,漏掉的那部分仍然在污染评分。
5.3 幸存者偏差与股票池构建
一开始我用今天的股票池去回测五年前,结果策略收益漂亮得不像话。原因很简单,今天的股票池里全是活下来的公司,退市和被并购的烂公司根本没被统计进去,回测自然高估。解决办法是把历史某一天的全部股票池纳入,包括后来退市的公司,这样才符合当时的可选范围。我后来在系统里加入了一个退市名单字段,每次建模前自动过滤掉那些在样本期内根本没有交易记录的股票。这个过程很枯燥,但没有它,回测指标没有任何可信度。
还有一类偏差更隐蔽:部分公司因为财报发布太晚,调仓日可能还在停牌状态。如果回测引擎默认这类公司可以交易,也会高估收益。我在调仓逻辑里加了一个最小交易量过滤条件,筛选近20个交易日日均成交额超过一定阈值的股票。这个阈值不用设太高,只要能把没有流动性的僵尸股排除掉,收益曲线会显著变得平滑。
5.4 现金流指标的时效性
自由现金流/净利润看起来很美,但这个指标在季报里更新极慢,很多公司甚至一季度不披露完整现金流表。我最初给它10%权重,结果每次调仓都是一堆缺失值填充。说实话,现金流更适合做确认项而不是交易项,如果你必须用,建议在年报场景用,季报场景直接放弃。我的最终方案是:季报权重降到5%,每年年报季恢复到10%,其余季度用行业中位数填充。这个调整让回测更贴近实际可用数据,而不是在理想化假设下自嗨。
5.5 交易成本不能设太低
回测里把手续费设成零,情绪会上头。真实环境有佣金、买卖价差和冲击成本,尤其小市值公司换仓时的冲击成本高得惊人。我把单边成本按千分之一打底,小市值再额外加缓冲。这么做会损失一截理论收益,但换来的才是能落地的策略。回测引擎里我希望大家至少覆盖两类成本:固定佣金比例、按持仓市值的价差冲击系数。把成本参数调高后,策略排名10和排名5的差别会变得非常明显,也更接近真实执行情况。
6. 可复用经验与后续扩展
6.1 建议的实施顺序
整个项目里我花在LLM调优上的时间最多,其次才是评分和回测。如果你也想复现,别一上来就追求最复杂的模型。先用规则评分把数据链路跑通,再在风险提示环节逐步加入LLM,最后才考虑让模型参与评分。每加一个LLM环节,都要增加对应的校验逻辑,否则调试噩梦在后面等着。我见过不少团队一开始就上“LLM直接打分”,结果模型输出不稳定,后面再回退重做规则系统,返工成本非常高。
具体到执行顺序,我建议这样:先把财报原始数据解析成干净的DataFrame;接着用传统规则完成多指标评分和行业中性化;再做简单回测,确定这个主干的收益来源是可靠的;只有在主干跑稳之后,才接入LLM做语义补充和风险提示。这样你每一步出了问题都能独立定位,不会出现“收益曲线变了但不知道该归因于LLM还是评分函数”的情况。
6.2 值得尝试的三个扩展方向
这套系统目前还有几个明显的改进空间。一是把财报电话会议记录纳入LLM分析,管理层的措辞变化往往领先于财务数字,这也是LLM相对传统NLP最有优势的地方。二是引入分析师一致预期,把EPS超预期从单一指标扩展成完整预期差模型,覆盖营收预期和利润预期。三是针对不同市场调整调仓节奏,比如某些市场信息披露密度低,季度调仓可能因为数据来不及更新而变成盲调,这时候改成半年度调仓反而更稳健。
另外可以考虑把“风险提示摘要”结构化保存下来,作为下一次调仓的负向过滤器。比如LLM输出“应收账款增速显著高于营收增速”,就可以在评分函数里对现金流项额外扣分。这种由文本生成规则的方式,是LLM增强基本面分析最有价值的方向,因为它把语义信息变成了可回测的规则,而不是仅仅停留在“看起来更智能”的层面。
6.3 这套系统里最值钱的部分
最后说点个人体会。这套系统跑下来,最有价值的东西其实不是那个综合评分,而是LLM在抽取指标同时生成的风险提示摘要。有几次策略在某调仓区间出现明显回撤,回头翻当时的LLM输出,发现模型早就写了一句“该季度应收账款增速显著高于营收增速”,只是当时权重没给到这一项。这种可解释性,是纯黑盒模型完全给不了的,也是我后来坚持保留LLM注释的原因。做量化策略久了会发现,很多回测里的好结果经不起实践检验,反而LLM给出的那段自然语言风险提示,能让你在实盘前多一次人工复核的机会。
