docs(data): akshare 低频 schtask plan(spec §14.5 A+B+C)

spec §14.5 akshare/index 低频 schtask 部署 plan, 待 compact 后新 session 执行:
- A 三表/估值增量(sanguo-ak-eod 日频 + ak-quarter 季频, --force 全量夜间慢跑)
- B 成份股月度(sanguo-index, 改 merge_constituent 可重跑 DROP/REPLACE + 3源wrapper + TDD)
- C 事件类 7 种(ak-events per-date 日频 + ak-stock per-stock 周频)

实测现状: static 停 7/22 18:25(provider依赖) / events 全空(从未采集) /
constituent_unified 7110 静态 / 旧 schtask 全无(方案A stop_all 清了)

关键约束: akshare marker symbol级→三表/估值必须--force更新 / per-stock全量慢+东财限流→夜间 /
merge_constituent RENAME不可重跑→改幂等

plan 自包含(fresh agent 可执行), 关联 memory akshare-low-freq-plan
This commit is contained in:
2026-07-23 08:49:56 +08:00
parent 41cc6d13bf
commit ae3a768091
2 changed files with 225 additions and 0 deletions
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""probe_akshare_status.py — 探查 akshare 低频任务现状(sanguo-bs-akshare + sanguo-index)。
看: 三表 static 各子目录文件数+最新mtime / 事件类数据有没有 / constituent_unified source 分布。
"""
import datetime
import sqlite3
from pathlib import Path
BASE = Path(r"C:\sanguo_vnpy_v2\data")
print("===== data/ 子目录 =====")
if BASE.exists():
for p in sorted(BASE.iterdir()):
if p.is_dir():
n = sum(1 for _ in p.rglob("*") if _.is_file())
print(f" {p.name}/ ({n} files)")
else:
print(f" {p.name}")
print("\n===== static/ 各表文件数 + 最新 mtime =====")
for sub in ["balance", "income", "cashflow", "valuation", "financial_abstract"]:
d = BASE / "static" / sub
if not d.exists():
print(f" static/{sub}: MISSING")
continue
files = list(d.glob("*.parquet"))
if not files:
print(f" static/{sub}: 0 parquet")
continue
mt = max(f.stat().st_mtime for f in files)
print(f" static/{sub}: {len(files)} parquet, latest mtime={datetime.datetime.fromtimestamp(mt):%Y-%m-%d %H:%M}")
print("\n===== 事件类数据(龙虎榜/北向/两融/解禁/大宗/可转债/研报) =====")
for sub in ["longhubang", "north_flow", "margin", "blockade", "block_trade", "convertible_bond", "research"]:
d = BASE / "events" / sub
if d.exists():
files = list(d.glob("*"))
print(f" events/{sub}: {len(files)} files")
else:
print(f" events/{sub}: MISSING")
# data 根下找可能的 events/其它事件目录
for cand in ["events", "akshare_events", "longhubang", "north"]:
d = BASE / cand
if d.exists():
print(f" {cand}/ exists")
print("\n===== constituent_unified source 分布(看 akshare 部分啥时点) =====")
c = sqlite3.connect(str(BASE / "quant_trading.db"))
try:
print(" source 分布:", c.execute("SELECT source, COUNT(*) FROM constituent_unified GROUP BY source").fetchall())
print(" per-index×source:")
for row in c.execute("SELECT index_code, source, COUNT(*) FROM constituent_unified GROUP BY index_code, source ORDER BY index_code"):
print(" ", row)
finally:
c.close()
print("\nPROBE DONE")