--- name: tdx2db-query description: 查询 tdx2db 同步的 A 股行情数据库(daily_data / minute*_data)。取日线分钟线、均线截面筛选、检查数据新鲜度/完整性、排查同步问题时使用。 --- # tdx2db 数据库查询手册 数据库由 `tdx2db sync` 写入(PostgreSQL / MySQL / SQLite,连接配置见项目 `.env`)。查询前先读 `AGENTS.md` 的 schema 与陷阱清单;本 skill 提供可直接套用的操作模板。 ## 第一步永远是确认数据状态 ```bash tdx2db status --json ``` 关注三点:`daily_data.latest` 是否为预期交易日;`rows`/`codes` 是否符合常识(全市场约 4000+ 只);`warnings` 是否为空。任何分析在数据不新鲜/不完整时都是白做。 ## SQL 模板 **单票日线(含缠论均线族)** ```sql SELECT date, open, high, low, close, volume, amount, ma5, ma13, ma21, ma34, ma55, ma89, ma144, ma233 FROM daily_data WHERE code = :code6 -- 6 位纯数字,如 '600036',不带 sh/sz 前缀! AND date BETWEEN :start AND :end ORDER BY date; ``` **某日全市场截面(成熟股票)** ```sql SELECT code, close, ma5, ma13, ma21, ma34, ma55, ma89, ma144, ma233 FROM daily_data WHERE date = :d AND ma233 IS NOT NULL; -- ma233 非空 ≈ 上市满一年,天然剔除次新股 ``` **最新可用交易日** ```sql SELECT MAX(date) FROM daily_data WHERE ma5 IS NOT NULL; ``` **分钟线**(表按周期选:minute5_data / minute15_data / minute30_data / minute60_data) ```sql SELECT datetime, open, high, low, close, volume, amount FROM minute30_data WHERE code = :code6 AND datetime BETWEEN :start AND :end ORDER BY datetime; ``` **周线/月线**:无独立表,取日线后 pandas `resample('W')`/`resample('ME')` 聚合(open=first, high=max, low=min, close=last, volume/amount=sum)。 **板块成分 / 个股板块归属**(block_type ∈ 行业/概念/指数/地区/风格/特殊) ```sql -- 板块 → 成分(行业为 881 研究行业,一/二/三级各一行,按名或 block_code 定位) SELECT code FROM block_stock_relation WHERE block_type = '行业' AND block_name = '煤炭开采'; -- 全部二级行业(≈ 通达信导出 CSV 的行业口径,板块强弱迭代用这个) SELECT DISTINCT block_name FROM block_stock_relation WHERE block_type = '行业' AND block_level = 2; -- 个股 → 全部板块归属 SELECT block_type, block_code, block_name FROM block_stock_relation WHERE code = :code6; -- 板块成分 JOIN 行情(北交所成员在行情表无数据,JOIN 自然过滤) SELECT d.code, d.close, d.ma233 FROM block_stock_relation b JOIN daily_data d ON d.code = b.code WHERE b.block_type = '概念' AND b.block_name = '人形机器人' AND d.date = :d; ``` 板块表为全量快照(随 sync 更新,无历史版本);板块名以 tdxzs.cfg 官方全名为准,跨口径对齐用 block_code。 **换手率 / 次新股过滤**(股本与上市日期在 stock_info,万股,快照口径) ```sql -- 换手率(%):volume(手)/ltag(万股) 单位差恰好抵消;股本变动点前的历史值失真 SELECT d.date, d.volume / s.ltag AS turnover_pct FROM daily_data d JOIN stock_info s ON RIGHT(s.code, 6) = d.code WHERE d.code = :code6 ORDER BY d.date DESC LIMIT 20; -- 剔除次新股(上市不足 500 天) SELECT RIGHT(code, 6) FROM stock_info WHERE list_date < CURRENT_DATE - 500; ``` **覆盖度自检**(跑批前防"同步不完整静默算子集") ```sql SELECT (SELECT COUNT(*) FROM daily_data WHERE date = (SELECT MAX(date) FROM daily_data)) AS today_n, (SELECT COUNT(*) FROM daily_data WHERE date = (SELECT MAX(date) FROM daily_data WHERE date < (SELECT MAX(date) FROM daily_data))) AS prev_n; -- |today_n - prev_n| / prev_n > 5% ⇒ 疑似同步不完整,先重跑 tdx2db sync 再分析 ``` ## 硬规则 1. **code 一律 6 位纯数字**。`sh600036` / `sz000001` 是 `stock_info` 和文件名的格式,行情表里没有。 2. **停牌日显式处理**:`WHERE date = :d` 查不到就是停牌,需要回退到前一交易日时显式写,禁止用 `<= :d ORDER BY date DESC LIMIT 1` 静默错配。 3. **价格不复权**。除权除息造成的跳空是数据特征不是 bug。 4. **股票名称**:`stock_info.name` 为真实名称(含退市名)。注意 `stock_info.code` 带前缀(`sz000001`),与行情表按 code 关联要 `RIGHT(stock_info.code, 6)`。板块归属查 `block_stock_relation`。 5. **统计结果踩到极端值(0%/100%/历史新低)先复核口径再下结论**。 ## 排查同步问题 | 症状 | 检查 | 处理 | |------|------|------| | 某票查无数据 | 收录范围:仅深 000/001/002/300/301、沪 60/688 | 北交所/ETF/指数不收录,属预期 | | 分钟表行数远少于日线 | `status` 的 warnings | `tdx2db minutes --db-only --incremental` 自愈 | | 当日行数骤降 | 覆盖度自检 SQL | 通达信补做盘后下载 → 重跑 sync | | 增量后仍缺历史 | 该票是否新入库(新股全历史应自动补) | 用 `tdx2db daily --code XXX --db-only --incremental` 单票重同步(必须带 --incremental,否则已有行会触发唯一约束冲突报错)