Files
zhixing-system/docs/research/onechartlab-tushare-data-requirements.md
T

39 KiB
Raw Blame History

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 官方确认;到达时点和实际频次需实测

接口名与口径更正

  1. moneyflow_dc 是“个股资金流向(DC)”,其 net_amount 单位为万元;东财概念/行业板块的直接资金流接口是 moneyflow_ind_dc,其 net_amount 单位为元。两者不可因名称相近混用。[Tushare 官方文档已确认]
  2. moneyflow.net_mf_amount 是基于 L2 主动买卖单统计的净流入,官方明确说不能简单由大小单总和相减;这与 OneChartLab manifest 的“主买净额”定义一致。[页面/manifest 与 Tushare 官方文档均确认]
  3. daily 是未复权行情,adj_factor 只是复权因子;若需要 qfq 价格,应使用官方 pro_bar 的 adj="qfq" 或基于版本化规则计算,不能把 adj_factor 当价格。[Tushare 官方文档已确认]
  4. index_daily 官方明确“不包含申万行业指数行情数据”;申万行业必须用 sw_daily。index_classify(src="SW2021", level="L2") 提供分类,index_member_all 提供带纳入/剔除日期的成员关系。[Tushare 官方文档已确认]
  5. 当前官方页面确认的东财板块目录接口是 dc_index,成员接口是 dc_member。不存在用一个静态 dc_member 当前表安全回填全部历史的做法;必须按交易日保存成员快照。[Tushare 官方文档已确认;复现建议]
  6. 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 校验七指数代码、发布方和终止日期。增强字段参与计算时必须写入参数版本,不能静默改变历史结果。[复现建议]

历史回填、每日增量与幂等

历史回填顺序

  1. 先回填 trade_cal、stock_basic 全状态、namechange、index_basic、index_classify,建立代码、生命周期、版本和交易日维表。
  2. 再回填 dc_member 每日快照和 index_member_all 成员区间;先完成成员事实,避免用当前成员污染历史。
  3. 回填 daily、daily_basic、sw_daily、index_daily 和 adj_factor,先形成价格与成交事实。
  4. 最后回填 moneyflow_dc、moneyflow 和 moneyflow_ind_dc。moneyflow_dc 只能从 2023-09-11 开始,早期缺口必须显式标记,不能用 0 填充。
  5. 在原始层通过覆盖率、重复键、单位和生命周期检查后,再生成成员有效日、窗口收益、资金聚合、替代指标和公开页面对账结果。

每日增量 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 官方限量;复现建议]

实施前账号实测清单

  1. 用目标账号逐一调用 17 个接口,记录成功/失败、错误码、单次行数、分钟级限流和字段集合;尤其验证官方页未写稳定权限的 namechange、suspend_d,以及 manifest 中未找到当前官方页的 suspend。
  2. 在连续至少 5 个交易日记录每个接口首次完整到达时间、后续修订时间和行数,以确定每日 DAG 的轮询、超时与 last_good 策略。
  3. 验证 dc_member 的最早历史和按日完整性;验证 index_member_all(is_new=Y/N) 是否覆盖全部历史、重复纳入、空 out_date 和剔除日边界。
  4. 对同一交易日抽取至少一个概念板块、一个东财行业和一个申万二级行业,比较逐股 sum(moneyflow_dc.net_amount)、moneyflow_ind_dc.net_amount 与 OneChartLab 公开 raw/成分榜,记录成员覆盖和单位差异。
  5. 验证停牌日、上市首日、退市前后、更名日、B 股/北交所和当日无资金流的样本,确认“无行、NULL、0、无效成员”四种状态不会混淆。

主要第一方来源

本文结论用于数据工程与公开机制复现,不评价指标的投资有效性,也不代表能够复制原作者未公开的专有算法。