简介《Alpha掘金系列之五如何利用ChatGPT挖掘高频选股因子》是一份面向量化研究者、金融工程从业者及对大语言模型选股感兴趣的进阶读者的专题报告聚焦ChatGPT在因子挖掘与策略构建中的实际用法。资源包仅含1个PDF文件约2.21MB便于集中阅读与检索。报告先解析GPT与Transformer架构、相较LSTM的权重分配改进以及Scaling Law和RLHF三步训练流程随后介绍提示工程的角色—任务—指令公式、思维链提示等技巧。实战部分围绕周频价量变异系数因子、高频买卖盘力量因子展开并给出中证1000指数增强策略回测、代码输出测试与风险提示可帮助读者理解模型能力边界、复现研究框架并沉淀可验证的因子挖掘思路。已有1359人学习。1. 需求新因子的起点到底在哪做高频因子挖掘的人大概都经历过这种时刻论文里的公式抄完了回测跑出来 IC 只有零点零几换个窗口参数就翻车而且你根本分不清是数据口径出了问题还是因子逻辑本身站不住。这份方案要解决的正是「新因子从哪来」这个起点问题——把 ChatGPT 这类大语言模型当成因子生成器用提示工程把研究流程固定下来最终落到一个能在中证 1000 成分股上跑通的选股因子和指数增强组合。它适合两类人正在做量化方向毕设、课程设计需要一个完整因子研究闭环的学生以及要在团队里交付一份因子研究报告的从业者。整套流程分四段推进模型为什么能给得出像样的答案、提示怎么写才收敛、周频与高频两条因子线怎么构建回测、最后是踩过的坑和验收口径。2. 模型底座Transformer 的权重分配与 RLHF 的三步训练2.1 从 LSTM 的两个缺陷说起要让模型给出可用因子先得知道它的能力边界在哪。传统 LSTM 处理文本预测这类任务时有两个硬伤一是对句子里不同词无法区分重要程度所有输入被一视同仁地压进隐状态二是长距离信息提取能力弱句子一长前面的信息就丢得差不多了。2017 年那篇提出 Transformer 的论文把这两个问题一起解决了靠的是自注意力机制——让序列里每个位置与其他位置两两计算相关性再按相关性给不同部分分配不同权重上下文语义因此能被完整建模长序列也不再是负担。结构上Transformer 保留了编码器和解码器的主体框架编码器负责把输入压成带权重的表示解码器负责逐词生成。这条路线带来的直接后果是模型可以吃下更大的数据集、堆更多的参数语言模型的成长空间被彻底打开。参数规模的演进很能说明问题初代 GPT 大约 1.17 亿参数第二代到了 15 亿第三代直接冲到 1750 亿第四代又把输入从纯文本扩展到图像复杂问题上的准确性和洞察力明显上了一个台阶。理解这条演进线对做因子研究有实际意义——参数量越大模型对金融文本里那些隐含逻辑的捕捉越细但它同时意味着输出的随机性和不可解释性也在增加这一点后面会反复提到。2.2 Scaling Law 与 RLHF智能水平的两个来源参数堆上去只是必要条件真正让模型表现「像人」的是两件事叠加。第一件是涌现现象也就是 Scaling Law参数数量和训练数据量跨过某个门槛之后模型会突然表现出小模型完全不具备的能力比如举一反三、按示例推理。第二件是 RLHF即人类反馈的强化学习它把人类的偏好判断注入模型参数里让输出更贴近人真正想要的答案而不是统计上最可能的答案。RLHF 的训练分三步这三步值得拆开看因为它直接解释了为什么模型有时候会给出一本正经的错误回答。第一步从包含人类真实意图的指令集合里采样由标注团队原文披露是 40 名标注员对这些指令做标注然后在对话模型上做微调。第二步再次从指令集采样输入让模型对同一个问题生成多个不同回答由标注员对这些回答的好坏排序用排序结果训练一个打分模型。第三步采样新的指令作为输入用打分模型反过来优化模型的输出让回答朝着人类评分高的方向偏移。三步走完才有我们手里这个能对话、能写代码、能讲逻辑的模型。这套训练模式还带来了三种使用范式零样本没有任何训练示例靠已有知识和推理完成新任务、单样本给一组示例就能学会、少样本少量语料即可理解和推理类似语料。放到因子挖掘场景里我一般走少样本路线——在提示里塞两三个合格因子和两三个不合格因子的样例模型输出的收敛速度明显快于纯零样本。代价是提示变长、每次都得多花一点上下文预算但比起反复重问这笔账是划算的。3. 提示工程三段式公式、提示分类与思维链3.1 角色、任务、指令提示公式怎么写才收敛提示工程的核心是设计起始短语指导模型朝你要的方向生成。标准的提示公式由三个元素组成角色即模型在这次生成任务里扮演谁任务对需要生成的内容做清晰简短的叙述指令生成文本时必须遵守的规则。一般形式是「作为一个【角色】按照这些指示生成【任务】【指令】」。比如让模型做客服答疑可以写成「作为一名客服人员请生成客户询问的回复这些回复应当专业、准确、简洁」。限制提示的作用不只是让回答更好看它实际上是在向模型灌输一个角色起到约束行为的效果。角色越具体回答越有针对性。同理指令部分越详尽回答范围被压得越窄拿到想要结果的概率越高。最开始的提示可能是「作为一名资深的量化研究员请给出一个你认为行之有效的选股因子」模型会给你一个听起来合理但完全不能用的东西。接下来得加约束「该因子必须具有原创性、有较强的逻辑支撑、且应当有出色的业绩表现」。再往下还得限定因子类别、构建方式和使用数据范围——这一步做完模型才开始正确使用逐笔成交数据里的字段并且按提示要求用求均值的方式完成降频。把上面这套东西落成可复用的模板比每次手写提示靠谱得多# 提示模板把角色、任务、约束拆成独立变量便于批量生成与版本管理 PROMPT_TMPL 作为一名{role}请{task}。 约束条件 1. {c1} 2. {c2} 3. {c3} 输出格式先给出因子定义与计算公式再说明经济逻辑最后列出所需数据字段。 def build_prompt(role, task, constraints): # constraints 传长度为 3 的列表避免逗号堆叠导致模型漏读某一条 return PROMPT_TMPL.format( rolerole, tasktask, c1constraints[0], c2constraints[1], c3constraints[2], ) prompt build_prompt( role资深高频量化研究员, task设计一个仅使用委托价和委托量数据的选股因子, constraints[ 因子必须原创不能是已知的动量或反转类因子, 构建过程必须给出明确的数学表达式不得使用模糊描述, 输出需说明该因子为何在中证 1000 成分股上具备横截面区分度, ], )这段代码没有玄学关键在三点约束用编号列表而不是一句话连写模型漏读的概率会低很多角色和任务分开传参方便同一套模板换不同角色做对比实验输出格式固定成「公式—逻辑—字段」三段后面人工复核时按段检查不会漏掉字段确认这一步。实际使用时通常还会追加一轮对话把上一轮输出里含糊的地方单独拎出来追问比如「第三条约束里提到的标准化请给出具体公式和分母口径」。3.2 提示分类与思维链把复杂问题拆成可校验的步骤除了标准公式还有几类针对不同任务的提示方式可以在研究流程的不同环节各取所需。知识生成提示是把新信息与特定主题的已有知识结合生成新知识适合让模型在既有文献基础上做变形组合情感分析提示用于判断一段文本的情感倾向做新闻情绪因子时用得上强化学习提示通过给模型一组输入和奖励让它根据奖励调整行为对抗性提示则反过来让模型生成难以被分类的文本适合做因子的压力测试场景。这四类里知识生成和对抗性提示在因子挖掘中用得最多前者的产出直接就是候选因子后者可以用来检验因子是不是靠某个特定样本区间撑起来的。情感分析这类任务我实测过结论要写清楚模型对含有明确情感词的文本判断稳定但输入文本没有明确情感词时输出的不确定性会明显上升因为神经网络本身带随机性。整体准确率仍然可观但你不能把它当成确定性的分类器用必须留人工复核的环节。真正让复杂任务可用的是思维链提示也就是引导模型分步骤思考、把中间推导过程展现出来。举个例子IC 作为因子评价指标是有漏洞的。两个因子可以有几乎相同的 IC 值但因子值与收益率的相关性在不同分组区间差异巨大——A 因子 IC 是 0.22多头组表现很好B 因子 IC 是 0.25多头组反而最差。直接按 IC 排序选因子实盘效果可能和指标完全相反。解决思路是按分组给 IC 赋不同权重让多头组权重更高再求加权 IC。直接问模型「怎么改进 IC 指标」它给不出这个角度。改成思维链先描述两个因子 IC 相近但多头表现相反的现象问它问题出在哪模型会回答「每组内分别计算 IC再把组内相关系数求均值得到横截面 IC」——方向对了但逻辑有漏洞。接着在下一轮直接指出漏洞模型才会给出加权平均 IC 的方案。再补一句「A 股存在做空限制」它才会修正成给做多组更高权重。整个过程五轮左右每一轮都在纠偏。这条经验很值钱模型不是不能想深是你得把台阶一级一级给它铺好而且每一级都要人来校验。4. 因子落地周频变异系数与高频买卖盘力量的两条线4.1 变异系数因子5 日滚动与四个变体第一条线走中低频。让模型基于量价数据给出独特因子它给出的方案是在收盘价和成交量两个维度分别计算变异系数再相乘衡量股票的波动性和流动性。这个思路可以进一步变形把两个变异系数相除得到新的组合因子。用日频量价数据、取过去 5 天的价格和成交量做滚动计算公式是这样import numpy as np import pandas as pd def cv_factor(price_df, vol_df, window5): price_df / vol_df: index 为交易日, columns 为股票代码, 值已做前复权处理 返回调仓日截面上的四个因子值, 每行一只股票 mu_p, sd_p price_df.rolling(window).mean(), price_df.rolling(window).std() mu_v, sd_v vol_df.rolling(window).mean(), vol_df.rolling(window).std() li sd_p / mu_p # 价格变异系数波动与价格水平的比值 vli sd_v / mu_v # 成交量变异系数量的稳定性 latest -1 # 取窗口末行对应周频调仓日 return pd.DataFrame({ LI: li.iloc[latest], VLI: vli.iloc[latest], LIxVLI: (li * vli).iloc[latest], LI2VLI: (li / vli).iloc[latest], })参数上有几个点要交代清楚。window 取 5 是原文口径对应一周的交易日数取值变大因子会更平滑但衰减更慢取值变小噪声会吃掉信号分母用均值而不是标准差是为了把价格水平和波动幅度拆开否则高价股的因子值会被系统性放大最后取窗口末行是为了对齐「每周初开盘买入、每周最后一个交易日收盘卖出」的调仓节奏中间的行只在滚动计算时用不参与截面排序。这四个变体的差别在于对量价关系的假设不同相乘是认为波动和流动性同时恶化才有效相除是认为两者背离时信息量更大。4.2 回测口径与多头超额不足的归因回测范围是 2016 年到 2022 年 8 月的中证 1000 成分股周度调仓以每周初开盘价买入、每周最后一个交易日收盘价卖出。四个因子的表现放在一张表里看更直观因子IC 均值IC 的 T 值多空年化多空夏普多头年化超额LI-5.36%-8.078.35%0.51-1.09%VLI-2.79%-7.538.40%0.862.75%LIxVLI-5.29%-10.748.89%0.710.74%LI2VLI-3.11%-4.692.06%0.130.74%IC 均值为负不是坏事它说明因子值越低、未来收益越高与低波动异象一致。四个因子的 IC 的 T 值绝对值全部大于 2统计上站得住多空净值曲线除 LI2VLI 外走势也相对平稳。但问题出在最后一列多头组合年化超额收益最高只有 2.75%LI 甚至是负的。这就是典型的「指标漂亮、策略做不出来」——IC 是个对称指标多空两头都算贡献而 A 股实际只能做多多头组不赚钱这个因子就没法直接变成产品。这条线最终没有继续往下做原因就在这里不是因子无效是收益来源和交易约束对不上。4.3 高频因子3 秒快照的十档委托量价聚合第二条线换到高频。高频数据挖掘的拥挤度相对低挖出来的因子与传统的量价因子独立性也更强。这次把提示的数据范围死死限定住只能用委托价和委托量且必须原创。经过几轮引导模型给出买卖盘力量因子。落到实现上处理方式是对每只股票每天的 3 秒快照数据分别求出前十档的买入委托价、买入委托量、卖出委托价、卖出委托量再在日内求均值得到买盘力量、卖盘力量和买卖盘力量差异三个因子def force_factor(snapshot, base_price_colvwap): snapshot: 单只股票单日 3 秒快照, 含 bid_p1..bid_p10 / bid_v1..bid_v10 以及 ask_p1..ask_p10 / ask_v1..ask_v10, base_price_col 为当日基准价 bid_p snapshot[[fbid_p{i} for i in range(1, 11)]].mean(axis1) bid_v snapshot[[fbid_v{i} for i in range(1, 11)]].sum(axis1) ask_p snapshot[[fask_p{i} for i in range(1, 11)]].mean(axis1) ask_v snapshot[[fask_v{i} for i in range(1, 11)]].sum(axis1) base snapshot[base_price_col] # 委托价相对基准价的偏离度乘以委托量, 量纲被压到价格比例上, 可横截面比较 b_force bid_v * (1 - bid_p / base) s_force ask_v * (ask_p / base - 1) return { BForce: b_force.mean(), SForce: s_force.mean(), BSForce: ((b_force - s_force) / (b_force s_force)).mean(), }代码里有三个设计决策值得单独讲。第一委托量用十档求和而不是取单档是为了把靠近盘口的挂单力量整体纳入单档容易被撤单行为干扰。第二价格偏离度乘委托量本质是把「挂得多」和「挂得远」合成一个量挂得越远说明意愿越弱乘上 (1 - bid/base) 之后自然被折价量纲统一到价格比例上横截面上不同价位的股票才可比。第三买卖盘力量差异做了 (B-S)/(BS) 的归一化原始差值在不同股票之间没有可比性归一化之后取值范围收敛到 -1 到 1 之间逻辑上也更干净——它衡量的是买卖双方力量的失衡程度而不是绝对强度。基准价通常取当日成交量加权均价取收盘价也可以但收盘价会被尾盘异动带偏我一般优先用加权均价。4.4 衰减、降频与指增组合日频口径下的测试结果分化很明显因子IC 均值IC 的 T 值多空年化多空夏普多头年化超额BForce-0.24%-0.6118.74%0.9611.17%SForce-1.02%-2.874.06%0.226.57%BSForce1.13%7.0037.00%4.5117.29%买卖盘力量差异因子的表现最突出多空夏普 4.51最大回撤只有 4.88%多头年化超额 17.29%。买盘力量因子 IC 不显著但多空区分度好多头超额也有 11.17%。这说明日内 tick 里的委托价和委托量确实能预测次日横截面收益差异。但日频调仓的成本太高实际投资里基本吃不到这个收益所以必须降频。降到周频后买卖盘力量差异因子衰减太快、第二天基本失效只能保留买盘和卖盘两个单边因子它们的多头年化超额分别是 9.77% 和 10.20%多空单调性一般但多头组合还能用。最终选相对更稳的卖盘力量因子构建中证 1000 指数增强策略在单边千分之二的手续费率下年化超额收益 7.17%信息比率 0.57。这个数字不算惊艳但它是扣过成本的、能落地的数字比日频那个 37% 有意义得多。至于模型写代码的能力实测结论是常用的因子测试框架、组合优化函数它能给得比较准但细节必须逐行看——字段名对不对、库版本兼不兼容、有没有用到未来数据这三处最容易出问题。在模型给的代码上做微调研究效率提升是实打实的。5. 避坑排查五个最容易翻车的环节5.1 公式照抄回测 IC 趋近于零甚至反向现象是模型给的因子表达式看着没问题自己实现出来跑回测IC 在零附近晃或者方向跟预期完全相反。原因八成在数据口径不在因子逻辑价格没做前复权除权日附近的价格跳变会被变异系数当成真实波动快照数据没去重同一时间戳重复推送导致委托量被放大停牌日的空值被 fillna(0) 填掉成交量变异系数直接失真。解决顺序是先对齐字段字典再写代码拿单只股票、单日数据手工算一遍因子值跟代码输出对得上再上全样本。这一步看着笨但能省掉后面几天的排查时间。5.2 同一个提示跑两次因子完全不同现象是今天让模型生成因子明天用看起来一样的提示再问给的公式结构就变了实验没法复现。原因是大语言模型本身带随机性采样温度、上下文长度、甚至前几轮对话的残留都会影响输出。解决办法是把提示模板版本化管理每次调用的完整对话日志落盘存档同一个研究结论至少跑三次独立采样只保留重复出现的因子思路。那些只出现过一次、逻辑又特别绕的大概率是模型的即兴发挥直接丢掉。5.3 IC 显著但多头组不赚钱现象是 IC 的 T 值大于 2多空净值曲线漂亮可多头组合年化超额是负的或者接近于零。原因是 IC 是秩相关系数对多空两侧一视同仁而 A 股存在做空约束收益只能从多头组来。解决办法是评价体系里强制加两项一是分组单调性看十分位组合的收益是不是逐组递增二是多头超额把它跟 IC 并列作为硬指标。更彻底的做法是按分组给 IC 加权多头组权重更高用加权 IC 替代原始 IC 做初筛这条思路本身也是从模型的思维链对话里逼出来的。5.4 日频夏普 4.51实盘一上就亏现象是日频回测的多空夏普高得离谱换成实盘或者加上真实成本之后直接转负。原因有两个一是换手率日频调仓意味着每天全仓换一遍单边千二的成本一天就是千四一年两百多个交易日成本能把超额全部吃掉二是因子衰减高频因子往往只对次日收益有预测力第二天就失效你根本没有持有到第三天的理由。解决办法是回测阶段就把成本参数写死先按单边千二跑一遍看还剩多少再测因子在不同持有期上的 IC 衰减曲线衰减快的就老老实实降频别幻想靠交易频率堆收益。5.5 模型给的代码跑得通结果是错的现象是代码没报错能出数但因子值和手工计算对不上或者回测收益明显偏高。原因通常是三类字段名张冠李戴把卖一价当成买一价用、库函数的默认参数和预期不一致某些 rolling 默认 min_periods 处理会引入空值、以及最隐蔽的未来函数——用当日收盘数据算了因子却在当日开盘就下单。解决办法是三层校验单票单日手工对数值、随机抽十个交易日做逐行断点、以及把因子计算和平仓时点的时间戳打印出来看有没有重叠。代码是模型写的责任是你的这一条没有捷径。6. 验收与答辩三层校验和一条自证链路验收这套东西我一般分三层走每层都有明确的通过标准。数据层看字段对齐和时点正确随机抽十只股票、五个交易日手工复算因子值误差超过千分之一就退回重做因子层看 IC、分组单调性和多头超额三项是否同时成立只有 IC 显著而多头不行的一律标记为「不可直接使用」组合层看扣费后的年化超额和信息比率卖盘力量因子那条线给出的是 7.17% 和 0.57这两个数必须是在单边千二成本假设下跑出来的换成本参数就要重跑。层级校验项通过标准数据层复权、快照去重、停牌处理抽样复算误差小于千分之一因子层IC 的 T 值、分组单调性、多头超额T 值绝对值大于 2 且多头超预期为正组合层扣费后年化超额、信息比率、最大回撤成本假设写死在配置里可一键复跑答辩时最容易被追问的一点是「这因子到底是模型想出来的还是你想出来的」。我的答法是把提示链路完整摆出来第几轮问了什么、模型答了什么、哪一轮的回答有明显漏洞、我怎么纠偏的、最后落地的公式和模型最初给的版本差在哪。这份对话日志比任何解释都有说服力它证明的是研究流程可控而不是把功劳推给工具。第二个高频问题是样本外表现回答时不要只报样本内的漂亮数字把因子衰减曲线和降频后的表现一起给主动说出「日频夏普 4.51 但扣费后不可用所以降到周频」比等着被问出来强得多。从那以后我每次让模型出因子都强制先把提示模板和历史对话存档再动手写一行代码——不是为了留证据是因为翻车的时候你只有这份日志能告诉你问题出在提示上还是数据上。希望帮到你。本文还有配套的精品资源点击获取