A 股 / TuShare 运维¶
TuShare 是中国大陆市场数据的并存 provider,当前主要用于 A 股基础数据采集。安装可选依赖后,以环境变量或未跟踪的 .env.local 提供 token。显式导出的环境变量优先级高于 .env.local。
当前分钟数据采用显式分源的双入口。minute_1m 保留 Guan legacy canonical。
minute_1m_tushare 是采用独立特征、模型和阈值基线的 TuShare operational canonical。
2026-07-15 启动的采集任务已完成 2022-07-15 至 2026-07-08 共 820 个可获得交易日。跨来源
语义、owner-native 特征和策略来源 A/B 拒绝的是无条件替换 Guan,不阻止 TuShare-native
链路独立晋级。本页的 backfill 命令只写 staging 或 TuShare 原始资产。只有 operational
promotion 工具可以移动 minute_1m_tushare,并会验证 minute_1m 未改变。来源口径、候选
证据和发布步骤见 A 股分钟数据。
uv sync --extra dev --extra tushare
marketdata tushare verify-token
如使用需要自定义 API 地址的高积分 token,在 .env.local 中配置与 token 后缀匹配的
TUSHARE_API_URL_2,或在命令行显式传入:
marketdata tushare verify-token \
--env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com
TUSHARE_API_URL* 会写入 TuShare SDK client 的 API 地址,不等同于 HTTP_PROXY /
HTTPS_PROXY。如果 --token-env TUSHARE_TOKEN_2 且未显式传 --api-url,程序会先读取
TUSHARE_API_URL_2,再回退到 TUSHARE_API_URL。
TuShare 命令默认屏蔽 HTTP_PROXY、HTTPS_PROXY 和 ALL_PROXY。如果当前网络依赖 mihomo、
Clash 或其他本机代理环境变量访问 TuShare 或代理域名,校验和下载命令都需要显式加
--use-proxy:
marketdata tushare verify-token --use-proxy
Raw 镜像¶
TuShare raw、instruments 和 trade calendar 下载默认在 provider 调用期间屏蔽
HTTP_PROXY、HTTPS_PROXY 和 ALL_PROXY,并设置 NO_PROXY=*,避免本机代理超时影响长历史
采集。确需走代理时显式加 --use-proxy。瞬时超时、连接中断、代理错误和 502/503/504 默认最多
重试 3 次,初始等待 2 秒、指数退避上限 30 秒。频率超限默认冷却 65 秒后重试。可用
--retry-attempts、--retry-sleep-seconds、--retry-max-sleep-seconds 和
--quota-cooldown-seconds 调整。
marketdata tushare export-a-share-instruments \
--out "$DATA_PLATFORM_ROOT/assets/tushare/a_share/instruments/a_share_all_instruments_latest.parquet"
marketdata tushare mirror-a-share-trade-cal \
--start-date 20260101 --end-date 20260526 \
--out "$DATA_PLATFORM_ROOT/assets/tushare/a_share/trade_cal/a_share_trade_cal_latest.parquet"
marketdata tushare mirror-a-share-daily \
--start-date 20260101 --end-date 20260526 \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily/a_share_all_20260101_20260526_daily"
# 分钟 OHLCV(写入 TuShare 原始资产或显式 staging)
marketdata tushare mirror-a-share-mins \
--start-date 20260701 --end-date 20260709 \
--token-env TUSHARE_TOKEN_2 --api-url https://proxy-a.example.com \
--cooldown-seconds 0.3 --batch-size 20
# 只下载当日实际交易的北交所动态股票池
marketdata tushare mirror-a-share-mins \
--start-date 20260701 --end-date 20260709 \
--exchange BJ --token-env TUSHARE_TOKEN_2 \
--out-dir "$DATA_PLATFORM_ROOT/staging/tushare_minute_bj_probe" \
--cooldown-seconds 1 --batch-size 20
marketdata tushare mirror-a-share-adj-factor \
--start-date 20260101 --end-date 20260526 \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/adj_factor/a_share_all_20260101_20260526_adj_factor"
marketdata tushare mirror-etf-adj-factor --help
marketdata tushare mirror-etf-daily --help
marketdata tushare mirror-a-share-daily-basic \
--start-date 20260101 --end-date 20260526 \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily_basic/a_share_all_20260101_20260526_daily_basic"
marketdata tushare mirror-a-share-limit-status \
--start-date 20260101 --end-date 20260526 \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/limit_status/a_share_limit_status_20260101_20260526"
marketdata tushare mirror-a-share-moneyflow \
--start-date 20260101 --end-date 20260526 \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/moneyflow/a_share_all_20260101_20260526_moneyflow" \
--token-env TUSHARE_TOKEN_2
marketdata tushare mirror-a-share-fund-portfolio \
--start-date 20141231 --end-date 20260529 \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/fund_portfolio/a_share_all_20141231_20260529_fund_portfolio" \
--token-env TUSHARE_TOKEN_2 \
--page-size 8000 --max-pages-per-period 300 \
--skip-existing
分钟镜像默认断点恢复。每个日期按 20 只证券批量请求。发生请求异常或可控中断时,会先将此前
成功批次合并写入 partial checkpoint。完整 sidecar 会绑定 Parquet 的 SHA-256、schema、行数和
证券集合。旧分区、损坏文件或与 sidecar 不一致的文件不会被静默信任,中断后只继续缺失证券。
每只证券必须满足已审计的 241 分钟网格,否则该日期保持 partial。显式 --force 才会刷新已经
完整的日期。
--batch-size 默认仍为 20,允许范围为 1–33。截至 2026-07-15,分钟 endpoint 明确单次响应
上限为 8000 行。完整 1min 证券日固定为 241 行,因此 33 只对应 7953 行,仍在上限内,而
34 只对应 8194 行,会产生被截断的风险。这个 33 的上限只适用于这里的完整 241-bar 1min
请求,不能外推到其他 endpoint、频率或非完整交易日语义。provider 调整行数上限后必须重新验证。
把生产或长历史任务从 20 调到 33 前,先在隔离 staging 对同一批交易日、同一动态证券池做 A/B
验证。两组任务分别使用 --batch-size 20 和 --batch-size 33,并比较完整 sidecar、证券集合、
241-bar 网格、Parquet 行数和标准化后的键值内容,同时记录实际分钟请求数、耗时、重试及限频冷却。
历史 backfill 的 batch size 属于不可变 plan identity,两组应生成不同 plan/run 目录。只有内容完全
一致且 33 未增加 partial、截断或限频异常时,才把 33 用于后续长任务。否则保留默认 20。
分钟命令会在 token 预检前自动加载仓库或当前目录中未跟踪的 .env.local / .env,不需要先
手工 source。--exchange BJ 在每个交易日解析完整 daily traded universe 后按 .BJ 后缀
筛选,sidecar 的 universe rule、source 和 hash 都绑定该过滤条件。该机制区别于会因上市或停牌
日期失效的静态 --symbols 列表。exchange-filtered mirror 必须显式指定独立 --out-dir,避免与默认
全 A raw 分区发生 universe identity 冲突。
少量、离散的 full-day promotion 缺口适合使用 bounded chunk runner。它直接读取既有
a_share.minute_tushare_full_day_plan.v1,完整校验 source root 中已有的 sidecar/Parquet 绑定,
每次只选择最早的 N 个未完成日期。先用纯读取 dry-run 查看本次选择:
marketdata tushare run-a-share-minute-full-day-chunk \
--plan "$DATA_PLATFORM_ROOT/metadata/minute_fusion/tushare_full_production.json" \
--full-day-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/minute_1m_full" \
--receipt-dir "$DATA_PLATFORM_ROOT/metadata/minute_backfill/full_day_chunk_receipts" \
--max-dates 3 --token-env TUSHARE_TOKEN_2 --dry-run
确认后去掉 --dry-run。默认 --max-dates 3、--batch-size 20、--cooldown-seconds 1。也可
保守改为 1,或在稳定窗口改为 5。一个 invocation 只调用一次 hardened mirror,并通过
trading_dates 在进程内逐日串行执行,没有 worker/并行参数。每次 actual invocation 自动创建唯一
JSON receipt,记录 plan SHA-256、选择日期、endpoint 标识、限速/重试参数和每个完成分区的紧凑
SHA-256 绑定。receipt 不记录 token 值。source root 上的 flock 会阻止重叠定时任务,即使两次调用
使用不同 receipt 目录也不能并发。
进程中断时,minute mirror 仍先写 daily partial sidecar。runner 会尽力将本次 receipt 标记为
partial/interrupted。下次使用同一条命令时重新从 sidecar 判定完成状态,只选择仍未完成的日期,
无需改 plan 或拼接 shell 日期。所有 plan 日期完成后,实际调用返回 noop 且不要求 token、
不再写空 receipt,定时器可以继续执行完整性复核而不制造文件。dry-run 不加载 token、不联网、
不创建 lock/receipt/目录,适合在安装定时任务前反复审查。
该 runner 不提供 BJ-only 模式,也不修改 derived/current。独立北交所历史仍走专门 backfill 和
promotion 流程。
历史分钟 canonical 当前由 Guan annual、Guan deal 和 TuShare full day 共同组成。少量抽查可以直接使用上面的 mirror 命令。BJ-only 历史补齐、全 A 对照历史和 Guan 替换研究使用下面的不可变计划与 staging runner,禁止逐日改写生产分钟目录。
分钟历史 backfill 计划与续跑¶
planner 只读取本地 trade calendar 和 instruments Parquet,不调用 TuShare。每个计划固定来源文件 SHA-256、scope、日期、月/年分段、限速参数、endpoint 标识和单 worker 约束,并将数据目录固定为:
$DATA_PLATFORM_ROOT/staging/tushare_minute_backfill/runs/<plan_id>/data/
先分别生成 BJ-only 与全 A 计划:
mkdir -p "$DATA_PLATFORM_ROOT/metadata/minute_backfill"
marketdata tushare plan-a-share-minute-backfill \
--scope bj-only \
--start-date 20160104 --end-date 20260709 \
--trade-cal "$DATA_PLATFORM_ROOT/assets/tushare/a_share/trade_cal/a_share_trade_cal_latest.parquet" \
--instruments "$DATA_PLATFORM_ROOT/assets/tushare/a_share/instruments/a_share_all_instruments_latest.parquet" \
--backfill-root "$DATA_PLATFORM_ROOT/staging/tushare_minute_backfill" \
--plan "$DATA_PLATFORM_ROOT/metadata/minute_backfill/bj_only_20160104_20260709.plan.json" \
--segment month --batch-size 20 --cooldown-seconds 1 \
--token-env TUSHARE_TOKEN_2
marketdata tushare plan-a-share-minute-backfill \
--scope all-a \
--start-date 20160104 --end-date 20260709 \
--trade-cal "$DATA_PLATFORM_ROOT/assets/tushare/a_share/trade_cal/a_share_trade_cal_latest.parquet" \
--instruments "$DATA_PLATFORM_ROOT/assets/tushare/a_share/instruments/a_share_all_instruments_latest.parquet" \
--backfill-root "$DATA_PLATFORM_ROOT/staging/tushare_minute_backfill" \
--plan "$DATA_PLATFORM_ROOT/metadata/minute_backfill/all_a_20160104_20260709.plan.json" \
--segment year --batch-size 20 --cooldown-seconds 1 \
--token-env TUSHARE_TOKEN_2
BJ-only 计划会把有效起始日限制为北交所首个交易日 2021-11-15。全 A 计划保留沪、深、北当日
动态交易股票池。二者有不同 plan_id 和 run 目录,不能共用 receipt。
首次试跑可以给 planner 增加 --max-dates 5 或 --request-budget 500。request budget 是硬上界:
每个日期按该 scope 在完整历史 instruments master 中的 canonical 唯一证券总数除以 batch size
向上取整,不依赖可能受旧代码映射影响的历史上市区间估计。区间估计仍在 summary 中作为诊断,
receipt 则分别记录计划请求上界和实际成功分钟请求数。预算不包含 stock_basic、daily 和
daily_basic 发现请求。这些请求的最小估算会单列。达到任一限制时,planner 只选择日期前缀并在
计划中记录 truncated_by。--dry-run 校验规划但不写 plan。
非连续缺口使用 --dates-file,文件可以是换行/逗号分隔的 YYYYMMDD 文本、JSON 日期数组,
也可以是顶层含 dates 数组的 full-day promotion plan。planner 会将整个文件 SHA-256 绑定到
plan,并要求每个日期都处于起止范围且在本地 calendar 中开放。例如 28+58 个离散目标日可以
直接写入同一文件,再按月份或年份分段:
marketdata tushare plan-a-share-minute-backfill \
--scope all-a --start-date 20260427 --end-date 20260709 \
--dates-file "$DATA_PLATFORM_ROOT/metadata/minute_backfill/tushare_full_day_production.plan.json" \
--trade-cal "$DATA_PLATFORM_ROOT/assets/tushare/a_share/trade_cal/a_share_trade_cal_latest.parquet" \
--instruments "$DATA_PLATFORM_ROOT/assets/tushare/a_share/instruments/a_share_all_instruments_latest.parquet" \
--backfill-root "$DATA_PLATFORM_ROOT/staging/tushare_minute_backfill" \
--plan "$DATA_PLATFORM_ROOT/metadata/minute_backfill/full_a_gaps.plan.json" \
--segment month --request-budget 30000 --token-env TUSHARE_TOKEN_2
执行前先生成不调用 API 的 dry-run receipt,然后开始单 worker 续跑:
marketdata tushare run-a-share-minute-backfill \
--plan "$DATA_PLATFORM_ROOT/metadata/minute_backfill/bj_only_20160104_20260709.plan.json" \
--receipt "$DATA_PLATFORM_ROOT/metadata/minute_backfill/bj_only_20160104_20260709.receipt.json" \
--token-env TUSHARE_TOKEN_2 --dry-run
marketdata tushare run-a-share-minute-backfill \
--plan "$DATA_PLATFORM_ROOT/metadata/minute_backfill/bj_only_20160104_20260709.plan.json" \
--receipt "$DATA_PLATFORM_ROOT/metadata/minute_backfill/bj_only_20160104_20260709.receipt.json" \
--token-env TUSHARE_TOKEN_2
runner 固定 workers=1,逐月或逐年调用已有 hardened minute mirror。日期请求异常或可控中断
时由 _minute_mirror.json 保存 partial checkpoint。segment 完成或失败后原子更新 receipt。重新
执行会跳过 receipt 中已完成的 segment,并由 daily sidecar 继续未完成证券。receipt 记录 fetch
vintage、经过净化的 endpoint 标识、实际成功请求数和错误,但只记录 token 环境变量名,绝不记录
token 值。失败信息
也会替换当前 token 和原始 endpoint 字符串。如果实际逻辑请求数超过计划硬上界,receipt 标记
budget_violation 并阻止原计划续跑,需根据新的 master vintage 重新生成计划。
计划与 receipt 完成后仍不能据此发布。staging 数据必须另行执行完整性、口径和市场 overlay 校验,再进入 promotion。runner 本身没有任何 current alias 或生产目录切换能力。
配额受控的分钟替换 campaign¶
scripts/operations/tushare_minute_replacement_campaign.py 用于把一个离散全市场日期集合拆成
可恢复、互不重叠的双 lane 日批次。prepare 会扫描所有已知 run root 的 daily sidecar union,
先排除已经通过 full-universe promotion 校验的日期,把 partial 日期登记为原地续传,再把 fresh
日期按默认每日 50 日、奇偶索引 25 + 25 拆分。首日自动拆成每 lane 3 日 canary 和剩余 main
phase。它只生成 staging plan/manifest,不请求 API。
run-next 持有 campaign 级 flock,检查正式 refresh/backup 服务均未运行,顺序续完 partial,
然后错峰启动两个 single-worker plan。每个 phase 完成后逐日调用
validate_complete_minute_partition(..., require_full_universe=True) 并原子更新 ledger。canary 未
全部通过时不会进入 main。它每次最多完成一个 campaign 日,partial 或 quota 退出会保留原
sidecar,下一次从缺失证券续传。不要同时恢复生成 campaign 前的宽计划,否则不同 run root 会
重复请求相同日期。
需要利用同一个配额窗口连续跨 campaign 日推进时,使用显式的预算模式:
uv run python scripts/operations/tushare_minute_replacement_campaign.py run-budgeted \
--manifest "$CAMPAIGN_DIR/manifest.json" \
--max-new-rows 67000000 \
--max-runtime-seconds 14400 \
--poll-seconds 10 \
--interrupt-grace-seconds 300 \
--quota-timezone Asia/Shanghai \
--quota-reset-guard-seconds 1200 \
--run-window-start 00:45 \
--run-window-drain 04:15 \
--run-window-stop 04:20 \
--heartbeat-seconds 300 \
--no-progress-limit 2 \
--single-lane-threshold-rows 5500000
run-budgeted 在每个本地配额日第一次启动时,以所有 mutable daily sidecar 的
partition.rows 建立窗口基线,并把窗口基线与高水位写入 campaign ledger。同一配额日再次运行
时会继承已经消耗的行数。前一配额日完整下载或保存在 partial checkpoint 中的行不会占用新窗口。
完成当前 campaign 日后,只要窗口预算和运行时间仍有余量,就继续下一个日批次。两条 lane 共用
同一个软行数阈值。到达阈值或 monotonic runtime 后,runner 向所有仍在运行的 lane 发送
SIGINT,等待 minute mirror 原子保存 partial sidecar,再以成功状态结束本轮。04:15 使用
北京时间墙钟开始排水,04:20 强制结束仍未退出的 lane。每次 poll 都重新读取墙钟,因此机器
suspend 后恢复不能绕过截止线。启动时间不在 00:45–04:15 时不会创建 lane。任一 sidecar
损坏、日期不匹配或行数倒退都会 fail closed。
父 runner 主动发出的 SIGINT、对应的 interrupted/partial receipt 和退出码 130 是正常
checkpoint。没有内部停止原因的非零 lane 退出属于可重试失败,脚本返回 75。receipt 中的
budget_violation、failed immutable-plan receipt、校验或记账错误属于致命失败,返回 70。完整
sidecar 不能掩盖这些 receipt 证据。共享账本的 MinuteQuotaExceeded 或
MinuteQuotaPoolClosed 会映射为正常的 shared_quota_exhausted checkpoint,并避免重试风暴。
连续两轮没有新增持久化行会写入 stalled health 并熔断后续自动 tick。排障后仅可显式使用
--allow-stalled-retry 做一次恢复尝试。
ledger.json.active_run 每 5 分钟更新 run id、PID、heartbeat、运行时长和新增行数。只读状态命令
支持人读格式和稳定 JSON:
uv run python scripts/operations/tushare_minute_replacement_campaign.py status \
--manifest "$CAMPAIGN_DIR/manifest.json"
uv run python scripts/operations/tushare_minute_replacement_campaign.py status \
--manifest "$CAMPAIGN_DIR/manifest.json" --json
输出包含 complete/partial/remaining、当前 campaign 软额度、最近停止原因、heartbeat health、下一 安全窗口和基于近期窗口的区间 ETA。这里的 campaign 额度属于本地估算。启用共享账本后应 同时查看其 consumer/pool 状态。
行数预算依据已持久化 sidecar 计算,只是 campaign 工作量软阈值。服务商硬限制按物理请求次数
计算。共享账本会在每次 stk_mins 发送前原子预占 1 个 request slot,0 行、小批和满 8,000 行
响应都消耗 1 次,每次外层重试也分别记账。committed/reserved/uncertain 会占用请求池,只有能
证明未发送的 released 和门禁拒绝的 rejected 不占用。生产使用 10,000 次完整保底池。只有
21:15 后的 tail-filler 开启 burst,20,000 上限扣除 500 次探测余量后有效上限为 19,500。
若分钟 provider 已部署共享额度账本,run-next 和 run-budgeted 可把同一组参数透传到 preflight
和两条 backfill lane:
--minute-quota-mode enforce \
--minute-quota-db "$DATA_PLATFORM_ROOT/metadata/tushare/minute_quota/minute_quota.sqlite3" \
--minute-quota-consumer replacement_campaign \
--minute-quota-gate requests \
--minute-quota-limit-requests 10000 \
--minute-quota-burst-limit-requests 20000 \
--minute-quota-safety-requests 500 \
--no-minute-quota-allow-burst \
--minute-quota-limit-rows 160000000 \
--minute-quota-safety-rows 4000000
这些参数只形成运行时配置,不修改 immutable manifest。也可用 canonical
MDP_TUSHARE_MINUTE_QUOTA_* 环境变量提供配置。consumer 缺省固定为
replacement_campaign,两条 lane 不拆成不同 consumer。接近
--single-lane-threshold-rows 时,已运行的双 lane 会确定性向名称排序靠后的 lane 发送 SIGINT,
等它原子写 partial 后让另一 lane 继续。被排水 lane 明确记录为 intentional checkpoint。若一次
invocation 启动时已低于阈值,则只启动第一条未完成 lane。请求级 reservation 仍是控制精确在途
额度的主门禁。--minute-quota-allow-burst 只能由 tail-filler 使用。普通 campaign、accelerator、
DailyWatch 和 Top200 都必须留在保底池并受 request hold 保护。
共享账本状态可按实际 token 和北京时间配额日读取:
marketdata tushare minute-quota-status \
--token-env TUSHARE_TOKEN_2 \
--minute-quota-db "$DATA_PLATFORM_ROOT/metadata/tushare/minute_quota/minute_quota.sqlite3" \
--minute-quota-mode enforce \
--minute-quota-gate requests \
--minute-quota-limit-requests 10000 \
--minute-quota-burst-limit-requests 20000 \
--minute-quota-safety-requests 500 \
--minute-quota-limit-rows 160000000 \
--minute-quota-safety-rows 4000000 \
--json
状态输出只包含短 token fingerprint,并列出 committed、reserved、uncertain、residual holds、 available 和各 consumer 明细。该命令不会创建 request reservation。读取状态时会把租约已过期的 reservation 保守结算为 uncertain。数据库旁的隐藏 HMAC key 文件必须与 SQLite 文件一同备份。
完整生产调度为:00:05 coordinator 建立 DailyWatch/Top200 request holds。00:45–04:20 历史
campaign。05:20 DailyWatch 原始数据完成后释放预留。08:00–16:40 accelerator 补足保底区。
21:00 Top200 原始数据完成后释放预留。21:15–23:35 tail-filler 探测浮动区。下载机会 timer 不设
Persistent=true,hard-stop 与 coordinator 可 persistent。同一个 service 实例和 campaign flock
会拒绝并发。Top200 的 tail 放行只检查 raw-completeness marker,不依赖后续 factor/walk-forward
结果。完整模板、renderer、marker 契约与启用命令见 scripts/systemd/README.md。
--quota-reset-guard-seconds 会在本地午夜前预留保护带。同一配额日的手工机会任务与凌晨任务
共享 ledger 高水位。campaign 仍然只是 raw acquisition + 结构 QA。Guan/TuShare 语义差异
审计和 production 切换必须作为独立门禁。
配额策略在同一个上海自然日内不可变。若部署时当天已经存在旧的 rows pool,coordinator 返回
75。该非零状态会让 coordinator unit 保持 failed,并通过有序的 Requires= 阻断所有下游下载,
不能把它登记成成功退出。策略在当天无法安全自愈,因此 service 不立即循环重试,后续机会 timer
可以重试 prerequisite,persistent coordinator timer 会在次日 00:05 再次运行。可通过
systemctl --user status tushare-minute-quota-coordinator.service 和
$HERMES_LOGS_DIR/tushare_minute_quota_coordinator.log 查看失败状态与结构化延后原因。tail 的策略
条件也会在任何 provider 请求前跳过。次日才建立新的 requests pool 和 holds,不得原地改写当天
pool。
全部目标日期完成后,runner 会重新做 full-universe reconciliation,并原子写入
acquisition-readiness.json。marker 固定声明 acquisition_complete=true、
structural_ready=true、semantic_audit=pending、promotion_ready=false、
cutover_performed=false。后续 timer 只校验 marker 后快速退出,绝不修改 production alias。
如果完整 campaign 的 marker 因控制面中断或旧版本写入顺序而与最终 ledger 哈希不一致,使用 只读数据源的 reconciliation 入口重建 marker。该命令不联网、不修改 ledger,也不触碰 production alias。它会重新校验全部 full-universe 分区、lane receipt 和文件绑定:
uv run python scripts/operations/tushare_minute_replacement_campaign.py \
reconcile-readiness --manifest "$CAMPAIGN_DIR/manifest.json"
日频类 TuShare 镜像按开放交易日请求全市场,并写入:
data/trade_date=YYYYMMDD/part.parquet
长历史下载先生成分段计划,再按月或按年续跑:
marketdata tushare backfill-a-share-history \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--start-date 20240101 --end-date 20260531 \
--dataset daily --dataset adj_factor --dataset daily_basic --dataset limit_status \
--token-env TUSHARE_TOKEN_2 \
--segment month \
--dry-run
确认计划后去掉 --dry-run 执行。全部成功后可用 --sync-latest 将 canonical latest alias 指向本次 snapshot。
重复运行同一输出目录时默认跳过已存在的 trade_date partition,因此可以用于补齐上次因超时或限额失败的缺口。
补齐 2008–2014 复权因子和涨跌停价格时先写 staging,不切换 latest。所有请求显式使用
15000 积分 token 环境变量并经 xiaodefa 转发:
marketdata tushare backfill-a-share-history \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--start-date 20080101 --end-date 20141231 \
--dataset adj_factor --dataset limit_status \
--token-env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com \
--segment year \
--dry-run
审阅 dry-run 计划后去掉 --dry-run。在覆盖率、逐日唯一键和分区 receipt 全部通过前不要增加
--sync-latest。研究端继续把现有长历史 raw 结果与约束版并列。
Daily Clean 和 Universe¶
build-a-share-daily-clean 默认使用 memory-managed streaming 构建:按 trade_date 分批读取 raw
partition,写入临时暂存目录,再用 streaming Parquet writer compact 成兼容下游的
data/<symbol>.parquet 布局。默认每 120 个交易日 flush 一次。当 WSL / Linux MemAvailable
低于 2048 MB 时提前 flush,低于 1024 MB 时中止并报错。可用 --batch-trade-dates、
--memory-soft-limit-mb、--memory-hard-limit-mb 调整,传 0 可关闭对应 memory guard。
validate-a-share-daily-clean 使用列投影和 Parquet batch scan,不会逐文件做 pandas 整块读取。
baseline profile 是当前数据刷新发布前的阻塞门禁,覆盖 manifest 对账、字段类型、唯一键、
OHLC、成交量和成交额。research profile 在此基础上增加估值、涨跌停、停牌、交易日历、上市天数、
板块分类和 ST 来源校验。研究级检查还逐行核对 is_st 与定日 ST 历史,来源回执、哈希或日期覆盖不合格时失败。--st-history-file 指向由 build-a-share-st-history 生成的
st_history_reconstructed.parquet 或已发布的 latest 资产,配套 receipt 必须为 complete
且覆盖全部构建日期。
is_st 按交易日匹配这份历史表。daily_clean v2 同时输出 st_available_from,并由研究级检查逐行核对两项值与 ST 历史来源。没有历史表时,is_st 和可用时间都为未知值,研究级校验拒绝该资产。
ST 历史使用 v2 receipt。公告时刻未知时,同日或更晚公告的 st_available_from 取公告日后的首个交易日,公告日期缺失时保持未知。消费者只能在可用日期不晚于决策日时使用正向 ST 状态。历史表按名称生效日期重建,日期规则不能证明具体的日内公告时间,revision_safe=false 仍然有效。
daily_basic 也只是逐日估值 overlay,不能描述成 PIT fundamentals。
marketdata tushare build-a-share-daily-clean \
--daily-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily/a_share_all_20240101_20260529_daily" \
--adj-factor-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/adj_factor/a_share_all_20240101_20260529_adj_factor" \
--daily-basic-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily_basic/a_share_all_20240101_20260529_daily_basic" \
--limit-status-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/limit_status/a_share_limit_status_20240101_20260529" \
--instruments-file "$DATA_PLATFORM_ROOT/assets/tushare/a_share/instruments/a_share_all_instruments_latest.parquet" \
--st-history-file "$DATA_PLATFORM_ROOT/assets/tushare/a_share/st_history_reconstructed/a_share_all_st_history_reconstructed_latest.parquet" \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily/a_share_all_20240101_20260529_daily_clean" \
--min-rows 3000000 --min-symbols 5000
marketdata tushare validate-a-share-daily-clean \
--daily-clean-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily/a_share_all_20240101_20260529_daily_clean" \
--require-valuation --require-limit-status \
--profile baseline \
--out "$DATA_PLATFORM_ROOT/reports/a_share_daily_clean_validation_20240101_20260529.json"
marketdata tushare validate-a-share-daily-clean \
--daily-clean-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily/a_share_all_20240101_20260529_daily_clean" \
--profile research \
--trade-cal-file "$DATA_PLATFORM_ROOT/assets/tushare/a_share/trade_cal/a_share_trade_cal_latest.parquet" \
--fail-on-severity warning --max-warning-rate 0.001 \
--out "$DATA_PLATFORM_ROOT/reports/a_share_daily_clean_research_validation_20240101_20260529.json"
marketdata tushare build-a-share-universe \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--daily-clean-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily/a_share_all_20240101_20260529_daily_clean" \
--start-date 20240101 --end-date 20260529 \
--rebalance-frequency M --lookback-days 60 --min-window-days 30 \
--min-rows 100000 --min-symbols 5000 --min-rebalance-dates 20
marketdata tushare validate-a-share-universe \
--by-date-file "$DATA_PLATFORM_ROOT/assets/universe/a_share_all_full_by_date.csv" \
--latest-symbols-file "$DATA_PLATFORM_ROOT/assets/universe/a_share_all_full_symbols.txt" \
--meta-file "$DATA_PLATFORM_ROOT/assets/universe/a_share_all_full_by_date.meta.yml" \
--expected-as-of 20260529 \
--min-rows 100000 --min-symbols 5000 --min-rebalance-dates 20
Universe builder 使用前置滚动中位成交额,避免在调仓日使用当日成交额。
当前数据发布¶
marketdata tushare plan-a-share-current-refresh \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--start-date 20240101 \
--end-date 20260529
plan-a-share-current-refresh 只输出计划。它不调用 provider、不写文件,也不更新 latest alias。
计划中的顺序是:raw backfill、daily_clean build、baseline validation、research validation、
universe build、universe validation、当前数据发布流程。
完成计划里的构建和验证后,用 promotion gate 切换当前数据契约:
marketdata tushare promote-a-share-current \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--start-date 20240101 \
--end-date 20260529 \
--apply
不加 --apply 时只做发布前检查,不更新当前数据契约。加 --apply 后会执行以下发布动作:
- 将 TuShare raw 和
daily_cleanlatest alias 指向本次 snapshot。 - 将暂存 universe 三个文件及其 manifest 复制到 canonical universe 路径。
- 生成
metadata/current_assets/a_share_current.json。 - 重建
metadata/dataset_registry.csv。 - 写入当前数据契约 health report 和发布证据。
默认 evidence 路径:
$DATA_PLATFORM_ROOT/reports/a_share_current_release_<start>_<end>.json
默认要求这些验证报告已经存在且 status=passed:
$DATA_PLATFORM_ROOT/reports/a_share_daily_clean_baseline_validation_<start>_<end>.json
$DATA_PLATFORM_ROOT/reports/a_share_daily_clean_research_validation_<start>_<end>.json
$DATA_PLATFORM_ROOT/reports/a_share_universe_validation_<start>_<end>.json
如果需要手工检查数据契约或注册表,仍可单独运行:
marketdata contract build --market a_share --provider tushare \
--artifacts-root "$DATA_PLATFORM_ROOT" --target-date 20260526
marketdata contract inspect --market a_share --provider tushare \
--artifacts-root "$DATA_PLATFORM_ROOT" --target-date 20260526 \
--require-start-date 20240101 \
--fail-on-severity error --format json \
--out "$DATA_PLATFORM_ROOT/reports/a_share_current_health_20260526.json"
marketdata registry build --artifacts-root "$DATA_PLATFORM_ROOT" --market a_share
promotion gate 默认只阻断日频当前数据契约发布必须检查的资产:instruments、trade calendar、raw daily
四项、daily_clean 和 universe 三项。PIT fundamentals、行业历史和真实券商门禁仍是研究 readiness
证据,不作为日频当前数据契约发布的默认阻断项。
Research Asset 和 Fundamentals¶
研究资产入口:
marketdata tushare build-a-share-pit-fundamentals --help
marketdata tushare validate-a-share-pit-fundamentals --help
marketdata tushare download-a-share-industry-membership --help
marketdata tushare download-a-share-reference --help
marketdata tushare normalize-a-share-reference --help
marketdata tushare publish-a-share-reference --help
marketdata tushare list-a-share-reference-specs --help
marketdata tushare build-a-share-industry-changes --help
marketdata tushare validate-a-share-industry-changes --help
marketdata tushare mirror-a-share-moneyflow --help
marketdata tushare build-a-share-flow-ownership-features --help
marketdata tushare validate-a-share-flow-ownership-features --help
财务报表、业绩预告、业绩快报、分红、财务指标、审计、主营构成和披露日使用单独的 restartable raw-to-PIT 链路。daily_basic 估值字段是逐日估值 overlay。财务报表 PIT 仍以 raw-to-PIT 链路为准。
历史行业 membership 按来源语义处理。TuShare 申万 index_member_all 和中信
ci_index_member 是区间型来源,核心字段是 ts_code、in_date、out_date、is_new
以及一级/二级/三级行业代码和名称。维护者可以先把授权环境中的 provider 结果保存为
未跟踪 CSV / Parquet,再用本地 extract builder 生成平台资产。例如申万 2021 三级行业:
marketdata tushare download-a-share-industry-membership \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/source/index_member_all_sw2021_l3" \
--src SW2021 \
--level L3 \
--is-new Y \
--is-new N \
--min-rows 1000 \
--min-symbols 1000
marketdata tushare build-a-share-industry-changes \
--source-file /path/to/tushare_index_member_all_sw2021_l3.csv \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/industry_changes/a_share_all_industry_changes_sw2021_l3" \
--effective-date-col in_date \
--end-date-col out_date \
--industry-code-col l3_code \
--industry-name-col l3_name \
--industry-system sw2021_l3 \
--provider tushare \
--min-rows 1000 --min-symbols 1000
marketdata tushare validate-a-share-industry-changes \
--asset-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/industry_changes/a_share_all_industry_changes_sw2021_l3" \
--min-rows 1000 --min-symbols 1000
ST、指数成分和上市公司基础信息属于低频参考数据集,走统一的 reference 链路。原始下载
统一写入一个 staging 目录。stock_st 与 share_float 按日期保存 _parts/,遇到限速后可以
用同一命令续跑。先列出可用的数据集规格:
marketdata tushare list-a-share-reference-specs
REFERENCE_STAGING="$DATA_PLATFORM_ROOT/staging/tushare_reference_20260730"
REFERENCE_DATASETS=(stock_st index_weight stock_company stk_managers share_float)
for dataset in "${REFERENCE_DATASETS[@]}"
do
marketdata tushare download-a-share-reference \
--dataset "$dataset" \
--out-dir "$REFERENCE_STAGING" \
--start-date 20220101 \
--end-date 20260730 \
--token-env TUSHARE_TOKEN_2 \
--request-interval-seconds 0.2 \
--retries 5
done
marketdata tushare normalize-a-share-reference \
--raw-dir "$REFERENCE_STAGING" \
--out-dir "$REFERENCE_STAGING" \
--end-date 20260730 \
--trade-cal "$DATA_PLATFORM_ROOT/assets/tushare/a_share/trade_cal/a_share_trade_cal_latest.parquet"
marketdata tushare publish-a-share-reference \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--raw-dir "$REFERENCE_STAGING" \
--target-date 20260730
未显式传 --index-code 时会下载沪深 300、中证 500、中证 1000、创业板指和上证 50。
未传 --exchange 时 stock_company 覆盖 SSE、SZSE、BSE。index_weight_daily 由月度
index_weight 按真实交易日展开并提供归一化 drift_weight。发布会同时生成日期版本、
原子替换的 latest.parquet 和 .receipt.json(schema、SHA-256、行数、质量状态)。
share_float 按公告日使用 limit + offset 分页,转发端单次容量不会被误当成公告日总量。
如果任何数据集达到配置的 max_pages,下载会明确失败并要求缩小窗口。跨仓消费方
(如 quant-market-data-platform)只读已发布资产并校验 receipt。
历史交易约束与 ST 重建¶
namechange 按年分段并使用 limit + offset 分页。margin_secs、margin_detail、
suspend_d 按年分段,slb_sec_detail 按月分段,margin_secs 和 margin_detail 按开放
交易日分段。st 做全量分页后按生效日过滤。每个分段都
写不可变 Parquet 和 SHA-256 receipt,重复运行只复用哈希匹配的完整分段。以下命令显式经
xiaodefa 转发,receipt 只记录 token 环境变量对应的 endpoint,不记录 token 值:
CONSTRAINT_STAGING="$DATA_PLATFORM_ROOT/staging/tushare_constraints_20260731"
marketdata tushare download-a-share-constraint-reference \
--dataset namechange \
--out-dir "$CONSTRAINT_STAGING" \
--start-date 20060101 --end-date 20260731 \
--token-env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com
marketdata tushare download-a-share-constraint-reference \
--dataset margin_secs \
--out-dir "$CONSTRAINT_STAGING" \
--start-date 20150101 --end-date 20260731 \
--token-env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com
marketdata tushare download-a-share-constraint-reference \
--dataset margin_detail \
--out-dir "$CONSTRAINT_STAGING" \
--start-date 20150101 --end-date 20260731 \
--token-env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com
marketdata tushare download-a-share-constraint-reference \
--dataset suspend_d \
--out-dir "$CONSTRAINT_STAGING" \
--start-date 20080101 --end-date 20260731 \
--token-env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com
marketdata tushare download-a-share-constraint-reference \
--dataset st \
--out-dir "$CONSTRAINT_STAGING" \
--start-date 20080101 --end-date 20260731 \
--token-env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com
marketdata tushare download-a-share-constraint-reference \
--dataset slb_sec_detail \
--out-dir "$CONSTRAINT_STAGING" \
--start-date 20200101 --end-date 20241231 \
--token-env TUSHARE_TOKEN_2 \
--api-url https://proxy-a.example.com
margin_secs 只表示证券进入融资融券标的范围,是做空资格的上界。它不能证明当日有券,也不
包含借券费、可借数量或召回概率。margin_detail 和 slb_sec_detail 是已发生、已报告的融资融券
或转融通交易,无法证明研究组合当时可借到的库存。st 是状态变更事件,只用于交叉验证,不能直接
当作完整逐日 ST 状态。slb_sec_detail 的实际历史覆盖可能短于研究窗口,应保留边界空分段,不能
把空结果外推为当日绝对不可借。全历史逐日下载请求量较大,应先用短窗口 canary 验证权限和
endpoint,再续跑同一 staging 目录。
历史 ST 由完整 namechange 时间线重建。构建器先用后续更名截断开放区间,再以 instruments
的上市日和退市日前一日限制有效区间,并把北交所旧代码归一到当前 920 代码。只在交易日历开放日
展开正样本。可用 2022 年以后的 stock_st 做交叉验证:
marketdata tushare build-a-share-st-history \
--namechange "$CONSTRAINT_STAGING/namechange.parquet" \
--trade-cal "$DATA_PLATFORM_ROOT/assets/tushare/a_share/trade_cal/a_share_trade_cal_latest.parquet" \
--instruments "$DATA_PLATFORM_ROOT/assets/tushare/a_share/instruments/a_share_all_instruments_latest.parquet" \
--stock-st "$DATA_PLATFORM_ROOT/assets/tushare/a_share/stock_st/a_share_all_stock_st_latest.parquet" \
--out-dir "$CONSTRAINT_STAGING" \
--start-date 20080101 --end-date 20260731 \
--min-precision 0.90 --min-recall 0.90
marketdata tushare publish-a-share-constraint-reference \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--source-dir "$CONSTRAINT_STAGING" \
--target-date 20260731
发布默认拒绝缺失资产或未通过阈值的 ST 重建。产物固定标注
pit_class=reconstructed_pit、revision_safe=false。它可以修复历史 ST 过滤,但不能被描述为
当时实时可见且版本安全的 PIT。--allow-partial 只用于诊断性发布,不应进入正式 current。
只需发布已完成且有收据的历史更名源时,可使用 --datasets namechange。此参数仅选择要发布的
数据集,不放宽该数据集的质量和来源收据检查:
marketdata tushare publish-a-share-constraint-reference \
--artifacts-root "$DATA_PLATFORM_ROOT" \
--source-dir "$CONSTRAINT_STAGING" \
--target-date 20260802 --datasets namechange
资金流特征先走 moneyflow raw 加日频成交额、市值 overlay。daily.amount 是千元口径,构建器会除以
10 转成与 moneyflow 金额字段一致的万元口径。daily_basic.circ_mv 也是万元口径。
marketdata tushare build-a-share-flow-ownership-features \
--moneyflow-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/moneyflow/a_share_all_20240101_20260529_moneyflow" \
--daily-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily/a_share_all_20240101_20260529_daily" \
--daily-basic-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily_basic/a_share_all_20240101_20260529_daily_basic" \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/flow_ownership_features/a_share_all_flow_ownership_features_latest" \
--min-rows 100000 --min-symbols 5000
marketdata tushare validate-a-share-flow-ownership-features \
--asset-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/flow_ownership_features/a_share_all_flow_ownership_features_latest" \
--min-rows 100000 --min-symbols 5000
热点研究 raw 资产分三类镜像。热榜、题材行情、涨停/炸板榜、连板天梯和最强板块按交易日分区。
券商盈利预测和机构调研按日历事件日分区。券商月度金股按月份分区。使用 15000 分账户时应显式传
--token-env TUSHARE_TOKEN_2,并确认本地配置了匹配的 TUSHARE_API_URL_2。
marketdata tushare mirror-a-share-ths-hot \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/ths_hot/a_share_all_ths_hot_latest" \
--start-date 20240101 --end-date 20260529 \
--market 热股 --is-new Y \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-dc-concept \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/dc_concept/a_share_all_dc_concept_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-dc-concept-cons \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/dc_concept_cons/a_share_all_dc_concept_cons_latest" \
--start-date 20260203 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
# dc_concept_cons 数据从 20260203 开始,单次最多返回 3000 行。镜像会自动分页并写逐日完整性 receipt。
marketdata tushare mirror-a-share-kpl-list \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/kpl_list/a_share_all_kpl_list_latest" \
--start-date 20240101 --end-date 20260529 \
--tag 涨停 --tag 炸板 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-kpl-concept-cons \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/kpl_concept_cons/a_share_all_kpl_concept_cons_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-limit-step \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/limit_step/a_share_all_limit_step_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-limit-cpt-list \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/limit_cpt_list/a_share_all_limit_cpt_list_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
# 开盘 / 收盘集合竞价接口需要账户单独授权。当前默认只请求 ts_code/trade_date,
# 确认授权和字段后用 --fields 显式传完整字段集合。
marketdata tushare mirror-a-share-stk-auction-open \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/stk_auction_o/a_share_all_stk_auction_o_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-stk-auction-close \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/stk_auction_c/a_share_all_stk_auction_c_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-report-rc \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/report_rc/a_share_all_report_rc_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-stk-surv \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/stk_surv/a_share_all_stk_surv_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-broker-recommend \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/broker_recommend/a_share_all_broker_recommend_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-moneyflow-ths \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/moneyflow_ths/a_share_all_moneyflow_ths_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-limit-list-ths \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/limit_list_ths/a_share_all_limit_list_ths_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-margin-detail \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/margin_detail/a_share_all_margin_detail_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-margin \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/margin/a_share_all_margin_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
marketdata tushare mirror-a-share-hsgt-top10 \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/hsgt_top10/a_share_all_hsgt_top10_latest" \
--start-date 20240101 --end-date 20260529 \
--token-env TUSHARE_TOKEN_2 --skip-existing
# 同花顺概念指数目录是单次快照,不需要 start-date / end-date 参数。
marketdata tushare mirror-a-share-ths-index \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/ths_index/a_share_all_ths_index_latest" \
--src THS \
--token-env TUSHARE_TOKEN_2
# 指数日线按指数代码逐只拉取,合并为单文件资产。--index-code 可重复。
# 用于 benchmark 收益等需要指数行情的场景。
marketdata tushare mirror-a-share-index-daily \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/index_daily/a_share_all_index_daily_20260807" \
--index-code 000300.SH --index-code 000905.SH \
--start-date 20220101 --end-date 20260807 \
--token-env TUSHARE_TOKEN_2 --api-url https://proxy-a.example.com
# 同花顺概念成分数据先拉取 ths_index 获取全部概念代码,再逐概念下载 ths_member。
# 下载量较大,建议设置 --request-interval-seconds 控制频率。
marketdata tushare mirror-a-share-ths-member \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/ths_member/a_share_all_ths_member_latest" \
--token-env TUSHARE_TOKEN_2 --request-interval-seconds 0.1
marketdata tushare build-a-share-hotspot-features \
--daily-basic-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily_basic/a_share_all_20150101_20260608_daily_basic" \
--ths-hot-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/ths_hot/a_share_all_ths_hot_latest" \
--dc-concept-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/dc_concept/a_share_all_dc_concept_latest" \
--dc-concept-cons-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/dc_concept_cons/a_share_all_dc_concept_cons_latest" \
--kpl-list-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/kpl_list/a_share_all_kpl_list_latest" \
--kpl-concept-cons-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/kpl_concept_cons/a_share_all_kpl_concept_cons_latest" \
--limit-step-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/limit_step/a_share_all_limit_step_latest" \
--report-rc-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/report_rc/a_share_all_report_rc_latest" \
--stk-surv-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/stk_surv/a_share_all_stk_surv_latest" \
--broker-recommend-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/broker_recommend/a_share_all_broker_recommend_latest" \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/hotspot_features/a_share_all_hotspot_features_latest" \
--start-date 20240101 --end-date 20260529 \
--min-rows 100000 --min-symbols 3000
marketdata tushare validate-a-share-hotspot-features \
--asset-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/hotspot_features/a_share_all_hotspot_features_latest" \
--min-rows 100000 --min-symbols 3000
dc_concept_cons 镜像按 limit/offset 拉到短末页,并校验每一行的 trade_date 严格等于
目标日、业务键 trade_date + theme_code + ts_code 唯一。接口结果按 theme_code 有序。
分页边界可能切在同一题材内部并产生少量跨页重叠,因此镜像会识别相邻页共享的边界题材,按
theme_code 单独重拉这些题材后替换边界行。若页内题材顺序倒退、非边界业务键重叠、边界
重拉仍重叠、达到最大页数或未出现短末页,任务会 fail closed,不发布新的 partition 或
manifest。
成功 manifest 在 completeness.trade_dates[YYYYMMDD] 记录总数据页数、请求数、offset 页数、
边界修复页数、行数、独立题材数和 theme_code 行覆盖率。page_count 包含 offset 数据页与
边界修复数据页,request_count 还包含用于证明结束的空页请求。只有逐日 complete: true
才可进入生产 fallback。瞬时空结果会原子写入 complete: false,同时保留 last-known-good
Parquet。生产消费者必须以目标日 receipt 为准,不能因旧文件仍存在而判定可用。
公募基金持仓先按报告期下载 fund_portfolio raw,再按披露日后一交易日生成 PIT 持仓特征。
年报和半年报可能超过 100 页,续跑时保留 --skip-existing,必要时提高
--max-pages-per-period。
marketdata tushare build-a-share-fund-portfolio-features \
--fund-portfolio-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/fund_portfolio/a_share_all_20141231_20260529_fund_portfolio" \
--daily-basic-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/daily_basic/a_share_all_20150101_20260608_daily_basic" \
--out-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/fund_portfolio_features/a_share_all_fund_portfolio_features_latest" \
--available-delay-days 1 \
--min-rows 100000 --min-symbols 3000
marketdata tushare validate-a-share-fund-portfolio-features \
--asset-dir "$DATA_PLATFORM_ROOT/assets/tushare/a_share/fund_portfolio_features/a_share_all_fund_portfolio_features_latest" \
--min-rows 100000 --min-symbols 3000
中信行业同理,将 --industry-system 改为 citic_l3,并使用
ci_index_member extract 中的三级行业字段。TuShare index_classify 用于校验申万
2014 / 2021 taxonomy list,不替代 membership interval。
理杏仁行业成分如果在授权环境中以指定日期 snapshot 返回,只能作为 snapshot source 处理。 使用前必须通过本地 entitlement docs 或 authenticated probe 确认 endpoint、字段和覆盖范围。 写入验证记录时应保留 snapshot date、taxonomy、level、source endpoint/extract 和 snapshot frequency。用 snapshot diff 反推区间时,不得把采样频率之外的变更日写成精确 provider 事实。只有当前行业标签、没有 effective history 或 dated snapshot provenance 的输入,不允许用于 历史 PIT 研究。
marketdata tushare list-a-share-fundamentals-specs
marketdata tushare plan-a-share-fundamentals --help
marketdata tushare download-a-share-fundamentals --help
marketdata tushare check-a-share-fundamentals-state --help
marketdata tushare list-a-share-fundamentals-failures --help
marketdata tushare compact-a-share-fundamentals-raw --help
marketdata tushare normalize-a-share-fundamentals --help
marketdata tushare validate-a-share-normalized-fundamentals --help
marketdata tushare build-a-share-fundamentals-pit --help
marketdata tushare validate-a-share-fundamentals-pit --help
marketdata tushare publish-a-share-fundamentals --help
marketdata tushare publish-a-share-pit-fundamentals --help
完整 raw-to-PIT 运维见 ../a-share-fundamentals.md。
RQData A 股入口(已退役)¶
RQData A 股在线读取与采集入口已在 2026-07-26 完全退役,相关代码(rqdata_a_share.py、cli_rqdata.py、rqdata_runtime*.py)已从活跃包移除。当前 A 股主线统一使用 TuShare 平台资产,新研究不应依赖 RQData。
晚间融资融券的延迟补齐¶
prepare_a_share_evening_data.py 对 margin 和 margin_detail 会回看本地 SSE
交易日历中的前两个交易日,只补缺失的历史分区,避免当天返回空数据后一直漏掉次日披露的数据。
已存在的有效非空分区不会重写。其他数据集仍按原来的目标日逻辑执行。日历缺失或不足时,
只尝试目标日,并在 receipt 的 recovery_window_error 中记录原因,不猜测工作日或扩大历史范围。
receipt 的 requested_target_date 表示请求目标,as_of 表示已验证分区的实际最新日期,
target_ready 只有目标日存在有效非空数据时才为真。目标日为空、实际最新数据滞后不超过
两个自然日时,状态为 expected_delay。超过该范围为 stale。无可用分区、请求失败或分区
日期、主键校验失败时,状态仍为 failed,并保留逐日结果及命令退出码。回看窗口按交易日取值,
延迟阈值仍按自然日计算,节假日不会改变这一阈值。
recovered_dates、date_results 和 market_coverage 提供补齐证据。市场数量仅为观测结果,
market_completeness=not_established 表示市场完整性仍需单独认证。此补齐窗口不会修复更早历史缺口,
也不会覆盖已封存原始数据或更改共享别名。