☰
大模型驱动的量化因子挖掘:从文本逻辑到可执行策略
2026/10/20 15:17:05 网站建设 项目流程

做量化这些年,我越来越觉得因子研究像在挖矿。传统挖法靠经验、靠线性模型、靠人工翻研报,成本高、同质化严重,挖出来的东西还常常解释不清为什么赚钱。直到最近把大模型引入因子挖掘流程,我才觉得这条路真正打开了一个新方向。LLMFactor就是干这个的:让大模型从海量文本里读取经济逻辑和交易逻辑,再把逻辑编译成可计算、可回测、可解释的盈利因子。这篇内容我会完整拆解这个项目的设计思路、关键模块、实操流程和踩坑记录,适合正在做量化因子研究、或者想用大模型改造传统投研流程的朋友参考。

1. 项目整体设计与技术选型

1.1 传统因子研究到底卡在哪里

先聊聊传统因子挖掘的痛点。过去我们做因子,大致路径是:从价量数据里手工构造技术指标,从财报里计算估值、成长、质量类指标,再用IC、分层回测、多因子回归这些工具筛选。这个流程本身没问题,问题在于几个环节的效率瓶颈。

第一,因子灵感的来源极度依赖人工阅读。研究员要翻大量的卖方研报、学术论文、行业专题,再把文字描述翻译成代码。这个过程不仅慢,而且每个人的翻译风格不一样,同一段逻辑换个人实现,可能就是两个因子。第二,传统因子表达以线性为主。经典的PB、ROE、动量、反转,本质上都是截面或者时序上的简单运算,很难刻画“行业集中度提升背景下龙头溢价增强”这类复合逻辑。第三,因子同质化严重。当市场上大多数人都用同样的数据源、同样的研报池、同样的实现方式时,挖出来的因子自然高度相关,多因子模型的边际增量越来越小。

这些痛点在传统框架内很难解决。你不可能靠多招几个研究员来突破阅读量的瓶颈,也不可能靠堆积线性算子来表达复杂逻辑。所以我从一开始就想:能不能让模型替人读、替人翻译、替人把逻辑写成代码?这就是LLMFactor项目的出发点。

1.2 核心理念:把因子当成“叙事加函数”

这个项目最关键的一个认知转变,是把因子不再看成一段纯数值计算,而是一个“叙事加函数”的组合体。

传统因子只是一个函数,输入原始数据,输出一个排序信号。但函数本身不携带任何语义,所以出了问题很难解释。而LLMFactor的思路是:先让大模型读一段文本,从中提炼出一条可验证的经济逻辑或交易逻辑,然后把这条逻辑表达成一个带注释、带参数说明、带引用来源的Python函数。这个函数就是因子,函数顶部的文档字符串和注释就是因子的可解释性来源。

举个例子。一篇行业报告提到“当行业库存周期处于主动去库存阶段,龙头企业的经营性现金流往往先于行业整体改善”。传统做法可能是研究员自己翻译成一个“现金循环周期变化率”指标。但在LLMFactor里,模型会先提取逻辑链:库存周期阶段识别,龙头定义,现金流相对改善的度量,然后生成一段代码,用行业库存同比增速的符号来近似判断库存周期阶段,用经营现金流与营收的比值变化来度量相对改善,最后合成一个因子。

这个过程的本质,是把“分析师写研报”和“程序员写函数”两件事合并成一步。模型的输出同时包含可读的逻辑说明和可执行的代码逻辑,两者天然绑定。这大大缩短了从文本阅读到可回测因子的距离。

1.3 为什么选择大模型而不是传统NLP或者人工规则

有人会问,传统NLP也能做文本信息抽取,为什么一定要上大模型。这个问题的答案,核心在于“泛化能力”和“指令遵循能力”两个维度。

传统NLP或者规则方法需要先定义清楚实体类别、关系模板,比如“什么行业、什么周期阶段、什么财务指标改善”,然后从文本里匹配对应槽位。这在封闭域里可以做得不错,但金融文本的表述极其多样,同一个逻辑在不同报告里可能是完全不同的写法。规则模板很难覆盖长尾表达。

大模型不一样。它是先在大规模语料上预训练,再通过指令微调学会“读懂一段话并转成代码”这个任务。只要提示词设计得当,它能直接处理开放式输入,不需要预定义实体类别和模板。实测下来,对于同样一篇行业深度报告,规则方法可能只能抽取出“库存周期下降”这类简单信号,而大模型能够捕捉到“龙头企业相对行业整体的现金流改善”这种带比较关系的复杂逻辑。

不过这里要澄清一个认知。很多人以为大模型是在“凭空发明因子”,其实不是。它的本质是高质量的信息压缩和翻译,把人类语言中隐含的逻辑结构转换成数值计算结构。它不会无中生有,而是把文本里原本存在的逻辑显式化。

2. 关键模块设计与核心难点突破

2.1 数据层:语料构建与因子表达规范化

这个项目的第一步,是构建一个干净、可追溯的文本语料库。我试过几种来源渠道,包括行业深度报告、公司调研纪要、宏观策略周报、学术论文摘要,以及一些高质量的财经评论。不同的语料源适合不同类型的因子。

行业报告通常包含产业链逻辑和景气度判断,适合抽取行业轮动和产业链传导类因子。调研纪要包含管理层对经营状况的定性描述,适合抽取公司治理和经营趋势类因子。宏观策略报告包含货币信用周期、库存周期、通胀传导等逻辑,适合抽取宏观状态类因子。

文本清洗这块没有太多取巧空间。需要做几件基础工作:去重、去广告模板、去无关图表说明文字,统一日期格式和单位。比较重要的是保留文本中的数字和相对变化的表述,比如“同比增长15%”“环比改善”“连续三个季度下降”,这些是后续生成因子时最关键的数值锚点。

因子表达规范化是这个模块最核心的设计。为了让大模型的输出稳定可控,项目定义了一套统一的中性因子描述格式,包含因子名称、因子类型、计算逻辑、数据依赖、更新频率、逻辑依据等字段。所有语料最终都会被组织成统一的JSON结构喂给模型,这样后续的生成和校验流程才能工业化运转。

2.2 因子抽取:让大模型输出可执行的盈利因子

如果把整个项目比作一条流水线,提示词工程就是最重要的机床。在LLMFactor里,我设计了一套三层提示词结构。

第一层是角色设定和背景说明。告诉模型它是一名量化研究员,任务是阅读给定的文本,从中提取可实现的盈利因子逻辑。第二层是输出格式约束。要求模型输出严格的JSON结构,包含“逻辑解释”、“因子代码”、“参数说明”、“数据依赖”、“风险提示”几个字段。第三层是示例驱动。给出两到三个不同类型的参考案例,用few-shot的方式让模型理解预期的输出粒度。

提示词里最关键的技巧是要求代码必须使用统一的函数签名。我们定义了一个通用的基础函数接口,每个因子都必须实现一个指定名称的计算函数,输入是标准化的DataFrame,输出是一个序列化的信号值。这个约束极大降低了下游回测框架的适配成本,也方便对不同模型生成的因子做横向对比。

实测下来,一个小时内可以处理大约30到50篇报告,每篇报告平均能生成5到10个候选因子,其中经过初步筛选后值得上回测的约有1到2个。这个产出效率放在传统人工流程里是不可想象的。人工读报告加实现因子,一天能完成一到两个精细因子已经很不错了。

当然,模型输出不可能一次就完美。项目设计了自动重试和校验机制。如果模型输出的代码语法错误或者字段缺失,系统会把错误信息反馈给模型,要求修正,最多重试三次。如果三次后仍然不合格,就标记为失败样本,进入人工复核池。从实际效果看,第一次输出的合格率大约在六成左右,经过一轮修正后能达到九成以上。

2.3 可解释性:从命名、逻辑说明到归因展示

可解释性是这个项目的最大卖点,也是很多人最容易误会的点。有读者以为所谓可解释只是给因子起一个中文名字、写一段注释就算完事,但真正用起来远不止这么简单。

LLMFactor里的可解释性分三层。第一层是因子命名和单因子逻辑说明。因子不是生成一个代码了事,而是模型会补充一段“逻辑依据”,说明这个因子试图捕捉什么经济现象,为什么这样的数值变化会被视为超预期信号。第二层是归因层面的解释。当因子进入多因子组合后,系统会记录每个因子在组合中的权重变化,以及在某一期收益归因中的贡献度。第三层是逻辑链路检视。这一步是我自己加上去的,把因子代码反向映射回原始文本,标注出代码中每个关键计算步骤对应原文中的哪句话。

这个反向映射真的很重要。一旦回测出现意外的结果,研究员可以直接沿着映射链路去检查到底是文本逻辑有偏,还是代码实现有问题。有一次模型生成一个“存货周转与毛利率剪刀差”因子,回测分组收益呈现明显的非线性。当时数据组怀疑是财务数据对齐出了问题,但通过映射链路反查,发现是模型对“剪刀差”的理解偏了,把两个指标的差值方向搞反了。这种定位效率在传统流程里要靠两个组来回扯皮才能解决。

3. 实操过程:从零到一份可回测的盈利因子

3.1 环境准备与依赖安装

LLMFactor的核心代码全部是Python实现。基础环境主要用到几个库,包括大模型推理的客户端、数据处理和回测。如果你是跟着这个项目自己搭建环境,建议用虚拟环境隔离依赖。

# 创建虚拟环境 python -m venv llmfactor_env source llmfactor_env/bin/activate # 安装必要依赖 pip install pandas numpy pip install openai # 大模型API客户端,可替换为其他模型服务商 pip install tqdm pyyaml # 回测框架按需安装 pip install alphalens

这里提一个经验:不要在一开始就追求搭建完整的工程系统,先把单条链路跑通。我最开始只写了一个Python脚本,输入一篇报告文本,输出一个JSON文件,里面有因子代码和解释。跑通之后再逐步加上重试机制、数据校验、批量调度这些模块。上来就想做分布式处理的话,调试成本会非常高。

3.2 构建提示词与抽取管线

现在展示一个核心的提示词模板设计。这个模板经过多轮迭代,目前稳定可用。

factor_extraction_prompt = """ 你是一位资深的量化策略研究员,请阅读下面这段文本,从中提炼出一条可实现的盈利因子逻辑。 文本内容: {document_text} 要求: 1. 因子必须能从给定的量价数据或财务数据中计算出来,不能依赖无法获取的数据。 2. 请严格输出JSON格式,包含以下字段: - name: 因子名称,简洁且能反映逻辑 - summary: 逻辑依据,用一段话解释因子试图捕捉什么现象 - code: 完整的Python函数代码,函数名为compute_factor - params: 参数说明列表 - data_dependency: 该因子依赖的数据字段清单 - risks: 使用该因子需要注意的风险和局限 参考示例: {examples} 请只输出JSON,不要输出其他解释。 """

代码生成部分有一个细节容易踩坑:模型有时会生成不兼容的代码风格,比如用了pandas库中版本不一致的API,或者访问了不存在的列名。我的解决方案是在提示词里明确指定函数只接收一个dataframe参数,所有中间计算必须通过临时列实现,最后通过一个列名为score的列输出。同时在接收模型输出后,先跑一遍语法检查和假数据测试,通过后才进入正式回测。

3.3 因子回测与显著性检验

生成代码只是第一步,因子能否赚钱要由回测说了算。项目的回测流程分为三层。

第一层是有效性检验,计算IC均值、ICIR、t统计量。第二层是分层回测,按因子值排序分十组,看多空组合的累计净值曲线和多头组合相对基准的超额收益。第三层是稳健性检查,包括分年度收益、不同股票池内的表现、与已有因子的相关性分析。

这里给出一个分层回测的核心代码示例,用的是alphalens框架。

import alphalens as al # factor_data是模型生成的因子值表 # prices是交易日的价格面板数据 factor_data = al.utils.get_clean_factor_and_forward_returns( factor=predicted_score, prices=prices, periods=(1, 5, 10), quantiles=5, groupby=industry_group ) # 计算分层收益 al.tears.create_summary_tear_sheet(factor_data) # 计算IC序列 ic = al.performance.factor_information_coefficient(factor_data)

判断一个因子值不值得继续投入,我个人的标准是:IC均值绝对值大于0.02,ICIR大于0.3,多空组合夏普比率大于1.0,同时与已有因子池的平均相关性低于0.5。这些阈值会随着股票池和数据频率变化,但对日频截面因子来说是比较通用的底线。

3.4 因子池管理与迭代记录

当生成因子数量积累到几百个以后,管理就变成核心问题。项目的因子管理系统包含三个层次:原始因子池、精筛因子池、上线因子池。

原始因子池是所有通过语法和逻辑检查的因子,哪怕表现一般也保留,因为可能在特定市场环境下发挥作用。精筛因子池是通过IC和分层回测初筛的因子,后续用于相关性聚类和合成。上线因子池是经过样本外验证并接入实盘模拟的因子,数量控制在个位数到十几位。

这个分池逻辑核心是避免过度拟合。很多因子单独看表现不错,但加入因子池后发现和已有因子高度相关,对组合的边际贡献很小。所以系统会在因子入库前自动计算新因子与已有因子池的相关性矩阵,如果相关性超过阈值,就建议进行合成或直接丢弃。

4. 常见问题与排查技巧实录

4.1 模型输出不稳定,格式漂移怎么办

大模型输出格式漂移是最常见的问题。有时候同一个提示词,上午输出正常JSON,下午就开始在JSON前后加说明文字,或者漏掉某个字段。这种不稳定性在小模型上尤其明显,大模型会好一些,但也不能完全避免。

我目前采用的方案是“宽容解析加自动修复”的组合。宽容解析是说,先尝试用字符串查找的办法把最外层的JSON花括号提取出来,而不是直接用json.loads解析整个返回内容。自动修复是说,解析失败时,把解析错误信息连同原始返回内容一起回传给模型,要求它重新输出一个无额外解释的JSON。

实测下来,这种重试机制对格式漂移的恢复率非常高。另外有一个小技巧:把返回格式的约束放在提示词的最后一句,并加上“只输出JSON”的强化限定,格式错误率会明显下降。这个经验在多个模型上都验证过。

4.2 因子过拟合与未来函数问题

大模型生成的因子容易出现两类隐蔽问题:一类是常见的过拟合,另一类是未来函数。

过拟合的典型表现是,因子在训练区间表现优秀,但在样本外断崖式下跌。这往往是因为模型在生成因子时,隐式地利用了训练区间内已知的股票池分布特征。比如一个因子在某个特定行业比例下表现很好,但这是样本内的巧合。对此的对策是坚持做严格的时间序列切分,训练区间、验证区间、测试区间彻底隔离,因子筛选只能看训练和验证区间,测试区间留到最后一次性评估。

未来函数问题更棘手,也更容易被忽视。模型可能生成包含“当期季报发布日期前就能知道财报数据”这样隐含假设的代码。财务数据有发布时滞,直接用最新披露数据来预测当期收益,会把未来信息带进因子值中。解决方案是在数据层统一做严格的数据对齐,用数据快照替代原始财务报表。所有因子计算只能基于快照时间点之前可获得的真实数据,这个约束必须在数据层强制执行,不能依赖模型自觉。

我印象最深的是一次教训:有段时间回测效果极好,IC高达0.08,远超历史平均水平。后来排查发现,因子隐式地使用了“当日涨跌停股票名单”这个信号,而名单本身包含了当日已经涨停的信息,等于用结果预测结果。把数据对齐调整后,因子表现回到正常水平。这类问题靠回测本身很难发现,只有从数据流源头排查才能找到。

4.3 可解释性流于形式,怎么做实质校验

模型生成的解释文本有时候确实存在“一本正经胡说八道”的问题。文字读起来逻辑通顺,但仔细追溯后发现计算逻辑与文字描述并不完全匹配。比如描述里写“捕捉毛利率拐点”,代码里却是在计算营收增速的斜率。

我在项目里增加了一个校验步骤:将代码实现翻译成自然语言,再与模型生成的解释做同义匹配,不过这个自动校验的准确率目前还不高。更实用的办法是人工抽检,每周随机抽取一定比例的因子,由研究员对照原始文本和代码,逐项检查逻辑和描述的一致性。这个流程虽然需要人力投入,但对保证因子质量至关重要。

另外还有一个衡量的地方是:因子解释应该能回答“为什么这个因子有效”和“什么时候会失效”两个问题。如果模型只写了一句“该因子捕捉到优质股票的盈利成长性”,这种解释没有实际价值。理想的解释应该包含具体的适用条件、失效场景和微观经济逻辑。

4.4 API调用成本与批量处理效率

运行大模型抽取因子的成本是个现实问题。以一篇行业报告约五千字为例,调用一次模型的输入和输出token加起来在两千到三千之间。如果每月处理两百篇报告,几十万token的消耗并不算小,尤其是高频迭代场景下成本会快速累积。

我在实践中摸索出几个降本手段。一是用优先级分层:最便宜的小模型负责预筛选和格式转换,只有逻辑复杂、需要生成代码的报告才调用成本更高的大模型。二是做缓存去重:同一篇报告经过摘要压缩后,如果核心逻辑没有变化,不再重复调用模型,直接从缓存库取结果。三是批量抓取:把相似行业的报告合并成一组输入,减少重复的背景描述token耗用。

实测下来,这三招组合使用能把总体成本压缩到原来的四成左右,同时不牺牲太多输出质量。如果你只是个人做研究而非生产环境部署,用API按量付费完全可行,不用单独部署模型推理服务。

5. 后续扩展思路与个人经验心得

5.1 从单因子到因子组合:让大模型辅助策略构建

单因子成熟之后,更自然的延伸是让大模型参与因子合成和组合构建。目前这个方向我在尝试做两件事。

第一件事是大模型辅助因子合成。传统的因子合成是用IC_IR加权或者最大化复合IC的数学规划方法,但大模型提供了一条不同的路径:直接让模型阅读多个互相关的因子逻辑,从中发现它们共有的经济主题,再给出一个合成因子的计算框架。这种主题式合成的好处是合成后的因子仍然保有语义,而不是一个黑箱线性组合。

第二件事是大模型辅助风险解释。当组合在某段时间发生回撤时,传统归因只能告诉你“是某个行业暴露或市值风格拖累”,但大模型可以结合市场文本,给出更丰富的归因解释,比如“近期小市值因子回撤与市场流动性收缩预期相关”这样的定性判断。把定量归因和定性叙事结合起来,策略调整就有了更完整的决策依据。

5.2 给想尝试这个方向的朋友的几句真心建议

接触LLMFactor这个方向一年多,我想对准备自己做类似项目的朋友说几句实在话。

第一,不要迷信大模型输出。模型的优势是效率而不是准确度,所有生成的因子都必须经过严格的数据验证和逻辑校验。第二,数据基础设施永远是第一位的。如果财务数据对齐、停复牌处理、行业分类映射这些基础工作没做好,再强的模型输出的因子也是垃圾进垃圾出。第三,可解释性不是锦上添花,而是工程质量要求。没有解释的因子一旦出了线上问题,排查成本会非常高。

我自己踩过最大的坑就是一开始过度关注模型的提示词设计,花了很多时间去调模板、调少样本,结果发现因子质量的瓶颈其实在数据质量和对齐层面。后来把精力重新放到数据基础设施上,单因子质量立刻有了肉眼可见的提升。

这个项目的当前版本只是第一步。后续还有很多可以深挖的方向,比如引入更多非结构化数据源、把因子生成做成闭环迭代、利用模型的推理能力构建动态因子库。每一次迭代,都在重新定义“挖掘盈利因子”这件事的边界。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询