39 KiB
OneChartLab 复现的 Tushare 数据需求研究
调研日期:2026-08-28。范围:OneChartLab「板块资金雷达」与「宏观择时」的数据采集、落库、历史回填和独立重算边界。本文只讨论技术复现,不构成投资建议。
结论摘要与目标边界
复现工作必须先区分两个不同目标。
目标 A:完全复刻页面消费层。 最可靠的输入不是重新从 Tushare 推导,而是直接保存 OneChartLab 已公开的 manifest、日期分片、排名历史、宏观 state.json、series.json 和 dispersion 数据块。页面已经公开 Ratio_Score、Swing_Score、D/C/O 等结果,却没有公开这些结果的完整构建公式。只要保留公开 payload、schema、hash、批次和修订水位,就能精确复刻页面已经确认的排序、百分位、阈值、MA 和贡献消费逻辑。[页面/manifest 已确认:radar_manifest.json、sector_rankings/manifest.json、macro/state.json]
目标 B:独立重算未公开指标。 Tushare 能提供板块成员、个股资金流、日行情、申万分类、申万成员和指数行情等底层事实,但不能直接提供或确认 OneChartLab 的 Ratio_Score、3—10 日权重、Swing_Score、核心离散度 D、行业贡献 C/O、修订水位生成规则或原站私有版本参数。因此可以独立构造“同语义替代指标”,也可以复算公开的下游恒等式,但在获得构建公式和 point-in-time 输入快照前,不能宣称独立结果与原站等价。[页面/manifest 已确认;需实测/缺公式]
当前最小可执行策略是“双轨落库”:一轨原样保存 OneChartLab 公开发布物以保证消费层可复现,另一轨按本文接口清单保存 Tushare 原始事实,以便做抽样对账、替代公式实验和未来独立重算。两轨通过 trade_date、稳定代码、source_version、observed_at、响应 hash 和计算参数版本关联,不用网页展示名称作为主键。
证据标记
本文使用四种状态:页面/manifest 已确认 表示 OneChartLab 第一方公开文件明确给出;Tushare 官方文档已确认 表示接口名、字段、单位或限制来自 Tushare 官方接口页;复现建议 表示本文为采集和落库提出的工程方案;需实测 表示官方页没有稳定说明、实际账号权限/频次/历史覆盖或边界语义需要用已授权账号验证。官方页面上的积分和限量是 2026-08-28 的页面快照,可能调整;上线前仍应以目标账号调用结果和权限中心为准。
第一方公开契约
OneChartLab 的 sector_rankings/manifest.json 当前明确声明以下来源和单位:
| 页面事实 | Radar | Macro | 证据状态 |
|---|---|---|---|
| 板块/行业成员 | tushare.dc_member |
tushare.index_member_all |
页面/manifest 已确认 |
| 主力净额 | tushare.moneyflow_dc.net_amount |
同左 | 页面/manifest 已确认;输入单位万元,聚合求和后输出亿元 |
| 主买净额 | tushare.moneyflow.net_mf_amount |
同左 | 页面/manifest 已确认;输入单位万元,禁止由大小单金额自行相减 |
| 个股涨跌幅 | tushare.daily.pct_chg |
同左 | 页面/manifest 已确认;多日窗口使用 compound_return |
| 上市生命周期 | tushare.stock_basic |
同左 | 页面/manifest 已确认;有效区间为 list_date <= trade_date <= delist_date_or_open |
| 日停复牌 | tushare.suspend_d |
同左 | 页面/manifest 已确认 |
| 停牌区间 | tushare.suspend |
同左 | 页面/manifest 已确认其字符串;当前官方接口目录未找到对应公开页,需实测,不能替代 suspend_d 的官方事实 |
| 股票池 | 沪深上市 A 股,排除北交所与沪深 B 股 | 同左 | 页面/manifest 已确认 |
该 manifest 的 public_payload 是 derived_top_bottom_only,说明公开成分文件只给派生后的前后榜,不是完整逐股输入明细。2026-08-28 观测到的当前批次日期为 2026-08-27,Radar 是 eastmoney-dc-v1、707 个板块、窗口 [1],Macro 是 sw2021_l2_current124_*、124 个申万二级行业、窗口 [1,3,5,10,90]。既有 2026-08-26 Radar 报告记录的是 791 个板块;数量变化证明 universe 必须随交易日快照保存,不得硬编码。[页面/manifest 已确认]
宏观 state.json 在同次观测中已从既有报告的 revision_watermark=21 更新到 22。这说明相同或相邻日期的数据可被重新构建,所有公开输入都应保存 batch_id、bundle_id、accepted_input_hash、revision_watermark、响应 hash 和 observed_at,不能只覆盖一张“最新值”表。[页面/manifest 已确认;复现建议]
模块数据血缘与分级
板块资金雷达
| 分级 | 数据 | 用途与边界 |
|---|---|---|
| 必需 | dc_index、dc_member、moneyflow_dc、daily、trade_cal、stock_basic、suspend_d |
建立每日东财概念/行业板块 universe、point-in-time 成员、主力净额、涨跌幅、交易日和有效样本。moneyflow_dc.net_amount 是公开成分 manifest 明确的主力净额来源。 |
| 必需(完整成分解释层) | moneyflow |
提供 net_mf_amount 主买净额;这是 L2 主动买卖净额,不能由大中小单简单相减。只复刻主雷达榜单而不实现成分详情时可暂缓。 |
| 推荐 | daily_basic、moneyflow_ind_dc、namechange |
daily_basic 提供换手率、市值等低流动性质量特征;moneyflow_ind_dc 是官方“东财概念及行业板块资金流向”接口,可与逐股聚合做交叉对账;namechange 保留历史展示名和名称区间。三者均不是公开 manifest 对主指标公式的确认。 |
| 可选 | adj_factor |
用于股票复权和公司行动质检,不是单日 daily.pct_chg 或 moneyflow_dc 的必需输入,也不能单独生成前复权价格。 |
可高置信度实施的链路是 dc_index/dc_member + stock_basic/suspend_d 确定当日有效成员,再关联 moneyflow_dc、moneyflow 和 daily 生成完整逐股事实与成分前后榜。Amount_Raw_BN 可用 sum(moneyflow_dc.net_amount) / 10_000 作为待对账候选,因为万元除以 10,000 得亿元;但主雷达构建端逐股明细未公开,必须逐日逐板块与公开 raw 值抽样核对后才能固化。[页面/manifest 已确认来源与单位;复现建议聚合;需实测等价性]
Ratio_Raw_Pct 的概念分母由作者在公开视频中解释为当日成交额,但 Tushare 和公开页面没有确认生产公式是板块级 moneyflow_ind_dc.net_amount_rate、sum(net_amount)/sum(daily.amount)、逐股比例再聚合,还是包含截尾和低流动性过滤。daily.amount 可作为成交额候选,moneyflow_dc.net_amount_rate 和 moneyflow_ind_dc.net_amount_rate 可用于对照实验,不能直接指定为原站公式。[作者自述;Tushare 官方字段已确认;需实测]
宏观择时
| 分级 | 数据 | 用途与边界 |
|---|---|---|
| 必需(独立构造主序列) | index_classify、index_member_all、sw_daily、trade_cal |
取得申万 2021 分类、二级行业及成员区间、申万行业日线和统一交易日。作者在公开视频中称核心输入为申万二级行业近 90 日涨跌幅横截面分布,但 D 的统计量仍未公开。 |
| 必需(七指数对照) | index_daily |
提供 000001.SH、399006.SZ、000688.SH、000016.SH、000300.SH、000852.SH、932000.CSI 的收盘序列。index_daily 官方明确不含申万行业,不能代替 sw_daily。 |
| 必需(完整成分解释层) | daily、moneyflow_dc、moneyflow、stock_basic、suspend_d |
复算 1/3/5/10/90 日行业成分股涨跌幅、主力净额和主买净额榜。仅研究 D 主序列时可以与主序列采集拆开。 |
| 推荐 | index_basic、daily_basic、namechange |
校验七指数代码、发布方和终止日期;提供流动性/规模质量特征和历史名称。 |
| 可选 | adj_factor |
用股票级复权价格复核多日个股收益;行业主序列优先用 sw_daily,页面公开的成分窗口已明确使用 daily.pct_chg 复合。 |
index_member_all 的输出含 in_date、out_date 和 is_new,适合保存成员区间;但官方页没有说明剔除日是否仍算有效,也没有证明返回历史覆盖能够重建 OneChartLab 的全部历史 universe。Macro 当前公开 universe 名称含 current124,现有页面报告也指出完整历史 point-in-time 成员未公开。因此历史计算不得把当前 124 行业及当前成员回填到过去。[Tushare 官方字段已确认;页面/manifest 已确认当前 universe;需实测边界与完整性]
接口字典:调用与落库
下表的“必要字段”是本任务最小字段集,不代表应丢弃供应商原始响应。生产中建议同时保存原始 JSON/Parquet、请求参数和响应 hash,以便接口字段调整或历史修订后重放。
Tushare 多个接口不会默认返回全部字段,尤其是 daily_basic.limit_status、stock_basic.exchange/list_status/delist_date、index_classify.src 和 index_basic.exp_date。生产调用必须显式传入本表列出的 fields,并把请求参数中的分类版本等维度一并落库;不能假设默认响应足以构造生命周期过滤或自然业务主键。[Tushare 官方文档已确认;复现建议]
| 接口 | 模块用途/级别 | 主要调用参数 | 必要输出字段 | 粒度与自然业务主键 |
|---|---|---|---|---|
dc_index |
Radar 必需:每日东财概念、行业、地域板块身份与类型 | trade_date;回填用 start_date/end_date;idx_type 必填,也可按 ts_code/name |
ts_code,trade_date,name,idx_type,level,pct_change,leading_code |
板块×交易日;(trade_date,ts_code) |
dc_member |
Radar 必需:每日板块成员 | 优先按 trade_date,必要时按 ts_code 分片;支持 con_code,start_date,end_date |
trade_date,ts_code,con_code,name |
板块×股票×交易日;(trade_date,ts_code,con_code) |
moneyflow_dc |
两模块必需:个股东财口径主力净额 | 日增量按 trade_date;回填按股票或日期窗口 |
trade_date,ts_code,name,net_amount,net_amount_rate,pct_change,close,建议保留四档净流入字段 |
股票×交易日;(ts_code,trade_date) |
moneyflow |
完整成分解释层必需:L2 主买净额 | 日增量按 trade_date;回填按 ts_code 或日期窗口 |
ts_code,trade_date,net_mf_amount,net_mf_vol,建议保留各档买卖金额/量 |
股票×交易日;(ts_code,trade_date) |
moneyflow_ind_dc |
Radar 推荐:官方东财板块资金流,供 raw/ratio 对账 | trade_date 或日期窗口;content_type 区分行业/概念/地域 |
trade_date,content_type,ts_code,name,net_amount,net_amount_rate,pct_change,rank |
板块类型×板块×交易日;(trade_date,content_type,ts_code) |
daily |
两模块必需:个股涨跌幅、成交额与行情可用性 | 日增量按 trade_date;官方建议按日期循环全市场,避免逐股回填 |
ts_code,trade_date,close,pre_close,pct_chg,vol,amount |
股票×交易日;(ts_code,trade_date) |
daily_basic |
推荐:换手率、市值、量比和低流动性质量规则 | 日增量按 trade_date;单股历史用 ts_code,start_date,end_date |
ts_code,trade_date,turnover_rate,turnover_rate_f,volume_ratio,total_mv,circ_mv,limit_status |
股票×交易日;(ts_code,trade_date) |
trade_cal |
两模块必需:交易日序列、窗口和前序日 | exchange,start_date,end_date;A 股至少保存 SSE,建议同时校验 SZSE |
exchange,cal_date,is_open,pretrade_date |
交易所×日历日;(exchange,cal_date) |
stock_basic |
两模块必需:上市/退市生命周期和市场过滤 | 必须分别拉 list_status=L,D,P,G,UN,不可只用默认 L;可按 exchange/market |
ts_code,symbol,name,market,exchange,list_status,list_date,delist_date |
当前证券主记录;ts_code,另存带 observed_at 的快照版本 |
namechange |
推荐:历史名称、展示标签和 ST 名称审计 | 增量按公告区间 start_date/end_date,也可按 ts_code 回填 |
ts_code,name,start_date,end_date,ann_date,change_reason |
股票×名称有效期;建议 (ts_code,start_date,name),将其余字段视为可修订 |
suspend_d |
两模块必需:区分停牌、复牌与数据缺失 | 日增量按 trade_date;回填用 start_date/end_date;可按 suspend_type |
ts_code,trade_date,suspend_timing,suspend_type |
股票×停复牌事件日;建议 (ts_code,trade_date,suspend_type,suspend_timing) |
adj_factor |
可选/推荐质检:复权和公司行动 | 日增量按 trade_date;回填可按 ts_code 全历史 |
ts_code,trade_date,adj_factor |
股票×交易日;(ts_code,trade_date) |
index_classify |
Macro 必需:申万 2014/2021 分类与 L2 universe | src=SW2021,level=L2;可按 index_code,parent_code |
index_code,industry_name,parent_code,level,industry_code,is_pub,src |
分类版本×行业;(src,index_code) |
index_member_all |
Macro 必需:申万 L1/L2/L3 成员区间 | 按 l2_code 分片;为历史回填分别核对 is_new=Y/N;也可按 ts_code |
l1_code,l1_name,l2_code,l2_name,l3_code,l3_name,ts_code,name,in_date,out_date,is_new |
行业层级路径×股票×纳入区间;建议 (l1_code,l2_code,l3_code,ts_code,in_date) |
sw_daily |
Macro 必需:申万行业日线 | 日增量按 trade_date;回填按 ts_code,start_date,end_date |
ts_code,trade_date,name,close,pct_change,vol,amount,需要时保留 OHLC/估值/市值 |
申万指数×交易日;(ts_code,trade_date) |
index_basic |
Macro 推荐:七指数代码和生命周期校验 | 按 ts_code/symbol,或分市场 SSE/SZSE/CSI 拉取 |
ts_code,name,market,publisher,category,list_date,exp_date |
指数;ts_code,另存观察快照 |
index_daily |
Macro 必需:七个市场对照指数;不含申万行业 | 必须给 ts_code,按 start_date/end_date 回填或按日增量 |
ts_code,trade_date,close,pre_close,pct_chg,建议保留 OHLC/量额 |
指数×交易日;(ts_code,trade_date) |
接口字典:拉取策略、时效与权限
| 接口 | 建议拉取方式、更新时点与历史深度 | 官方限量/权限页面快照 | 证据状态与待测项 |
|---|---|---|---|
dc_index |
每个开市日按 idx_type 分三类拉取并保存完整日快照;回填按日期循环。官方称支持每日板块数据,未给稳定入库时点。 |
单次 5,000 行;页面写 6,000 积分 | 字段/限量/积分为 Tushare 官方确认;实际到达时点和账号频次需实测 |
dc_member |
每个开市日按日期拉完整成员;超过上限时再按板块代码分片。历史成员按日期回填,绝不拿最新成员覆盖历史。 | 单次 5,000 行;页面写 6,000 积分 | 官方确认可按板块代码和日期取历史;最早历史、当日到达时点、频次需实测 |
moneyflow_dc |
每日盘后按 trade_date 拉全市场;回填先按日期,失败再按股票分段。官方明确历史始于 2023-09-11。 |
单次 6,000 行;页面写至少 5,000 积分 | Tushare 官方确认;盘后具体完成时刻和账号频次需实测。2023-09-11 以前不能由本接口补齐 |
moneyflow |
每日按 trade_date 拉全市场;长历史按日期或股票分片。官方写数据始于 2010 年。 |
单次 6,000 行、总量不限;页面写至少 2,000 积分且基础积分有流控 | Tushare 官方确认;每日到达时点和账号实际流控需实测 |
moneyflow_ind_dc |
每日盘后按日期和 content_type 拉取,用于与逐股聚合和公开 Radar raw 做三方对账。 |
单次 5,000 行;页面写 6,000 积分 | Tushare 官方确认接口,但 OneChartLab manifest 未声明其为主雷达构建输入;实际等价性需实测 |
daily |
交易日按日期全市场增量;官方建议按日期循环。15:00—16:00 入库,停牌期间不返回。 | 单次 6,000 行;官方页写基础积分每分钟 500 次 | Tushare 官方确认;目标账号仍需做限流和完整性实测 |
daily_basic |
交易日按日期拉全市场;15:00—17:00 入库。历史可按日循环。 | 单次 6,000 行;至少 2,000 积分,官方称 5,000 积分无总量限制 | Tushare 官方确认;实际频次需账号实测 |
trade_cal |
初始化拉完整日历,之后按年滚动刷新;不应每天全量重拉。历史起点和远期日历发布范围以响应为准。 | 页面写 2,000 积分;未给稳定行数/频次 | 字段/积分为官方确认;覆盖范围与账号频次需实测 |
stock_basic |
初始化分别拉所有 list_status,每日或每周做小成本快照对比;事件发生后更新生命周期。 |
单次 6,000 行;2,000 积分起、每分钟 50 次 | Tushare 官方确认;接口默认仅 L,必须显式补 D/P/G/UN |
namechange |
初始化按股票或公告日期回填,之后按最近公告窗口重叠拉取,允许旧记录修订。 | 官方页未给稳定积分、限量或频次 | 字段为 Tushare 官方确认;权限、频次、最早历史与日期边界需实测 |
suspend_d |
每个开市日按日期拉,连续重叠回拉最近若干日以接纳“不定期”修订;历史按日期窗口。 | 官方页未给稳定积分、限量或频次 | Tushare 官方确认“不定期更新”;权限、频次、覆盖和同日多事件需实测 |
adj_factor |
盘前 09:15—09:20 后按日期增量;回填按股票或日期。 | 2,000 积分起;5,000 以上可高频,未给精确频次 | Tushare 官方确认;实际频次需实测 |
index_classify |
初始化按 SW2014/SW2021 × L1/L2/L3 保存版本快照;低频刷新并对比代码、名称、父级和 is_pub。 |
页面写 2,000 积分,未给稳定行数/频次 | Tushare 官方确认;版本修订时点和账号频次需实测 |
index_member_all |
按 L2 行业分片回填 is_new=Y/N,原样保存 in_date/out_date;每日或每周检查新增/剔除,不覆盖区间历史。 |
单次 2,000 行、总量不限;页面写 2,000 积分 | Tushare 官方确认字段;is_new=N 的完整语义、剔除日边界、历史完整性和频次需实测 |
sw_daily |
每日按日期拉全部发布行业,回填按行业代码分段;默认是申万 2021 版。 | 单次 4,000 行;页面写 5,000 积分 | Tushare 官方确认;最早历史、到达时点和实际频次需实测 |
index_basic |
初始化按市场拉取,低频刷新;官方页写每天 18:00 更新、数据起始 1990-01-01。 | 单次 8,000 行;2,000 积分起 | Tushare 官方确认;账号频次需实测 |
index_daily |
七个代码逐个按时间段回填,每日收盘后增量;指数自身上市前为空。 | 页面写 2,000 积分,5,000 以上频次相对较高,未给精确频次 | Tushare 官方确认;到达时点和实际频次需实测 |
接口名与口径更正
moneyflow_dc是“个股资金流向(DC)”,其net_amount单位为万元;东财概念/行业板块的直接资金流接口是moneyflow_ind_dc,其net_amount单位为元。两者不可因名称相近混用。[Tushare 官方文档已确认]moneyflow.net_mf_amount是基于 L2 主动买卖单统计的净流入,官方明确说不能简单由大小单总和相减;这与 OneChartLab manifest 的“主买净额”定义一致。[页面/manifest 与 Tushare 官方文档均确认]daily是未复权行情,adj_factor只是复权因子;若需要 qfq 价格,应使用官方pro_bar的adj="qfq"或基于版本化规则计算,不能把adj_factor当价格。[Tushare 官方文档已确认]index_daily官方明确“不包含申万行业指数行情数据”;申万行业必须用sw_daily。index_classify(src="SW2021", level="L2")提供分类,index_member_all提供带纳入/剔除日期的成员关系。[Tushare 官方文档已确认]- 当前官方页面确认的东财板块目录接口是
dc_index,成员接口是dc_member。不存在用一个静态dc_member当前表安全回填全部历史的做法;必须按交易日保存成员快照。[Tushare 官方文档已确认;复现建议] - OneChartLab manifest 出现
tushare.suspend,但当前 Tushare 官方接口目录只找到suspend_d的公开页。实施清单中只把suspend_d视为已确认接口;suspend作为历史/兼容调用名单独实测,未成功前不得建立生产依赖。[页面/manifest 已确认字符串;需实测]
最小采集集与增强采集集
目标 A:页面消费层最小集
无需 Tushare token,按发布物原样保存:Radar 的 radar_manifest.json、30 日日期分片、rank_history、成分排行 manifest 和日期文件;Macro 的 state.json、current/last_good 指向的 series.json、dispersion manifest、latest180 与所需年度块。保存 URL、HTTP 观测时间、内容 hash、schema 和所有批次身份。这个集合能复现页面已经公开的结果和消费公式,但不能生成缺失日期或重建私有指标。[页面/manifest 已确认]
目标 B:独立上游最小集
Radar 主榜最小集为 trade_cal + dc_index + dc_member + stock_basic + suspend_d + daily + moneyflow_dc;若要完整复现成分解释,再加入 moneyflow。Macro 主序列实验最小集为 trade_cal + index_classify + index_member_all + sw_daily + index_daily;若要完整成分解释,再复用 stock_basic + suspend_d + daily + moneyflow_dc + moneyflow。该集合只保证输入事实充分,不保证 Ratio/Swing/D/C/O 与原站一致。[复现建议;缺公式]
增强采集集
加入 daily_basic 做换手率、量比、市值和低流动性质量控制;加入 moneyflow_ind_dc 对账官方板块级净额/净占比;加入 namechange 保留历史名称区间;加入 adj_factor 做复权和公司行动质检;加入 index_basic 校验七指数代码、发布方和终止日期。增强字段参与计算时必须写入参数版本,不能静默改变历史结果。[复现建议]
历史回填、每日增量与幂等
历史回填顺序
- 先回填
trade_cal、stock_basic全状态、namechange、index_basic、index_classify,建立代码、生命周期、版本和交易日维表。 - 再回填
dc_member每日快照和index_member_all成员区间;先完成成员事实,避免用当前成员污染历史。 - 回填
daily、daily_basic、sw_daily、index_daily和adj_factor,先形成价格与成交事实。 - 最后回填
moneyflow_dc、moneyflow和moneyflow_ind_dc。moneyflow_dc只能从 2023-09-11 开始,早期缺口必须显式标记,不能用 0 填充。 - 在原始层通过覆盖率、重复键、单位和生命周期检查后,再生成成员有效日、窗口收益、资金聚合、替代指标和公开页面对账结果。
每日增量 DAG
flowchart TD
A[trade_cal 确认开市日 T] --> B[盘前 stock_basic / adj_factor / 分类变更]
B --> C[盘后轮询 daily / daily_basic / index_daily / sw_daily]
C --> D[拉 moneyflow_dc / moneyflow / moneyflow_ind_dc]
C --> E[拉 dc_index / dc_member / suspend_d]
D --> F[完整性与单位校验屏障]
E --> F
F --> G[生成 T 日 point-in-time 有效成员]
G --> H[逐股事实与板块/行业窗口聚合]
H --> I[公开发布物对账与版本化指标计算]
I --> J[原子发布 manifest + hash + last_good]
不能只按固定钟点启动一次。daily、daily_basic、资金流和成员数据的到达时间不同,应分别轮询到“日期正确、行数/覆盖率达标、关键字段非空”,再通过校验屏障;超时则保留上一个 last_good 并标记 stale/partial,不发布假完整结果。OneChartLab 页脚的约 17:00—17:30/视频简介的约 17:10—17:40 只应作为观察窗口,不是 Tushare SLA。[页面与作者自述;复现建议]
幂等与修订
所有事实表按上文自然业务主键 upsert。先对同一请求参数和规范化响应计算 hash:相同则记 unchanged,不同则在原始版本表新增 observed_at/source_revision,再更新当前投影。成员、名称和生命周期表不得做破坏性覆盖;派生结果主键至少包含 (metric_version, universe_version, trade_date, entity_code)。公开 OneChartLab 发布物还应把 batch_id/bundle_id/revision_watermark/content_sha256 放入唯一约束或发布身份,允许同一 as_of_date 多修订共存。[复现建议]
Point-in-time 与证券状态处理
dc_member 已直接提供交易日粒度,某日成员只来自该日快照。缺少某日快照时应标记 membership_unknown,不能向前或向后填充,除非经过单独验证并记录填充策略版本。[Tushare 官方字段已确认;复现建议]
index_member_all 应原样保存 Y/N 两类响应和 in_date/out_date。候选有效规则是 in_date <= T < out_date,空 out_date 表示仍有效;但剔除日是否排除、is_new=N 是否返回全部历史、同股多次纳入如何表达,都需账号样本验证。验证前不要把这个候选规则写成供应商保证。[复现建议;需实测]
stock_basic 默认只返回上市状态 L,历史回填必须显式拉取 D/P/G/UN。证券只有在 list_date <= T 且 delist_date 为空或 T <= delist_date 时才进入生命周期候选;再按 OneChartLab manifest 排除 B 股和北交所。停牌日 daily 不返回数据,必须联合 suspend_d 判断:无行情既可能是停牌,也可能是未上市、已退市、成员无效或供应商延迟,不能把缺行自动变成收益 0。[Tushare 官方与页面/manifest 已确认;复现建议]
namechange 用代码和有效日期恢复历史展示名,不作为稳定身份。ST/风险警示状态若会影响自建 universe,应单独定义并验证数据源;OneChartLab 当前公开 ranking universe 契约没有声明排除 ST,不应根据本项目其他模块的“非 ST”规则擅自改变复现口径。[页面/manifest 已确认;复现建议]
单位、空值与质量规则
必须在原始层保留供应商单位,在规范层显式换算:
| 来源字段 | 原始单位 | 规范换算/注意事项 |
|---|---|---|
moneyflow_dc.net_amount、moneyflow.net_mf_amount |
万元 | 亿元值为 / 10_000;元值为 × 10_000 |
moneyflow_ind_dc.net_amount |
元 | 亿元值为 / 100_000_000;不能沿用个股资金流换算 |
daily.amount、index_daily.amount |
千元 | 亿元值为 / 100_000 |
sw_daily.amount |
万元 | 亿元值为 / 10_000 |
daily.vol、index_daily.vol |
手 | 与 sw_daily.vol 的万股单位分开保存 |
sw_daily.vol |
万股 | 不得与“手”直接相加或比较 |
daily.pct_chg、index_daily.pct_chg、sw_daily.pct_change |
百分数 | 1.5 表示 1.5%;做复合收益时先除以 100 |
OneChart Ratio_Raw_Pct/Swing_Ratio_Val |
公开 payload 的小数比例 | 既有前端展示时乘 100;不要与 Tushare 的百分数字段直接混算 |
建议执行以下质量门槛,但阈值必须由数据分布和公开样本校准后版本化:
- 主键重复、代码格式错误、非有限数、日期不在交易日历、生命周期外观测属于硬错误;空字符串、
None、NaN统一规范为 NULL,不能转成 0。[复现建议] - 对每个交易日分别计算
daily、moneyflow_dc、moneyflow、成员和指数覆盖率;缺失资金流不代表净流入为 0。只有在生命周期有效、非停牌且源接口应有数据时才进入缺失率分母。[复现建议] - 板块有效样本数、总成交额、换手率和成员覆盖率必须随派生结果输出。小样本、低成交额、低换手率或分母接近 0 时标记
available_limited_sample/low_liquidity,禁止仅因比例高就视为强信号。具体阈值公开资料未披露,需校准。[作者自述与公开页面质量语义;需实测] - 计算资金占比候选时,先把
moneyflow_dc.net_amount和daily.amount统一到元,再做sum(net_amount)/sum(amount);分母为 0 或缺失则返回 NULL。该公式只是对账候选,不是已确认的Ratio_Raw_Pct。[复现建议;需实测] - 同日
daily.pct_chg与moneyflow_dc.pct_change、板块逐股聚合与moneyflow_ind_dc只用于差异告警,不应无版本地互相覆盖。不同数据源可能有到达时间、复权和成分口径差异。[Tushare 官方字段已确认;复现建议] index_classify的is_pub=0行业和成分少于 5 的指数可能不发布行情;构造 Macro universe 时应记录剔除原因,不能用 0 收益补齐。[Tushare 官方文档已确认]
仍无法由 Tushare 直接提供或确认的内容
Tushare 数据补齐后,下列内容仍是明确缺口:
Amount_Score和Ratio_Score的标准化、截尾、规模/流动性调整及并列排序稳定键;Ratio_Raw_Pct的精确分子、分母、先聚合后求比或先求比后聚合、异常值处理;- 3—10 个交易日的具体权重、
Swing_Ratio_Val、Swing_Amount_Val和Swing_Score的组合公式; - Macro 核心
D使用的横截面统计量、相对收益基准、90 日自然日/交易日口径、截尾和历史校准; - 行业贡献
C的上游分解和O的定向符号规则。公开数据只能确认ΔD=ΣC、K=ΣO、abs(O)=abs(C)等下游恒等式; - 原站如何生成
accepted_input_hash、revision_watermark、历史修订和last_good,以及未公开的参数版本、输入快照和发布时间戳。
因此,独立实现必须给自建公式新的名称和 metric_version,并同时输出与 OneChartLab 公开序列的误差、覆盖率和样本状态。不能通过拟合一个倍率或选择最接近的 Tushare 字段来宣称“完全复刻”。[页面/公开数据复算已确认缺口;复现建议]
Python 调用骨架
以下骨架只展示调用和幂等批次形状,token 从环境注入,不写入代码、日志或请求清单。Tushare 官方客户端的 DataApi.query 会把动态方法名映射为 api_name,因此 pro.dc_member(...) 与 pro.query("dc_member", ...) 属于同一调用模型。[Tushare 官方 GitHub 源码已确认]
from __future__ import annotations
import os
from collections.abc import Callable
import pandas as pd
import tushare as ts
FIELDS = {
"daily": "ts_code,trade_date,close,pre_close,pct_chg,vol,amount",
"daily_basic": (
"ts_code,trade_date,turnover_rate,turnover_rate_f,volume_ratio,"
"total_mv,circ_mv,limit_status"
),
"moneyflow_dc": (
"trade_date,ts_code,name,net_amount,net_amount_rate,pct_change,close"
),
"moneyflow": "ts_code,trade_date,net_mf_amount,net_mf_vol",
"suspend_d": "ts_code,trade_date,suspend_timing,suspend_type",
"dc_index": "ts_code,trade_date,name,idx_type,level,pct_change,leading_code",
"dc_member": "trade_date,ts_code,con_code,name",
"sw_daily": "ts_code,trade_date,name,close,pct_change,vol,amount",
"stock_basic": (
"ts_code,symbol,name,market,exchange,list_status,list_date,delist_date"
),
"index_classify": (
"index_code,industry_name,parent_code,level,industry_code,is_pub,src"
),
"index_member_all": (
"l1_code,l1_name,l2_code,l2_name,l3_code,l3_name,ts_code,name,"
"in_date,out_date,is_new"
),
}
def build_client():
"""从运行环境创建 Tushare Pro 客户端,不泄露或持久化 token。"""
return ts.pro_api(os.environ["TUSHARE_TOKEN"])
def fetch_trade_date(pro, trade_date: str) -> dict[str, pd.DataFrame]:
"""拉取一个交易日的原始事实;重试、限流和落库由外层批次协调器负责。"""
return {
"daily": pro.daily(trade_date=trade_date, fields=FIELDS["daily"]),
"daily_basic": pro.daily_basic(
trade_date=trade_date, fields=FIELDS["daily_basic"]
),
"moneyflow_dc": pro.moneyflow_dc(
trade_date=trade_date, fields=FIELDS["moneyflow_dc"]
),
"moneyflow": pro.moneyflow(
trade_date=trade_date, fields=FIELDS["moneyflow"]
),
"suspend_d": pro.suspend_d(
trade_date=trade_date, fields=FIELDS["suspend_d"]
),
"dc_index_concept": pro.dc_index(
trade_date=trade_date,
idx_type="概念板块",
fields=FIELDS["dc_index"],
),
"dc_index_industry": pro.dc_index(
trade_date=trade_date,
idx_type="行业板块",
fields=FIELDS["dc_index"],
),
"dc_member": pro.dc_member(
trade_date=trade_date, fields=FIELDS["dc_member"]
),
"sw_daily": pro.sw_daily(
trade_date=trade_date, fields=FIELDS["sw_daily"]
),
}
def fetch_security_dimensions(pro) -> pd.DataFrame:
"""显式拉取全部上市状态及非默认生命周期字段。"""
parts = [
pro.stock_basic(list_status=status, fields=FIELDS["stock_basic"])
for status in ("L", "D", "P", "G", "UN")
]
return pd.concat(parts, ignore_index=True)
def fetch_macro_dimensions(pro) -> dict[str, pd.DataFrame]:
"""拉取申万 2021 二级分类及成员响应;历史/当前响应必须分开保存。"""
classification_version = "SW2021"
industries = pro.index_classify(
src=classification_version,
level="L2",
fields=FIELDS["index_classify"],
)
industries["classification_version"] = classification_version
current_parts = []
historical_parts = []
for l2_code in industries["index_code"].dropna().unique():
current = pro.index_member_all(
l2_code=l2_code,
is_new="Y",
fields=FIELDS["index_member_all"],
)
historical = pro.index_member_all(
l2_code=l2_code,
is_new="N",
fields=FIELDS["index_member_all"],
)
current["classification_version"] = classification_version
historical["classification_version"] = classification_version
current_parts.append(current)
historical_parts.append(historical)
return {
"index_classify": industries,
"index_member_current": pd.concat(current_parts, ignore_index=True),
"index_member_history": pd.concat(historical_parts, ignore_index=True),
}
def ingest(
api_name: str,
params: dict[str, str],
fetch: Callable[[], pd.DataFrame],
) -> None:
"""保存请求身份、原始响应 hash,再按自然业务主键幂等 upsert。"""
frame = fetch()
normalized = normalize_nulls_units_and_dates(
api_name,
frame,
request_params=params,
)
assert_unique_business_keys(api_name, normalized)
raw_version = persist_raw_response(api_name, params, frame)
upsert_current_projection(api_name, normalized, source_version=raw_version)
dc_member 全市场单日若超过 5,000 行,必须按 ts_code 或其他可验证分片重拉;不能接受被截断的“成功”响应。所有接口同理以官方单次上限、返回行数和预期覆盖率判断是否需要分片。[Tushare 官方限量;复现建议]
实施前账号实测清单
- 用目标账号逐一调用 17 个接口,记录成功/失败、错误码、单次行数、分钟级限流和字段集合;尤其验证官方页未写稳定权限的
namechange、suspend_d,以及 manifest 中未找到当前官方页的suspend。 - 在连续至少 5 个交易日记录每个接口首次完整到达时间、后续修订时间和行数,以确定每日 DAG 的轮询、超时与
last_good策略。 - 验证
dc_member的最早历史和按日完整性;验证index_member_all(is_new=Y/N)是否覆盖全部历史、重复纳入、空out_date和剔除日边界。 - 对同一交易日抽取至少一个概念板块、一个东财行业和一个申万二级行业,比较逐股
sum(moneyflow_dc.net_amount)、moneyflow_ind_dc.net_amount与 OneChartLab 公开 raw/成分榜,记录成员覆盖和单位差异。 - 验证停牌日、上市首日、退市前后、更名日、B 股/北交所和当日无资金流的样本,确认“无行、NULL、0、无效成员”四种状态不会混淆。
主要第一方来源
- OneChartLab
sector_rankings/manifest.json:成员、资金流、涨跌幅、停牌、生命周期、单位、聚合与股票池契约。 - OneChartLab
radar_manifest.json:Radar 日期分片和排名历史入口。 - OneChartLab
macro/state.json:Macro 当前/最近有效批次、hash 与修订水位。 - 作者视频《我把自己的交易系统,做成了4个网页工具》:单日流入率的成交额分母语义、3—10 日窗口和 Macro 近 90 日申万二级行业输入语义;未披露精确公式。
- Tushare 官方接口页:
dc_index、dc_member、moneyflow_dc、moneyflow、moneyflow_ind_dc、daily、daily_basic。 - Tushare 官方接口页:
trade_cal、stock_basic、namechange、suspend_d、adj_factor。 - Tushare 官方接口页:
index_classify、index_member_all、sw_daily、index_basic、index_daily。 - Tushare 官方 GitHub
tushare/pro/client.py:Pro 请求结构和动态接口方法实现。
本文结论用于数据工程与公开机制复现,不评价指标的投资有效性,也不代表能够复制原作者未公开的专有算法。