新闻详情

新闻详情

首页 / 资讯中心 / 详情

ChatGPT量化因子挖掘:高频选股因子生成与回测实战

发布时间:2026/10/2 4:45:01来源:尧图网络
ChatGPT量化因子挖掘:高频选股因子生成与回测实战
简介这份国金证券金融工程专题报告聚焦ChatGPT在量化选股中的实战应用面向量化研究员、因子挖掘从业者及对AI选股感兴趣的进阶学习者。报告系统梳理了ChatGPT的模型原理与演进逻辑重点讲解提示工程的使用方法包括角色、任务、指令三要素提示公式及思维链提示等高级技巧并给出因子挖掘的完整测试流程。资源为1个PDF文件压缩包约2.16MB内容涵盖周频价量变异系数因子构建、高频买卖盘力量因子测试以及基于卖盘力量因子的中证1000指数增强策略回测结果同时附有ChatGPT代码输出能力的实测评估与风险提示。目前已有247人学习。读者可借此掌握将大语言模型引入因子研究的思路框架理解提示设计对因子有效性的影响并参考报告中的IC表现、年化超额收益与信息比率等指标评估策略的可行性与局限。1. 从一份券商研报说起ChatGPT 到底能不能挖出高频选股因子2023 年 4 月国金证券发了一篇叫《Alpha 掘金系列之五如何利用 ChatGPT 挖掘高频选股因子》的研报在量化圈子里传得挺开。它做的事情说白了就一句话把高频量价数据丢给 ChatGPT让它自己写代码、自己算因子、自己筛因子最后拼出一个能用的选股信号。这件事放到今天看依然有意思因为它绕开了传统因子挖掘里最耗人的环节——人工试错。传统做法是研究员先想一个逻辑比如“开盘半小时成交量突然放大可能预示日内反转”然后手写公式、回测、调参一轮下来两三天。ChatGPT 的路子是反过来你把数据字段和任务目标用 Prompt 描述清楚让它批量生成候选因子表达式再用程序自动回测筛选。人从“写因子”变成“审因子”效率差一个量级。这篇东西适合两类人看。一类是做量化研究但被因子枯竭卡住的想知道 ChatGPT 在因子挖掘上到底能帮到什么程度、边界在哪另一类是有 Python 基础、想把这套流程跑通但不知道从哪下手的。下面我按自己复现这套方案时踩过的路把 Prompt 设计、数据准备、因子生成、回测筛选、避坑点一层层拆开讲。2. 高频因子挖掘的完整链路从 Prompt 到因子表达式2.1 为什么选高频量价数据而不是财报数据高频因子和基本面因子最大的区别在数据频率和信噪比。财报数据一年四个点因子逻辑清晰但拥挤严重高频量价数据是分钟级甚至 tick 级信息量大但噪声也大人工挖因子的试错成本极高。这恰恰是 ChatGPT 能发挥的地方——它不怕试错你让它生成 200 个候选表达式程序跑一遍回测留下 IC 显著的那几个就行。常见的高频数据字段包括开盘价、最高价、最低价、收盘价、成交量、成交额、成交笔数、买卖盘口数据。国金那篇研报主要用的是分钟频的量价数据因为这类数据获取门槛相对低A 股 Level-1 行情就能覆盖大部分字段。我一般会把数据整理成一张宽表每行是一个时间戳每列是一个字段股票代码单独一列。这样后面让 ChatGPT 生成因子表达式时它只需要引用列名就行不用关心数据怎么来的。import pandas as pd import numpy as np # 假设原始数据是分钟频字段datetime, stock_code, open, high, low, close, volume, amount df pd.read_parquet(minute_bar.parquet) # 按股票分组计算日内衍生字段 df df.sort_values([stock_code, datetime]) df[ret] df.groupby(stock_code)[close].pct_change() df[vwap] df[amount] / df[volume].replace(0, np.nan) df[vol_ma5] df.groupby(stock_code)[volume].transform( lambda x: x.rolling(5, min_periods1).mean() ) df[amplitude] (df[high] - df[low]) / df[close].shift(1) # 只保留需要的列方便后续 Prompt 引用 cols [datetime, stock_code, open, high, low, close, volume, amount, ret, vwap, vol_ma5, amplitude] df df[cols].dropna(subset[ret]) print(df.shape) print(df.columns.tolist())这段代码做了三件事按股票分组算收益率、算 VWAP成交量加权均价、算 5 期成交量均线和振幅。参数上注意min_periods1是为了避免开盘前几分钟数据被全部丢掉replace(0, np.nan)是防止成交量为零时除零报错。跑完之后你会得到一张干净的宽表列名就是后面 Prompt 里要引用的字段名。2.2 Prompt 怎么写才能让 ChatGPT 吐出可用的因子表达式这是整套流程里最关键的环节。Prompt 写不好ChatGPT 给你的东西要么是废话“可以计算动量因子”要么是没法执行的伪代码。我的经验是把 Prompt 拆成四个部分角色设定、数据字段说明、输出格式约束、示例。角色设定让它进入量化研究员的状态数据字段说明告诉它有哪些列可以用输出格式约束是最重要的——必须要求它输出 pandas 可执行的表达式而不是自然语言描述示例给一两个让它知道你要的粒度。PROMPT_TEMPLATE 你是一名量化研究员擅长从高频量价数据中挖掘选股因子。 我有如下字段的分钟频数据 - open, high, low, close: 开盘价、最高价、最低价、收盘价 - volume: 成交量 - amount: 成交额 - ret: 分钟收益率 - vwap: 成交量加权均价 - vol_ma5: 5期成交量均线 - amplitude: 振幅 请生成 {n} 个高频选股因子表达式要求 1. 每个因子用一行 pandas 表达式表示输入是 DataFrame df输出是 Series 2. 因子逻辑要有金融含义不要随机组合 3. 表达式里只能使用上述字段和 numpy 函数 4. 输出格式为 JSON 列表每个元素包含 name 和 expression 两个字段 示例 {{name: volume_ratio, expression: df[volume] / df[vol_ma5]}} {{name: price_position, expression: (df[close] - df[low]) / (df[high] - df[low] 1e-8)}} 参数说明{n}控制生成数量我一般一次让它生成 20 到 30 个太多了质量会下降。1e-8是防止分母为零的常见写法。输出 JSON 是为了后面程序解析方便不用去正则匹配自然语言。拿到 ChatGPT 的返回后先做一轮语法检查把不能执行的表达式过滤掉。这一步能筛掉大概 10% 到 20% 的废品。import json def parse_factors(response_text): 解析 ChatGPT 返回的因子列表过滤掉语法错误的 factors json.loads(response_text) valid [] for f in factors: try: # 用一小段数据试跑看表达式能不能执行 test_df df.head(100).copy() result eval(f[expression], {df: test_df, np: np}) if isinstance(result, pd.Series) and result.notna().sum() 50: valid.append(f) except Exception as e: print(f因子 {f[name]} 执行失败: {e}) return valid这段代码的核心是eval试跑。注意eval有安全风险生产环境里应该用ast模块做白名单校验或者用numexpr替代。我这里为了演示方便直接用eval实际跑的时候建议加一层沙箱。2.3 因子回测框架IC 计算和分层测试因子生成出来只是半成品必须回测才知道有没有用。高频因子的评估和日频因子类似核心指标是 IC信息系数、ICIRIC 的均值除以标准差、换手率、分层收益单调性。IC 的计算方式是每个时间截面上因子值和下一期收益率的相关系数。高频数据里“下一期”通常指下一个调仓周期比如 30 分钟或 1 小时。我一般用 Rank IC也就是先对因子值和收益率做排序再算相关系数这样对异常值更稳健。def calc_ic(df, factor_col, ret_col, period30): 计算 Rank IC df: 包含 datetime, stock_code, factor_col, ret_col 的 DataFrame period: 未来收益的期数分钟数 df df.sort_values([stock_code, datetime]).copy() # 计算未来 period 期的累计收益 df[future_ret] df.groupby(stock_code)[ret_col].transform( lambda x: x.rolling(period).sum().shift(-period) ) df df.dropna(subset[factor_col, future_ret]) # 每个时间截面算一次 Rank IC ic_series df.groupby(datetime).apply( lambda g: g[factor_col].corr(g[future_ret], methodspearman) ) return ic_series def factor_report(df, factor_col, ret_colret, period30): ic calc_ic(df, factor_col, ret_col, period) ic_mean ic.mean() ic_std ic.std() icir ic_mean / ic_std if ic_std 0 else 0 positive_rate (ic 0).mean() return { IC_mean: round(ic_mean, 4), IC_std: round(ic_std, 4), ICIR: round(icir, 4), IC0占比: round(positive_rate, 4), 样本数: len(ic) }参数说明period30表示看未来 30 分钟的收益这个参数要根据你的调仓频率来定。如果你的策略是每天调仓一次那 period 应该设成一天的总分钟数。methodspearman就是 Rank IC换成pearson就是普通 IC。ICIR 大于 0.3 通常认为因子有一定预测能力大于 0.5 算不错。分层测试是把股票按因子值分成 5 组或 10 组看每组未来收益是否单调。单调性好的因子说明因子值和收益之间有稳定的线性关系更适合直接用来选股。3. 把 ChatGPT 接入自动化流水线批量生成与筛选3.1 用循环批量调用 API 生成因子池手动一个个问 ChatGPT 效率太低实际做的时候要把它接进自动化流程。核心思路是写一个循环每次换一个 Prompt 角度比如动量类、反转类、波动率类、量价背离类让 ChatGPT 生成一批因子解析后存进因子池。import openai import time # 注意API key 从环境变量读取不要硬编码 client openai.OpenAI(api_keyos.environ[OPENAI_API_KEY]) PROMPT_ANGLES [ 动量类因子捕捉价格趋势的持续性, 反转类因子捕捉短期超买超卖, 波动率类因子衡量价格波动的不对称性, 量价背离类因子捕捉成交量与价格的不同步, 盘口结构类因子利用高低开和振幅信息, ] def generate_factor_pool(angles, n_per_angle20): pool [] for angle in angles: prompt PROMPT_TEMPLATE.format(nn_per_angle) f\n本次请专注于{angle} try: resp client.chat.completions.create( modelgpt-4, messages[{role: user, content: prompt}], temperature0.7, ) factors parse_factors(resp.choices[0].message.content) pool.extend(factors) print(f{angle}: 生成 {len(factors)} 个有效因子) except Exception as e: print(f{angle} 调用失败: {e}) time.sleep(1) # 避免触发限流 return pool factor_pool generate_factor_pool(PROMPT_ANGLES) print(f因子池总数: {len(factor_pool)})参数说明temperature0.7是让输出有一定多样性设太低每次生成的因子都差不多设太高会出现大量无意义组合。time.sleep(1)是防止触发 API 限流如果你的账号额度高可以缩短。model参数根据你实际能用的模型来填不同模型生成质量差异明显建议用能力强的模型做因子生成。3.2 因子去重和相关性过滤ChatGPT 生成的因子池里一定有大量重复或高度相关的。比如“收盘价除以开盘价”和“收盘价减开盘价再除以开盘价”本质是同一个东西。不去重的话后面回测出来的结果会严重高估因子的独立性。去重分两步第一步按表达式字符串去重简单直接第二步按因子值的相关性去重把相关系数大于 0.8 的因子对里保留 IC 更高的那个。def dedup_by_correlation(df, factors, ic_dict, threshold0.8): 按因子值相关性去重保留 IC 更高的因子 factors: [{name: ..., expression: ...}, ...] ic_dict: {factor_name: ic_mean} # 先算出每个因子的值 factor_values {} for f in factors: try: factor_values[f[name]] eval(f[expression], {df: df, np: np}) except Exception: continue names list(factor_values.keys()) # 按 IC 从高到低排序优先保留 IC 高的 names.sort(keylambda x: abs(ic_dict.get(x, 0)), reverseTrue) keep [] for name in names: redundant False for kept in keep: corr factor_values[name].corr(factor_values[kept]) if abs(corr) threshold: redundant True break if not redundant: keep.append(name) return keep参数说明threshold0.8是相关性阈值设太低会误杀有差异的因子设太高去重效果不明显。我一般先用 0.8 跑一遍看看剩下多少再根据因子池大小调整。abs(ic_dict.get(x, 0))用绝对值是因为有些因子是反向的负 IC 同样有价值只要取反就行。3.3 样本外验证别在训练集上自嗨这一步是很多人翻车的地方。ChatGPT 生成的因子是在你给它的数据上“看起来有效”但如果你用全样本回测然后直接上实盘大概率会失望。正确做法是把数据切成训练集和验证集训练集上筛因子验证集上确认 IC 是否还显著。def train_test_split_by_time(df, split_ratio0.7): 按时间切分前 70% 做训练后 30% 做验证 dates sorted(df[datetime].unique()) split_idx int(len(dates) * split_ratio) train_dates set(dates[:split_idx]) test_dates set(dates[split_idx:]) train_df df[df[datetime].isin(train_dates)].copy() test_df df[df[datetime].isin(test_dates)].copy() return train_df, test_df train_df, test_df train_test_split_by_time(df) # 训练集上算 IC筛选 train_ic {f[name]: factor_report(train_df, f[name])[IC_mean] for f in factor_pool if f[name] in train_df.columns} # 验证集上确认 test_ic {f[name]: factor_report(test_df, f[name])[IC_mean] for f in factor_pool if f[name] in test_df.columns} # 找出训练和验证 IC 同号且都显著的因子 robust_factors [ name for name in train_ic if abs(train_ic[name]) 0.02 and abs(test_ic.get(name, 0)) 0.02 and np.sign(train_ic[name]) np.sign(test_ic.get(name, 0)) ] print(f稳健因子数量: {len(robust_factors)})参数说明split_ratio0.7是训练验证比例高频数据里我一般用 7:3 或 6:4。abs(...) 0.02是 IC 显著性门槛高频因子 IC 普遍偏低0.02 已经算能用。np.sign同号判断是确保因子方向在样本外没有反转方向反转的因子直接丢掉。4. 避坑与排查ChatGPT 挖因子最容易翻车的五个地方4.1 因子表达式里有未来函数现象回测 IC 高得离谱0.15 以上但实盘一跑就亏。原因ChatGPT 生成的表达式里用了shift(-1)或者直接引用了未来数据。比如它可能写出df[close].shift(-1) / df[close]这种表达式回测时看起来完美实盘根本拿不到未来价格。解决在parse_factors里加一道检查扫描表达式里有没有shift(-或future字样有就直接丢弃。另外回测框架里要严格用shift(-period)只出现在计算未来收益的那一步因子表达式本身不能含未来信息。4.2 生成的因子全是同一类现象让 ChatGPT 生成 50 个因子去重后只剩 3 个而且都是动量类。原因Prompt 里没有限制因子类别ChatGPT 会倾向于生成它认为“最合理”的那一类导致多样性不足。解决在 Prompt 里明确要求覆盖多个类别或者用PROMPT_ANGLES那种方式分角度调用。我一般会强制要求“至少包含动量、反转、波动率、量价关系四个类别各 5 个”。4.3 API 返回格式不稳定导致解析失败现象json.loads报错ChatGPT 返回的内容里混了自然语言解释。原因Prompt 里虽然要求了 JSON 格式但模型有时候会“好心”加一段说明文字比如“以下是生成的因子”然后再跟 JSON。解决解析前先用正则把 JSON 部分抠出来或者用response_format{type: json_object}参数强制 JSON 输出。另外在 Prompt 里加一句“只输出 JSON不要任何额外文字”。4.4 因子值分布极端导致 IC 计算失真现象某个因子 IC 算出来是 0.3但分层测试完全没单调性。原因因子值里有极端异常值比如除以一个接近零的数导致因子值变成 1e10Rank IC 虽然对异常值稳健但分层测试会受影响。解决算 IC 之前先做去极值处理用中位数绝对偏差MAD法或者分位数截断。我一般用 1% 和 99% 分位数截断简单有效。def winsorize(series, lower0.01, upper0.99): lo series.quantile(lower) hi series.quantile(upper) return series.clip(lo, hi)4.5 忽略交易成本和换手率现象因子 IC 不错但实盘收益被交易成本吃光。原因高频因子换手率天然高如果调仓频率是 30 分钟一次一天换手好几次手续费和冲击成本累积起来很吓人。解决回测时必须把交易成本算进去。A 股双边手续费加印花税大概千分之一点几高频策略还要考虑冲击成本。我一般会在回测里设单边千分之二作为保守估计如果因子在这个成本下还能盈利才值得进一步研究。5. 进阶技巧用 ChatGPT 做因子迭代和组合优化前面讲的都是单因子生成和筛选但真正能上实盘的往往是因子组合。ChatGPT 在这个环节也能帮上忙而且用法和单因子生成不太一样。一个我常用的技巧是让 ChatGPT 做“因子迭代”。具体做法是把上一轮筛选出来的有效因子和它们的 IC 表现一起丢给 ChatGPT让它基于这些因子的逻辑生成变体。比如“volume_ratio”这个因子 IC 不错就让它生成“volume_ratio 的 5 期均线”“volume_ratio 的截面排名”“volume_ratio 和振幅的交互项”等衍生版本。这样比从零生成命中率高得多。ITER_PROMPT 以下是我上一轮筛选出的有效因子及其 IC 表现 {factor_list} 请基于这些因子的逻辑生成 10 个变体因子要求 1. 每个变体是对原因子的改进或组合不是简单重复 2. 输出格式为 JSON 列表包含 name 和 expression 3. 表达式只能使用以下字段open, high, low, close, volume, amount, ret, vwap, vol_ma5, amplitude def iterate_factors(valid_factors, ic_dict, n10): factor_list \n.join( f- {f[name]}: {f[expression]} (IC{ic_dict.get(f[name], 0):.4f}) for f in valid_factors[:10] ) prompt ITER_PROMPT.format(factor_listfactor_list) resp client.chat.completions.create( modelgpt-4, messages[{role: user, content: prompt}], temperature0.6, ) return parse_factors(resp.choices[0].message.content)参数说明valid_factors[:10]只取前 10 个因子太多会超出上下文限制。temperature0.6比生成新因子时略低因为迭代任务需要更聚焦。这个循环可以跑多轮每轮把新筛出的因子加进去几轮下来因子池会越来越精。另一个技巧是让 ChatGPT 帮你做因子正交化。把相关性高的因子对丢给它让它生成正交化后的表达式。比如两个因子高度相关可以让它生成“因子 A 对因子 B 回归后的残差”作为新因子。这个操作在传统量化里要手写回归代码ChatGPT 可以直接给你表达式。最后说一个验证方法把 ChatGPT 生成的因子和已知的经典因子比如反转因子、换手率因子做相关性对比。如果新因子和经典因子相关性低于 0.3说明它提供了增量信息值得保留如果高于 0.7那基本是经典因子的变体意义不大。这个检查能帮你快速判断因子池里有多少是真正的新东西。我自己跑这套流程最大的教训是别指望 ChatGPT 一次给你一个能上实盘的因子。它的价值在于把因子挖掘的试错成本从“人工两天一个”降到“程序两小时一批”你真正要做的是设计好筛选和验证的流水线让机器去试错人来把关逻辑。这套东西跑顺了因子池的更新速度会比纯人工快一个数量级。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Spring Boot+Vue学生选课系统开发实战:从表结构到并发防超卖 2026/10/2 5:32:39

Spring Boot+Vue学生选课系统开发实战:从表结构到并发防超卖

简介:这是一份基于Spring Boot和Vue技术栈开发的学生网上选课系统完整项目,采用前后端分离架构,后端以Java和Spring Boot为核心,前端由Vue.js构建,配合MySQL 5.7数据库,为计算机专业学生及Java Web开发者提…

阅读更多 →
Jev 智能 if 语句:TypeSafe AI 判定引擎的工程实践与部署指南 2026/10/2 5:32:32

Jev 智能 if 语句:TypeSafe AI 判定引擎的工程实践与部署指南

1. 从"聊天机器人"到"智能 if 语句":Jev 到底在解决什么问题大多数人第一次听到 Jev,会下意识把它归类到"又一个 AI 聊天助手"里。这个判断其实挺自然——毕竟现在但凡带个 AI 标签的东西,十有八九都是对话框形…

阅读更多 →
VCS与Verdi联合仿真:从安装配置到环境搭建全攻略 2026/10/2 5:32:32

VCS与Verdi联合仿真:从安装配置到环境搭建全攻略

干验证这行的人,基本都绕不开 VCS。我第一次碰它还是在学校实验室,导师丢给我一套 RTL 代码和一个安装包,没有文档、没有教程,我自己硬生生折腾了小一周才把第一个仿真跑通。后来到公司里,发现很多刚入行的同事也卡在同…

阅读更多 →
机器学习设计模式实战:分箱、缩放、重平衡与级联集成落地 2026/10/2 5:32:32

机器学习设计模式实战:分箱、缩放、重平衡与级联集成落地

简介:《机器学习设计模式》英文原版PDF是一本面向机器学习工程师与数据科学家的实践指南,由OReilly出版,聚焦数据准备、模型构建与MLOps三大阶段的高频难题。书中系统梳理了数据探索、数据预处理、数据转换,模型选择、模型评估、模…

阅读更多 →
Codex CLI本地部署全指南:破解openrig误传迷雾 2026/10/2 5:32:31

Codex CLI本地部署全指南:破解openrig误传迷雾

1. OpenRig 是什么:一个被误传多年、实际并不存在的“工具”概念你搜“openrig”,页面跳出一堆 Node.js、tmux、codex、CLI 相关热词,甚至混着“cc switch local proxy failed while handling codex endpoint /responses”这种报错——但翻遍…

阅读更多 →
机器学习设计模式实战:从特征工程到模型部署的完整套路 2026/10/2 5:32:30

机器学习设计模式实战:从特征工程到模型部署的完整套路

简介:《Machine Learning Design Patterns》是由谷歌工程师瓦尔拉帕拉克什曼南、莎拉罗宾逊与迈克尔穆恩合著的机器学习实践指南,重点解决数据准备、模型构建和MLOps三个阶段中的常见挑战。书中系统归纳了数据探索、数据预处理、数据转换、模型选择、模型…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉