随仓库附带的本地 A 股行情数据库(marketdb,Python + DuckDB)的工具无关 toolkit。用于查询本地历史 OHLCV、复权数据、做面板 / 因子分析。要拉实时行情或财报请走 ../fuyao/。
本目录是任何使用者(人或 AI agent:Claude Code / Codex / Cursor / ChatGPT / CI 脚本 / Jupyter …)读、更新、分析本地行情数据时的入口。它只放文档,真正的能力面在:
marketdbCLI —— 由pip install -e ./python(或python python/bootstrap.py)安装。给 agent 用时统一加--json。marketdb.MarketDBPython SDK ——from marketdb import MarketDB。- DuckDB 视图
v_daily/v_daily_qfq/v_daily_hfq/v_symbol—— 原始 SQL 走marketdb query或db.query_sql(...)。
本目录刻意不放任何自动触发文件(没有 SKILL.md / AGENTS.md / .cursorrules)。Agent 统一通过 hithink-finance Skill 进入,再按任务路由到本 README。
AI agent 读到本文件后,匹配以下关键词时应该触发:
- 本地 A 股行情 / 历史 K 线 / 日线 / OHLCV
- 复权 / 前复权 / 后复权 / qfq / hfq / 复权因子
- 增量更新 / update-daily / 补当天数据
- 全市场截面 / panel / 因子研究 / 选股回测
- thscode 形态的代码:
600519.SH、300033.SZ、000001.SZ… - 直接 SQL 查 DuckDB /
data/market.duckdb
不要触发:实时盘口、tick 级数据、海外行情、宏观指标、基本面财报(财报走 python/toolkit/fuyao/)。
| 你想做什么 | 用什么 | 一行命令 / 代码 |
|---|---|---|
| 一只票最近一段历史 | SDK get_daily |
db.get_daily("300033.SZ", start="2025-06-12", adjust="forward") |
| 一篮子票(几十只) | SDK get_daily(list) |
db.get_daily(["300033.SZ", "600519.SH"], start=...) |
| 全市场 / 单交易所截面 | SDK get_panel |
db.get_panel(start="2025-06-12", adjust="forward", exchange="SH") |
| 任意 SQL(含 JOIN / 聚合) | CLI query --json 或 db.query_sql |
marketdb query --json --sql "SELECT date, AVG(close) FROM v_daily_qfq WHERE ..." |
| 单股 CSV 落盘 | CLI export |
marketdb export --thscode 300033.SZ --out out/300033.csv --adjust forward |
| 当天 / 最近几天补数据 | CLI auto-sync |
marketdb auto-sync --db data/market.duckdb |
| 落后太久 / 直接全量重建 | CLI auto-sync 或 bootstrap.py |
marketdb auto-sync(自动判 FULL/INCREMENTAL)或 python python/bootstrap.py --force |
| 看 DB 当前状态 | CLI status --json |
marketdb status --json --db data/market.duckdb |
| 自动探查 schema | CLI describe |
marketdb describe --db data/market.duckdb |
| 数据质量校验 | CLI validate --json |
marketdb validate --json --db data/market.duckdb |
如果只能记一件事:先跑 marketdb describe --db data/market.duckdb 把 schema 拿到,再从结果里挑视图,然后 query / get_daily / get_panel 开干。
python python/bootstrap.py # 安装包 + 建库 + auto-sync 拉数据(API 优先,本地兜底)
# 如果包已经装好:
marketdb status --db data/market.duckdbDB 缺失或太旧时,一条命令即可:
marketdb auto-sync --db data/market.duckdb # 需 .env 配好 API_KEY;不需要任何本地 Parquetauto-sync 自动判定:本地为空 → FULL;落后 ≤ 7 个交易日 → INCREMENTAL(10 日增量 dump 合并);落后 > 7 → 回退 FULL。复权事件每次都重拉。下载的临时 Parquet 落到 data/.cache/dumps/,应用后立即删除;下载失败自动重试 1 次,仍失败会提示到 全市场数据导出 手动下载并 python python/bootstrap.py --prefer-local。
旧命令
marketdb update-daily(逐 thscode 走 REST)作为兼容入口保留。
from datetime import date, timedelta
from marketdb import MarketDB
with MarketDB.open("data/market.duckdb") as db:
# 单股近一年(前复权)
end = date.today()
df = db.get_daily(
"300033.SZ",
start=str(end - timedelta(days=365)),
end=str(end),
adjust="forward",
)
# 批量(去重保序),一条 SQL IN (...) —— 比 N 次单股快很多
basket = db.get_daily(
["300033.SZ", "600519.SH", "000001.SZ"],
start="2025-06-12",
adjust="forward",
)
by_code = {c: g.reset_index(drop=True) for c, g in basket.groupby("thscode")}
# 全市场截面(因子研究 / 排序 / 回归)—— 一次顺序扫描,最快路径
panel = db.get_panel(start="2025-06-12", end="2026-06-12", adjust="forward")
close_wide = panel.pivot(index="date", columns="thscode", values="close")
# 任意 SQL,返回 pandas DataFrame
sh_top = db.query_sql(
"""
SELECT thscode, AVG(turnover) AS adv20
FROM v_daily_qfq
WHERE date >= ? AND thscode LIKE '%.SH'
GROUP BY thscode
ORDER BY adv20 DESC
LIMIT 50
""",
["2026-05-01"],
)默认列已去掉 currency / interval(A 股里是常量)。要拿回这两列就直接 db.query_sql("SELECT * FROM v_daily_qfq WHERE ...")。
复权因子查询(校验 / 反推用):
events = db.get_adjustment_events("300033.SZ") # 派息、送股、配股等事件
factors = db.get_adjustment_factors("300033.SZ") # 日频前/后复权因子完整 SDK 参考:docs/sdk.md。
# DB 状态 —— 版本、行数、最大日期
marketdb status --json --db data/market.duckdb
# Schema 自动探查 —— 一次 JSON 拿到所有 table / view / 列 / 行数
marketdb describe --db data/market.duckdb > /tmp/marketdb-schema.json
# 数据质量校验
marketdb validate --json --db data/market.duckdb
# 任意 SQL → JSON
marketdb query --json --db data/market.duckdb \
--sql "SELECT date, close FROM v_daily_qfq WHERE thscode='300033.SZ' ORDER BY date DESC LIMIT 5"
# 单股 CSV 导出
marketdb export --db data/market.duckdb \
--thscode 300033.SZ --out out/300033_qfq.csv --adjust forward
# 增量更新(需要 API_KEY)
marketdb update-daily --db data/market.duckdb
marketdb update-daily --db data/market.duckdb --target 2026-06-12status / validate / query 都支持 --json。JSON 只写 stdout,错误 / 提示走 stderr。退出码:0 成功 · 1 校验失败 · 2 缺 API_KEY(仅 REST 命令)。
完整 CLI 参考:docs/cli.md。
任何 DuckDB CLI / Python duckdb / 其他 DuckDB 客户端都能直接读 data/market.duckdb。视图是稳定契约;原始表(raw_kline_daily、calc_adjust_factor_daily …)也能读,但可能被 rebuild-factors / rebuild-views 重建。
duckdb data/market.duckdb \
"SELECT thscode, MAX(date) FROM v_daily_qfq GROUP BY thscode ORDER BY 2 DESC LIMIT 10"| SDK 函数 | CLI | 说明 |
|---|---|---|
MarketDB.get_daily(code|codes, start, end, adjust) |
query --sql ... / export |
单股或批量;批量走 IN (...);按 (thscode, date) 排序 |
MarketDB.get_panel(start, end, adjust, exchange) |
query --sql ... |
全市场顺序扫描;做截面 / 因子的最薄路径 |
MarketDB.query_sql(sql, params) |
query --json --sql ... |
透传 SQL → DataFrame / JSON |
MarketDB.get_symbols(exchange, asset_type) |
query --sql "SELECT * FROM v_symbol" |
标的目录 |
MarketDB.get_adjustment_events(code) |
query --sql ... |
派息 / 送股等原始事件 |
MarketDB.get_adjustment_factors(code) |
query --sql ... |
日频前 / 后复权因子 |
MarketDB.export_csv(code, out, adjust) |
export --thscode --out --adjust |
单股 CSV |
| —— | status --json |
schema 版本 + 行数 + 最大日期 |
| —— | validate --json |
8 项数据质量校验;出错退出码 1 |
| —— | describe |
全 schema 转储(table / view / 列 / 类型) |
| —— | update-daily [--target YYYY-MM-DD] |
REST 增量合并 |
| —— | sync-symbols |
从 REST 刷 dim_symbol |
| —— | init / rebuild-views / rebuild-factors / import-parquet |
管道命令,一般 python python/bootstrap.py 帮你调 |
不要把大查询结果整段塞回会话上下文。正确流程:
1) CLI/函数 → 把 stdout 重定向到 /tmp/<x>.json(或写到 data/、out/)
2) 把行数 + 文件路径报告回会话
3) 下游消费者(notebook、pandas)从文件读
当前数据规模参考:
raw_kline_daily/v_daily*:约 945 万行(10 年 × 5000 只票)calc_adjust_factor_daily:约 945 万行raw_adjustment_events:约 5.2 万行- 全市场 1 年面板 ≈ 120 万行,pandas 约 100–150 MB
经验法则:
- 单股 × 1 年 ≈ 250 行 → 直接打印没问题
- N 只 × 1 年,N ≤ 20 →
head()看看 OK - 全市场或 N ≥ 100 → 落盘,回报 shape
- SQL 聚合后行数 < 1000 → 直接打印
N > 200 时优先用 db.get_panel(...) 而不是巨长的 IN (...) 列表 —— 更快,也避免 SQL 字符串爆炸。
| 现象 | 原因 | 处理 |
|---|---|---|
marketdb: command not found |
包没装 | pip install -e ./python 或 python python/bootstrap.py |
data/market.duckdb 不存在 |
DB 没建过 | python python/bootstrap.py |
update-daily 报"落后超过阈值" |
本地 DB 落后 > 7 个交易日 | 下新 parquet → python python/bootstrap.py --prefer-local,或把 .env 里的 MARKETDB_MAX_LAG_TRADING_DAYS 调大 |
update-daily 报 missing API_KEY |
.env 没配 |
在 .env 设 API_KEY + BASE_URL |
validate 退出码 1 |
至少一项 error 级别校验失败 | marketdb validate --json 看 issues[].detail |
get_daily 返回 0 行 |
thscode 后缀不对(SH / SZ)或日期范围没数据 |
用 db.get_symbols() 或 marketdb describe 查 |
python/bootstrap.py 检测到本地 Parquet |
refer-to/data/ 下有可用快照 |
使用 --prefer-local,需强制覆盖时加 --force |
复权语义提醒:
adjust="none"→ 不复权原始 OHLCV(权威事实表,对账用)adjust="forward"(前复权)→ 分析默认值,最新价对齐,历史价回调adjust="backward"(后复权)→ 历史价对齐,最新价上调(少用)
| 层 | 对象 | 说明 |
|---|---|---|
| raw | raw_kline_daily |
不复权日 K 权威事实表 |
| raw | raw_adjustment_events |
复权事件(除权除息)权威事实表 |
| calc | calc_adjust_factor_daily |
日频前 / 后复权因子,rebuild-factors 可重算 |
| dim | dim_symbol |
标的目录(sync-symbols 来填) |
| view | v_daily |
不复权 + 干净列 |
| view | v_daily_qfq |
前复权 OHLC(含 forward_factor) |
| view | v_daily_hfq |
后复权 OHLC(含 backward_factor) |
| view | v_symbol |
干净的标的列表 |
| meta | _meta, _import_batches |
schema 版本、批次记录 |
要程序化拿 schema(含类型、行数、最大日期):marketdb describe。源 SQL:marketdb/sql/views.sql。详细文档:docs/schema.md。
安装 hithink-finance Skill 后,Agent 会在本地库覆盖请求窗口时选择 marketdb;未安装 Skill 的仓库内 Agent 也可按根 AGENTS.md 读取本 README。
不要在本目录增加客户端专用 Skill、rules 或上游 REST 契约副本。CLI/SDK/schema/recipes 由本目录维护;远端字段契约统一链接 docs/api/。
python python/bootstrap.py 会安装。手动装:
pip install -e ./python
# 会带入:duckdb, pandas, typer, rich, requests, python-dotenv- Schema 改动 → 把
marketdb/_version.py里的SCHEMA_VERSION升版,重跑init(或python python/bootstrap.py)。 - 新 parquet 快照 → 丢进
refer-to/data/,重跑python python/bootstrap.py --prefer-local。 - 本地 DB 坏了 → 先备份数据库,再按恢复流程重建;不要把删除数据库作为常规修复步骤。
API_KEY只通过.env/ 环境变量。不要贴到代码、提示词、commit 里。- 本地 DuckDB 文件不含任何凭证,可信用户间在同一台机器上共享是安全的。