ChatGPT实战指南:高频选股因子挖掘与回测全流程

发布时间:2026/10/13 12:51:46
ChatGPT实战指南:高频选股因子挖掘与回测全流程 简介这份PDF是Alpha掘金系列第五篇聚焦如何利用ChatGPT挖掘高频选股因子适合量化研究员、金融工程学习者及对NLP投资感兴趣的读者。内容从大语言模型演进讲起对比LSTM与Transformer机制拆解ChatGPT背后的Scaling Law与RLHF三步训练流程并系统梳理提示工程公式、思维链提示等使用方法。包体为单个PDF文件压缩后约2.21MB完整涵盖模型原理、提示指南、因子实战与代码测试四大模块。目前已有1359人学习。报告中不仅给出中低频价量变异系数因子的测试结论还重点展示了高频买卖盘力量因子在日频及周频下的表现其中卖盘力量因子构建的中证1000指数增强策略年化超额收益率达7.17%同时附有ChatGPT代码能力测试与微调建议可帮助读者提升因子研究与回测效率。1. 让ChatGPT挖高频选股因子先想清楚它替你干哪一段活Alpha掘金系列第五篇讲高频选股因子工具换成ChatGPT。先给一个反直觉的判断它能写出一堆能跑的因子代码但别指望它从零发明alpha。它真正做的是把“提出一个因子”到“验证一个因子”的成本从小时级压到分钟级。高频数据结构复杂恰恰是它最容易编造列名、翻车的地方。这篇不讲AI自动交易只讲怎么让它当研究员助理提方向、写初版代码、陪你回测和排查。动手前先想清楚你缺的是点子还是验证点子的流水线如果是后者下面这套流程可以照抄。2. 高频选股因子的数据边界与AI介入点给ChatGPT当研究助理的第一课2.1 高频因子的数据边界盘口快照与分钟线先把“高频”说清楚。这里不是指高频交易而是指因子的采样频率达到分钟甚至tick级。对选股模型来说日频因子、分钟级因子、tick级交易信号是三条完全不同的路线。“高频选股因子”通常指从日内快照或分钟线里聚合、但用于持仓数小时到数天的选股信号。它保留了日内微观结构信息又不至于被交易成本完全吃掉这也是它在Alpha掘金这类因子体系里被单独拎出来的原因。做这类因子绕不开三类数据。逐笔委托和逐笔成交最细但错单、对倒标记、合并成交都会干扰计算盘口快照提供多档买卖挂单量是订单流类因子的主原料分钟K线由成交聚合而来量纲统一适合初筛和回测。它们的共性是必须先清洗成一致口径才能交给模型。下面这张字段表就是你喂给ChatGPT时要固定的最小schema。字段名含义注意事项datetime快照时间戳交易日内的本地时间跨数据源必须对齐bid1_price / ask1_price买一价 / 卖一价是限价单报价不是最新成交价bid1_vol / ask1_vol买一量 / 卖一量单位必须统一手和股不能混用last_price最新成交价快照时刻最后一笔的成交价amount成交额有的是分钟累计有的是单笔成交口径要确认字段口径一旦不统一同一个因子在不同数据源上算出来的相关性可能跌到0.5以下。我习惯在数据层先跑一个自检时间戳乱序、挂单量为负、最新价超出涨跌停幅度这三类脏数据不修完后面所有因子都是纸面alpha排查起来也最折磨人。2.2 ChatGPT在挖掘流程里的三种角色很多人把ChatGPT当成“因子生成器”直接问“给我一个高频选股因子”然后拿了就跑。我一般会把它拆成三个角色分别管控风险。角色一是点子库。让它从订单流失衡、买卖价差、日内反转、已实现波动率这些学术方向上发散产出“候选假设”而不是“成品因子”。它可能提到十个方向其中两三个在A股有先例五六个是常见学术概念剩下一两个是它自己拼接的。没关系方向列表本来就是用来筛的不是用来信的。角色二是初版写码工。把假设翻成pandas函数这一步它的效率远高于人。但前提是你在prompt里给清楚schema、列名、空值策略否则它会用“看起来合理”的列名写代码跑起来全是KeyError。给真实字段名不给它自由发挥的空间。角色三是代码评审员。把已经跑通的回测框架丢给它让它找未来函数和数据泄漏比如shift方向用错、滚动均值包含了当前信号之后的信息。这一步被严重低估。在“找茬”类任务上它的遗漏率往往比人低因为它不会被“这个因子好像很有道理”的主观期待带偏。这三个角色对应三件事AI负责定义搜索空间、写第一版实现、复查低级错误数据清洗、口径定义、存活判断必须人来管。生成和验收不要放在同一轮对话里否则你会被它自信的语气带偏。2.3 先搭一条最小流水线在让AI生成因子之前确保你手里已经有下面四个模块。缺一个后面所有因子都只能在研报里发光。数据清洗模块输入原始快照输出以(sec_code, datetime)为索引的长表处理缺失、乱序、异常挂单量。因子计算模块统一函数签名factor(df)-Seriesdf内已按股票和时间排序函数内部严禁使用未来数据。截面处理模块每个时刻截面上独立做去极值和zscore必要时做市值中性化。评估模块计算IC、IR、分组收益、衰减曲线和换手率。流水线的顺序不能乱。高频数据量很大清洗一次可能跑几十分钟如果因子函数都按统一签名实现清洗结果可以复用后面的因子批量生成才有意义。有了这条流水线ChatGPT生成的因子只要满足签名就能直接进入评估环节一天刷出二十个候选因子绝不是问题。没有流水线你就会陷入“一个因子做三天三天发现是数据错”的死循环。3. 用ChatGPT批量生成候选因子提示词、代码和初筛的一体化流程3.1 提示词模板把schema、口径和约束一次说清先给一份我已经改过很多遍、踩过无数坑的prompt模板。核心不是让ChatGPT自由发挥而是逼它按接口输出。你是一名高频量化因子研究员。输入数据为每分钟快照长表结构字段如下 datetime, sec_code, bid1_price, bid1_vol, ask1_price, ask1_vol, last_price, amount 约束 1. 计算时只能使用当前行以及更早的数据禁止使用任何未来信息 2. 返回的因子Series必须与输入索引完全一致 3. 因子必须能从订单流、买卖价差或日内波动角度解释。 任务 提出3个候选因子 每个因子输出三部分公式说明、Python/pandas实现代码、方向假设因子值越大未来5分钟收益越__。 同时给出每个因子的建议参数搜索范围和潜在失效条件。 先输出因子说明表格再输出代码。这份模板里最容易漏掉的是“先输出表格再输出代码”。ChatGPT面对开放任务会自由发挥返回一大堆描述性文字而不是可测试的接口。把输出格式强制定住你才能批量处理它的回答。另一个小习惯是让AI每轮只做一件事。先让它输出因子表格你确认方向合理后再让它展开写代码。一次让它给十个因子加十个实现结果里能直接跑通的往往不到一半而且你很难定位是逻辑错还是幻觉错。提示不要在prompt里写“请给出最优参数”改成“给出建议搜索范围”。否则它会拍脑袋定一个数你还要花时间证明它在过拟合。3.2 订单流失衡因子一个能直接跑通的实现订单流失衡OFI是高频研究里被反复验证的方向。核心思想是当盘口买一档和卖一档的挂单量发生变化时短时间内价格会被推向挂单更厚的一侧。实现并不复杂难在窗口参数和组内排序。import pandas as pd import numpy as np def ofi_factor(df: pd.DataFrame, window: int 10) - pd.Series: # 仅在同一只股票内计算盘口价格变动 bid_up df[bid1_vol].where(df[bid1_price] df[bid1_price].shift(1), 0.0) bid_down df[bid1_vol].where(df[bid1_price] df[bid1_price].shift(1), 0.0) ask_up df[ask1_vol].where(df[ask1_price] df[ask1_price].shift(1), 0.0) ask_down df[ask1_vol].where(df[ask1_price] df[ask1_price].shift(1), 0.0) ofi (bid_up - ask_down) - (bid_down - ask_up) # 分钟窗口内滚动求和时间窗口由window控制 return ofi.rolling(window).sum().fillna(0.0)逻辑说明买一价上移时原来挂着的买盘量视为新增买压卖一价下移时原卖一量视为卖压减少反过来同理。四行diff逻辑就能把盘口两边的压力变化压缩成一个序列。window是滚动窗口对分钟数据来说window10即约十分钟的订单流累计。参数说明window常见取5、10、20。只在一个窗口上IC高不算数三个相邻窗口都稳定才有保留价值。fillna(0.0)是为了避免前N行为空但注意这个填充值本身会影响截面标准化如果你发现因子覆盖率高但有效样本少先检查是不是这个填充把大部分值变成了同一个数。调用这个函数前必须按sec_code和datetime排序否则shift(1)会把上一只股票的盘口价格拉到当前股票这一行来对比形成跨标的伪数据泄漏。这是AI代码里最隐蔽的bug之一。def standardize(factor_s: pd.Series, universe: pd.Series) - pd.Series: # 同一时点截面上的标准化不允许混入其他时点 s factor_s[universe].clip( factor_s[universe].quantile(0.01), factor_s[universe].quantile(0.99) ) return (s - s.mean()) / s.std()说明标准化必须按时刻分组做。如果全天的因子值一起算zscore相当于混入了不同时点的截面信息截面相关性计算全是错的。去极值用1%和99%分位数比3σ更耐极端单子。3.3 批量生成与初筛先排除垃圾再谈eta批量挖掘不等于让AI生成几百个因子然后全部跑回测。更稳的做法是先让它按模板生成20个左右跑完初筛留下5个再拿这5个去做相关性去重。初筛阶段只看三件事覆盖率、方差、两两相关性。factor_lib { ofi_5: lambda df: ofi_factor(df, 5), ofi_10: lambda df: ofi_factor(df, 10), sign_mom: lambda df: sign_momentum(df, 10), } stats {} for name, func in factor_lib.items(): s func(sample_df) stats[name] { coverage: s.notna().mean(), std: s.std(), zero_ratio: (s 0).mean(), } factor_panel pd.DataFrame({k: f(sample_df) for k, f in factor_lib.items()}) high_corr factor_panel.corr().abs().stack() high_corr high_corr[high_corr 0.7]初筛目的是过滤不是选冠军。coverage低于0.9先丢std接近0说明列名错位或填充值把因子压平了相关性高于0.7的因子大概率同源保留逻辑最简单的那个。这一步不要用ChatGPT来评奖——它会偏向自己生成的历史表现好的因子而那个因子往往只是过拟合。4. 高频因子回测与参数校准AI给的是建议不是参数结论4.1 IC、IR、换手率先卡指标再谈alpha高频因子回测和日频因子的指标口径很不一样。日频IC动辄0.05高频因为噪声大、样本多mean(|IC|)超过0.02就已经是值得留下跟踪的信号。下面是我常用的三个卡口。指标高频场景下的含义建议阈值IC因子值与未来收益的截面相关系数均值绝对值大于0.02才值得关注IRIC均值除以IC标准差大于0.3说明信号稳定否则是运气换手率持仓组合每期股票替换比例单期超过50%要警惕成本吞噬IR比IC重要得多。一个IC均值0.03但标准差极高的因子实盘表现会像过山车很难坚持拿住。反过来IR大于0.3的因子即使IC看起来不高亏损曲线通常也更平滑。4.2 交易成本与滑点高频因子的收益消失高发区高频因子天然高换手。你以为赚的是选股alpha实际上赚的是流动性的钱只要成本模型更贴近现实收益就明显缩水。我一般准备三档成本假设来做验收。成本档双边总成本加滑点用途乐观档5bp研究阶段看方向不决定去留保守档15bp策略参数筛选时使用极保守档25bp提交实盘前必须通过的一关如果因子只在乐观档下为正直接请出因子池。极保守档还能稳定为正才说明它对成本有足够的缓冲。一个经验持仓周期至少要大于5根bar除非你有一套独立的冲击成本模型否则短持仓很难扛住真实成本和滑点。4.3 参数邻域验证一个可复用的脚本AI经常给你推荐window10, hold5这种点估计。我不建议直接采信而是跑参数邻域window取5、10、15hold取3、5、10两两组合都看一遍。一个真因子应该在参数邻域里表现连续稳定而不是只在一个点上发光。def walk_forward_ic(factor, fwd_ret, min_obs10): # factor和fwd_ret都是(asset, time)双层索引的Series ic_list [] for dt in sorted(factor.index.get_level_values(time).unique()): f factor.xs(dt, leveltime).dropna() r fwd_ret.xs(dt, leveltime).reindex(f.index) if len(f) min_obs: ic_list.append(f.corr(r)) if len(ic_list) 0: return np.nan, np.nan return np.mean(ic_list), np.std(ic_list)说明该函数在每个时点做一次因子值和未来收益的截面相关得到IC序列后返回均值和标准差。min_obs是有效股票数下限避免某时段只有三五只票时算出虚假高相关。fwd_ret的定义决定了你测的是多久的未来收益常见做法是shift(-5)的5期收益。参数邻域验证时如果IC的符号会在邻域内漂移说明因子对参数过于敏感这是过拟合的典型信号。反过来从window5到window20IR都稳定在同一水平说明它对采样频率不敏感可以放心一点。最后再把最后20%样本切成“从未见过的数据”专门做一次验证这是对抗AI生成结果里隐性过拟合的后悔药。5. 高频因子挖掘的常见问题排查五条实盘级踩坑记录以下五条按出现频率排序基本覆盖了用AI挖高频因子时最常翻车的环节。5.1 分组收益不单调中间段乱跳现象按因子值分成五组第一组收益很负第五组很正中间三组完全没有梯度甚至第四组比第五组还高。原因最常见的是收益对齐错位。因子用了t时刻的盘口数据收益却提前用了同一根bar的尾部数据或者shift方向用错导致“下一根bar”并不是真正的下一交易时段。解决把收益口径强制改成“信号bar之后下一根bar开盘买入持有若干根bar后的收益”并在生成fwd_ret时剔除涨停买入、跌停卖出这类无法成交的样本。这个动作不要省略ChatGPT生成的代码几乎不会帮你处理撮合边界你要自己补上。5.2 回测收益漂亮实盘净值不动现象模拟盘稳稳跑赢小额实盘跑了一个月就跑平甚至跑输一看手续费明细就明白问题出在哪。原因回测成交价用了信号bar的收盘价或次bar收盘价忽略了盘口深度或者成本假设停在乐观档滑点完全没计入。解决在回测引擎里强制加入“成交价等于次bar开盘价加买卖方向滑点”的规则并用第4章提到的保守档成本跑一遍。另外一个自检习惯是每天记录因子组合的换手率凡是单期换手超过50%的因子先降权等成本模型完善后再放出来。5.3 生成的几十个因子相关性全在0.8以上现象兴致勃勃挖了一堆因子做完相关性矩阵发现全是“亲戚”放进模型里不贡献任何增量。原因ChatGPT在相同schema和相同prompt的约束下很容易生成同源公式。比如所有因子都围绕“收盘价相对开盘价的涨幅”做各种变形数学结构上本质是同一个东西。解决初筛阶段就做相关性聚类按簇保留一个代表。然后让ChatGPT基于“已经有下面这些因子”重新提正交方向并在prompt里明确列出已有公式逼它换数学结构比如从价格类换到波动类、从水平值换到变化量。5.4 同一段代码换个数据源结果完全变脸现象用A数据源算出的IC是0.05换成B数据源的同字段分钟数据IC变成0.005因子瞬间失效。原因列名含义或单位不一致。有的源买一量单位是手有的是股有的时间戳是本地时间有的带时区复权因子没处理直接影响差分和收益率计算。解决建一张字段口径映射表把所有源清洗成统一schema后再进入因子工厂。这件事要排在AI生成因子之前做否则排查起来非常痛苦。AI可以帮你写清洗脚本但它不知道你的数据“脏”在哪里这是必须人工盯的环节。5.5 迭代到第三轮因子变成不可解释的黑匣子现象为了让IC更高不断追加差分、比值、平方项最后因子变成一个无法解释的怪物换一个时间段立刻失效。原因让AI自己评论自己推荐的因子是一种反馈放大。你给它“IC更高”的奖励信号它就会在那个方向上走极端直到过拟合。解决每一轮都要求AI输出“失效条件”和“逻辑假说”验收时把可解释性放在统计显著性前面。因子不是越多越好是越可维护越好。一个说不出经济学理由的因子即使IC再高我也不会放进实盘池。6. 一个提效技巧让ChatGPT给因子做失效前体检最后一招讲怎么提前发现一个因子快不行了而不是等它拖累组合净值后才后悔。我现在的例行公事是因子入库后每两周跑一次IC衰减曲线。衰减曲线看的是把信号从未来1根bar逐步换成未来10根barIC会怎么变化。一个健康的因子应该是单调衰减——信号越旧预测力越弱。如果它在第1根bar上很低、到第4根bar反而反弹说明它大概率吃了某根异常bar的收益或者隐藏着未来信息泄漏。def ic_decay_curve(factor, ret, max_lag10): # factor: (asset, time)索引的因子值 # ret: 同一索引的bar收益 decay [] for lag in range(1, max_lag 1): fwd_ret ret.groupby(levelasset).shift(-lag) # 未来第lag期收益 ic_lst [] for dt in factor.index.get_level_values(time).unique(): f factor.xs(dt, leveltime).dropna() r fwd_ret.xs(dt, leveltime).reindex(f.index) if len(f) 10: ic_lst.append(f.corr(r)) decay.append(np.mean(ic_lst)) return decay拿到衰减曲线后再把这条曲线丢给ChatGPT让它按衰减形状做诊断是换手太快不适合中频持仓还是因子捕捉的是不可持续的一次性冲击或者窗口参数应该调大。注意AI给的诊断只是建议最后你还是要看数据。衰减曲线在某个lag上突然拉高基本是收益对齐又出了问题先去查fwd_ret的定义不要试图给异常编造逻辑。我的习惯是把因子轮换变成制度而不是靠灵感。每个因子入库时都要附带一个失效条件每次体检先跑失效条件再决定降权还是剔除。这样ChatGPT挖出来的不是一次性彩票而是一条能持续复用的研究管线。这条路我也踩过不少坑最深的那个是总想让AI一口气给我“最好的因子”。后来想明白了最好的因子永远是下一个而你真正需要的是让上一个因子体面退场的方法。希望帮到你。本文还有配套的精品资源点击获取