核心成果摘要
基于 PandaAI 数据平台构建 A4 板块资金轮动因子,通过申万 31 个一级行业的个股成交额聚合,捕捉市场资金在各板块间的轮动趋势。
- 三年回测 IC 均值 0.4314,ICIR 1.8651,预测能力强且稳定
- 生产数据覆盖 5,154 只股票,82,377 条记录,已推送至 quantskills 组织仓库
- 交付物完整:SKILL.md、factor.py、validate.py、backtest.py、生产数据 Parquet
一、项目背景与目标
| 配置项 |
值 |
| 业务场景 |
量化选股 / 板块轮动策略 |
| 因子类型 |
资金流 / 行业轮动 |
| 数据来源 |
PandaAI 云端数据平台 |
| 数据账号 |
86***********(pandaskill 全量权限已开通) |
| 开发周期 |
2026-06-04 ~ 2026-06-24 |
1.1 问题背景
- A 股市场资金在各申万行业间持续轮动,捕捉资金流入/流出信号对选股具有预测价值
- 申万行业指数权限未开通,需要通过个股数据聚合实现等效因子
- 因子需同时满足:逻辑可解释、回测 IC 稳定、生产可自动运行
1.2 解决思路
- 用个股成交额(amount)替代行业指数,通过申万 L1 行业成分股映射实现个股→行业的资金聚合
- 计算每日各行业资金占全市场比例,再计算 3 日变化率,最后做截面 rank 归一化
- 扩展到个股级别:同一行业内的个股继承行业因子值,并补充 rank/confidence 字段
二、数据环境与基础设施
2.1 软件与网络环境
| 组件 |
版本 / 路径 |
说明 |
| Python |
3.12+(conda 环境 panda_env) |
因子计算主语言 |
| Anaconda |
D:\anaconda |
环境管理器,PATH 已配置 |
| Git |
2.54.0(D:\Git) |
版本控制,PATH 已配置 |
| GitHub CLI |
2.95.0 |
仓库创建与推送 |
| GitHub ID |
yizhai-GIT(已加入 quantskills 组织) |
代码托管 |
| panda_data SDK |
0.0.9(本地 whl 安装) |
PandaAI 数据接口封装 |
| pandas |
≥2.0 |
数据处理 |
| pyarrow |
— |
Parquet 文件读写 |
| MongoDB |
8.0.9( |
备用,本地数据存储 |
2.2 数据源配置
| 配置项 |
值 / 说明 |
| Base URL |
http://pandadata.pandaaiquant.com |
| 接口鉴权 |
panda_data.init_token() 返回 JWT token |
| 行业代码体系 |
申万一级行业(L1),共 31 个,代码范围 801010~801980 |
| 成分股数量 |
5,514 只股票(ST 过滤后) |
| 数据格式 |
Parquet(二进制列式存储,手动解析,不依赖 duckdb) |
| 批量限制 |
单次请求最多 300 只股票,建议不超过 30 个交易日 |
| 权限状态 |
pandaskill 全量权限已开通(2026-06-24) ✅ |
2.3 核心 API 接口
| API 函数 |
用途 |
输入 → 输出 |
调用频率 |
init_token |
登录认证 |
username + MD5(password) → JWT token |
一次/会话 |
get_industry_constituents |
获取行业成分股 |
申万 L1 行业代码 → 股票列表 |
启动时一次 |
get_stock_daily |
获取个股日线 |
股票列表 + 日期范围 → OHLCV + amount |
每日一次 |
三、数据产出详情
3.1 回测数据集(三年回测)
| 指标 |
值 |
说明 |
| 回测区间 |
2023-01-03 ~ 2026-06-13 |
首至末日均有效交易日 |
| 实际数据覆盖 |
27 个月 |
2023-01~2024-05, 2025-03~2026-06 |
| 数据缺失 |
9 个月 |
2024-06 ~ 2025-02(约 25% 窗口) |
| 交易日数 |
410 天 |
日线数据有效天数 |
| 行业数量 |
31 个 |
申万一级行业全覆盖 |
| 日线缓存文件 |
22 个 Parquet |
按月分区,a4_cache/daily_YYYYMM.parquet |
| 日线缓存大小 |
~41 MB |
gzip 压缩后约 10 MB |
3.2 生产数据集(最新)
| 指标 |
值 |
说明 |
| 数据文件 |
production/数据库.parquet |
生产路径 |
| 文件大小 |
79 KB |
原始 Parquet 文件 |
| 总行数 |
82,377 行 ✅ |
清洗 NaN 后有效记录 |
| 日期范围 |
2025-05-22 ~ 2025-06-13 |
最新交易日 |
| 股票数量 |
5,154 只 ✅ |
沪深 A 股全市场 |
| 字段数量 |
13 列 |
全字段非空,无缺失值 |
| 最新日期信号 |
2025-06-13 |
流入 1,331 / 中性 1,200 / 流出 2,620 |
3.3 信号分布统计(生产数据)
| 信号 |
全量分布(行数) |
占比 |
触发条件 |
| 流入 |
32,611 |
39.6% |
score > 0.7 |
| 中性 |
31,563 |
38.3% |
0.3 ≤ score ≤ 0.7 |
| 流出 |
18,203 |
22.1% |
score < 0.3 |
四、因子计算逻辑与数据处理
4.1 计算流程(5 步)
| 步骤 |
名称 |
具体操作 |
| Step 1 |
登录认证 |
init_token → 获取 JWT token |
| Step 2 |
行业成分股映射 |
get_industry_constituents → 5,514 只股票 × 31 行业 |
| Step 3 |
批量拉取日线 |
get_stock_daily → amount/volume/close,按月缓存 Parquet |
| Step 4 |
行业资金聚合 |
groupby(date, industry_code).sum(amount) → 每日行业成交额 |
| Step 5 |
因子计算 |
资金占比 → 3日差分 → 截面 rank → score/signal/confidence |
4.2 核心计算公式
| 字段 |
计算公式 |
含义 |
| 资金占比 |
amount_pct_{i,t} = sector_amount_{i,t} / total_amount_t |
行业 i 在 t 日的成交额占全市场比例 |
| 3日变化率 |
delta_{i,t} = amount_pct_{i,t} - amount_pct_{i,t-3} |
捕捉资金流入/流出的加速度 |
| 因子分 |
score_{i,t} = rank_pct(delta_{i,t}) |
每日截面 rank 归一化到 [0,1] |
| 信号判定 |
signal = 流入 if score>0.7, 流出 if score<0.3, else 中性 |
阈值边界清晰 |
| 置信度 |
confidence = |score - 0.7| 或 |score - 0.3| |
距离阈值越远越可信 |
4.3 个股级别扩展
因子在行业级别计算完成后,通过行业代码映射扩展到个股级别:
- 同一行业内的所有个股继承相同的 score 和 signal 值
- 个股 rank = 行业 rank(rank 在行业间截面排名,非行业内排名)
- confidence 字段用于衡量信号边界清晰程度,越大表示信号越明确
五、回测结果
5.1 IC 分析(410 交易日)
| 指标 |
值 |
评价 |
| IC 均值 |
0.4314 |
强预测能力(> 0.3 即为有效因子)✅ |
| ICIR |
1.8651 |
极高稳定性(> 1.5 为优秀)✅ |
| Rank IC 均值 |
0.4315 |
与 IC 一致,无饱和效应 ✅ |
| Rank ICIR |
1.8672 |
排名稳定性极强 ✅ |
| 数据说明 |
27 个月 / 缺失 9 个月 |
年化收益/回撤指标暂不可用(需完整数据)⚠️ |
5.2 信号分布(行业日)
| 信号 |
行业日数量 |
占比 |
解读 |
| 流入 |
4,790 |
39.8% |
资金流入趋势占主导 ✅ |
| 中性 |
3,863 |
32.1% |
约 1/3 行业资金流向不明 |
| 流出 |
3,456 |
28.1% |
资金流出行业相对较少 |
5.3 回测数据文件清单
| 文件 |
大小 |
内容 |
路径 |
a4_factor_3y.parquet |
372 KB |
3 年因子值(410日 × 31 行业) |
a4_cache/ |
backtest_3y.json |
482 B |
IC/ICIR/RankIC 等指标 |
a4_cache/ |
daily_*.parquet × 22 |
~1.5~2.2 MB/个 |
月度日线数据缓存 |
a4_cache/ |
| 行业成分股映射.json |
124 KB |
申万 31 行业 × 5,514 只股票 |
a4_cache/ |
六、生产交付状态
6.1 交付物清单
| 类型 |
文件名 / 地址 |
说明 |
状态 |
| 生产数据 |
production/数据库.parquet |
82,377行 / 13列 |
✅ 已完成 |
| 生产 SKILL |
production/SKILL.md |
生产级 skill 文档 |
✅ 已完成 |
| 因子计算脚本 |
scripts/factor.py |
因子主计算逻辑 |
✅ 已完成 |
| 验证脚本 |
scripts/validate.py |
数据验证+信号分布检验 |
✅ 已完成 |
| 回测脚本 |
scripts/backtest.py |
IC/ICIR 计算 |
✅ 已完成 |
| 数据说明 |
references/data_guide.md |
API 接口+字段+清洗口径 |
✅ 已完成 |
| 三年回测报告 |
A4因子三年回测报告.md |
完整回测文档 |
✅ 已完成 |
| 最终交付文档 |
A4因子最终交付文档.docx |
完整 Word 版交付包 |
✅ 已完成 |
| GitHub 仓库 |
quantskills/alpha-a04-sector-fund-flow |
Private,main 分支 |
✅ 已完成 |
6.2 生产数据字段说明
| 字段 |
类型 |
说明 |
备注 |
trade_date |
date |
交易日期 YYYY-MM-DD |
主键 |
ts_code |
string |
股票代码(000001.SZ 格式) |
主键 |
factor_id |
string |
固定值 "A4" |
因子标识 |
factor_name |
string |
"板块资金轮动" |
因子名称 |
factor_value |
float |
行业成交额占比 3 日变化率 |
原始值 |
score |
float |
截面 rank 归一化 [0,1] |
标准化分 |
rank |
int |
每日截面降序排名(1=最强) |
排名 |
signal |
string |
流入 / 中性 / 流出 |
交易信号 |
confidence |
float |
距离阈值边界距离,越大越可信 |
置信度 |
data_version |
string |
"v1.0" |
版本控制 |
update_time |
datetime |
结果生成时间戳 |
审计字段 |
七、技术踩坑与解决
| 问题 |
原因 |
解决方案 |
类型 |
| 申万行业指数无权限 |
get_index_daily 对申万行业指数返回空(200103) |
改用个股成交额按行业聚合 |
无板块数据 |
| panda_data numpy 冲突 |
panda_data 0.0.9 需 numpy<2.0 |
创建 conda 环境隔离 |
版本冲突 |
| duckdb 安装 SIGKILL |
winget/pip 安装 duckdb 被系统杀掉 |
放弃 duckdb,用 pyarrow 直接解析 Parquet |
内存/OOM 限制 |
getMultiMarketData 下架 |
平台已下架该接口 |
改用 get_stock_daily 批量获取 |
接口变更 |
| GitHub 组织仓库不存在 |
quantskills 下无仓库,web 导入有 IP 白名单 |
安装 gh CLI,命令行创建并推送 |
权限+网络 |
PandaAI 量化因子开发 | A4 板块资金轮动因子 | quantskills/alpha-a04-sector-fund-flow
评论