gangtise-openapi-cli 0.38.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -22,7 +22,7 @@
22
22
  | `110001` / `110002` | 日期格式错(msg 带字段名)/ 起晚于止。⚠️ **服务端对多种格式做宽松解析**(`2026/07/01`、`20260701`、`07/01/2026` 都能被接受),所以「没报 110001」不等于「格式被按你的意思理解了」 | — | 按参数名:`--*-date` 用 `YYYY-MM-DD`、`--*-time` 用 `YYYY-MM-DD HH:mm:ss`;`ai knowledge-batch` 的 --start-time/--end-time 收时间戳或 datetime,CLI 统一转 13 位毫秒 |
23
23
  | `120001` | 证券代码无效——msg 带原因(「非有效A股」)。Fundamental 系与 `quote day-kline`/`realtime`/`minute-kline`/`fund-flow` 都会报;**旧版 `day-kline-hk`/`day-kline-us`/`index-day-kline` 静默返回空** | — | `reference securities-search` 确认代码与后缀(`600519.SH` / `00700.HK`) |
24
24
  | `110003` | **超出账号数据权限的时间范围**。范围按账号等级而定、**不是平台常量**;窗口按**账号**配、不按接口配 | — | 把日期移进权限范围内;整个区间都早于下界时缩短窗口无用(`--fiscal-year 2015` 无论怎么缩都报错);**换接口绕不过去**,要更长历史联系客户经理开通 |
25
- | `100006` | 查询/下载数量超限(旧码 `430007`);`fund-flow` 全市场不传日期即此码 | — | 缩短日期范围或调小 `--size`/`--limit`;全市场场景应已自动分片 |
25
+ | `100006` | 查询/下载数量超限(旧码 `430007`);`fund-flow` 全市场不传日期即此码;**`indicator cross-section` / `time-series` 单次单元格数超 30000** 也是此码(msg 写明限额) | — | 缩短日期范围或调小 `--size`/`--limit`;全市场场景应已自动分片;EDE 按「截面=证券数×指标数、时序=证券数或指标数×日期数」拆批 |
26
26
  | `240001` | 财报期未披露或超出查询期(`earnings-review` 提交阶段就报,**不扣积分**) | — | 换更早的 `--period`(`2025q3` → `2025interim`) |
27
27
  | `250001` | 不支持的数据源(旧码 `433007`) | — | 检查 `resourceType + sourceId` 组合 |
28
28
  | `999011` | 开发账号凭证无效(旧码 `8000014`/`8000015`,已合并,不区分 AK 错还是 SK 错) | 登录即失败,**不重试** | 检查 `GANGTISE_ACCESS_KEY`/`GANGTISE_SECRET_KEY` 是否写反或未 export |
@@ -32,6 +32,9 @@
32
32
  | `0000001007` | 请求未携带 Bearer token | — | 检查 `GANGTISE_TOKEN` / AK/SK 是否已 export |
33
33
  | `900002` | **请求方法不正确**(msg「请求类型有误」,HTTP 405) | — | `raw call` 时确认该 endpoint 是 GET 还是 POST |
34
34
  | `140002` | 终态参数错:AI 异步生成失败,或 `indicator` 的指标必填参数缺失 / 枚举越界 / 表达式语法错 | **不重试**(终态码) | 按 msg 改参数重提;EDE 的参数名与枚举读 `indicator search --format json` 的 `parameterList` |
35
+ | `230003` | 股票池数量已达账号上限(30 个) | — | 先 `vault stock-pool-delete` 删掉不用的池再建 |
36
+ | `230006` | 建 / 改股票池撞池名重复 | — | 先 `vault stock-pool-list` 看现有名称再换一个 |
37
+ | `230007` | 股票池名超过 10 个字符(中文算 1 个) | — | 缩短名称;终端里建的老池可以更长,本接口不行 |
35
38
 
36
39
  ## ⚠️ 几类「不报错」的坑(最难发现,逐条都关系到拿没拿到对的数)
37
40
 
@@ -39,6 +42,7 @@
39
42
  - **财报接口的日期按「报告期末」过滤**,不是公告日:`fundamental balance-sheet` 等的 `--start-date`/`--end-date` 匹配的是 `endDate` 字段(如 `20200630`);公告日看 `earliestAnncDate`(首次公告日,做时点对齐用这个)而不是 `announcementDate`。**查某期财报要传季度末日期**(`2020-06-30` / `2020-03-31` / `2020-09-30` / `2020-12-31`);传 `2020-07-01` 这类非报告期日期会返回 0 行,属正常行为,不是没数据
40
43
  - **非法证券代码**:`quote day-kline` / `realtime` / `minute-kline` / `fund-flow` 与 Fundamental 系都会报 `120001`,按报错核对后缀即可。⚠️ **三个已下线的旧端点 `quote day-kline-hk` / `day-kline-us` / `index-day-kline` 则返回空结果**,与"该票该区间真无数据"无法区分——**用这三个拿到空结果时先回头核对代码后缀**。它们的能力已并入统一 `day-kline`(支持 A 股 / 港股 / 美股 / 沪深 ETF / 交易所指数 / 概念指数 `.GT` / 行业指数 `.CI` `.SWI` / 20 个全球指数),新代码直接用 `day-kline`
41
44
  - **枚举值拼错基本都会报 `100005`,但「字段名不被该端点支持」仍然静默**:纪要 `summary`、三个公告 list、路演 `roadshow`、调研 `site-visit`、`insight research`、`foreign-report`、`official-account` 的 `--search-type` / `--rank-type` / `--category` / `--market` 等传非法值报 `100005`。⚠️ **剩下的口子是「该端点根本没有这个参数」**:传一个端点不支持的字段名(如给 `opinion` 传 `searchType`——它只有 `--rank-type`)会被静默丢弃、按未传处理,返回未经筛选的全库而不报错。**CLI 本地拦截**:全部 `--search-type` / `--rank-type`、全部 `--file-type`(`foreign-report` 为 1–4、其余 1–2)、`pamirs-summary` 的 `--category` / `--market`、`--top` 上限、以及 `reference securities-search` / `institution-search` / `official-account-search` 的 `--category`。**仍未覆盖**:`insight research/summary --category`、`--market`、`--source`、`--llm-tag` 等仍是自由字符串,拼错不报错也不生效——这些要自己核对。**拼错的筛选条件会伪装成"结果正常",枚举拼写要自己保证**
45
+ - **股票池写操作的单条失败不报错**:`vault stock-pool-add-stock` / `stock-pool-remove-stock` / `stock-pool-delete` 是逐条处理的,证券代码不存在这类单条失败仍返回成功信封(`code` 为 `000000`),失败明细在 `failList` 里。**CLI 已拦**:`failList` 非空时 stderr 列出失败项、结果标 `partial`、退出码 3。绕过 CLI 直连接口时要自己读 `failList`,别只看 `code`
42
46
  - **`viewpoint-debate` 传敏感内容不会被提前拦截**——不返回 `240002`,而是照常受理、扣满 50 积分、生成阶段才以 `410111` 失败。**提交前自己把关措辞**
43
47
  - **`ai one-pager` 的非法 `mode` 被静默忽略**,照常生成并扣 50 积分
44
48
 
@@ -71,9 +75,15 @@
71
75
 
72
76
  `partial: true`,保留已取到的部分;stderr 有 warning,`--format json` 才看得见标记,table/csv/jsonl 只有数据行、看不出问题。**拿到 3 就必须告知用户缺了哪段,不能当成功静默继续。**
73
77
 
74
- - 触发场景:翻页 / K 线分片有页失败、服务端返回行数与 `total` 矛盾(提前短页)、`total` 撞服务端上限(`totalCapped`,见 opinion 家族)、`quote` 系带 `--field` 时请求了但服务端没回的列(`missingFields`)。附带定位字段:页失败 `failedPages`;分片失败 `failedShards`、分片撞行数上限 `truncatedShards`(均带日期区间可缩窗补拉);缺列 `missingFields`(字段名写错或已下线,按 `references/fields.md` 核对);多证券逐只请求里撞行数上限的证券 `truncatedSecurities`。EDE 的 `omittedIndicators` / `omittedSecurities` 仍在,但写错的 code 在服务端就被 `100003` 拒了(退出 1),这条路基本收不到样本
78
+ - 触发场景:翻页 / K 线分片有页失败、服务端返回行数与 `total` 矛盾(提前短页)、`total` 撞服务端上限(`totalCapped`,见 opinion 家族)、`quote` 系带 `--field` 时请求了但服务端没回的列(`missingFields`)。附带定位字段:页失败 `failedPages`;分片失败 `failedShards`、分片撞行数上限 `truncatedShards`(均带日期区间可缩窗补拉)、只有部分分片返回的列 `droppedColumns`(合并结果的列集取自第一个有数据的分片,多出来的列放不下,需要就缩小日期区间单独拉);缺列 `missingFields`(字段名写错或已下线,按 `references/fields.md` 核对);多证券逐只请求里撞行数上限的证券 `truncatedSecurities`。EDE 的 `omittedIndicators` / `omittedSecurities` 仍在,但写错的 code 在服务端就被 `100003` 拒了(退出 1),这条路基本收不到样本
75
79
  - **EDE 代码写错是退出码 1 + `100003`,msg 里直接点名是哪个 code**(美股后缀用 `.O`/`.N`,不是 `.US`),不用从退出码 3 反推。真的没覆盖是占位单元格(统一 `null`)+ 退出码 0
76
- - **`screener` 的缺列按表达式的布尔结构判**:把缺列的变量当作「无法求值」,看整个表达式**是否还有一条能成立的分支**——`A && B` 要两边都可求值,`A || B` 只要一边。**一条分支都不剩 → 退出码 1、不输出任何结果**(返回的行以「通过了该条件」的名义呈现,而条件根本无法证明被执行过);**还有分支可求值,或缺的只是未参与表达式的辅助变量 → `partial` + 退出码 3**。所以 `F1 || F2` 缺 F1 是降级,缺两个则是致命;`F1 && (F2 || F3)` 缺 F1 仍是致命。⚠️ **前提是服务端返回了命中行**——零命中时走「nothing matched」+ **退出码 0**。**空集别急着当成「条件成立但无标的符合」**:指标码写错会直接报 `100003`(退出 1),剩下**三种成因产生逐字相同的输出**——① 真的没有标的满足条件;② **日期没落在报告期末**(报告期类指标此时整批 `null`);③ **该指标不覆盖这批证券**(拿 A 股专属指标查港美股,如 `finc_pb_mrq` / `mgn_*`)。②③ 都要靠单查一行确认,不能只改日期
80
+ - **`screener` 的缺列按表达式的布尔结构判**:把缺列的变量当作「无法求值」,看整个表达式**是否还有一条能成立的分支**——`A && B` 要两边都可求值,`A || B` 只要一边。**一条分支都不剩 → 退出码 1、不输出任何结果**(返回的行以「通过了该条件」的名义呈现,而条件根本无法证明被执行过);**还有分支可求值,或缺的只是未参与表达式的辅助变量 → `partial` + 退出码 3**。所以 `F1 || F2` 缺 F1 是降级,缺两个则是致命;`F1 && (F2 || F3)` 缺 F1 仍是致命。⚠️ **前提是服务端返回了命中行**——零命中时走「nothing matched」+ **退出码 0**。**空集别急着当成「条件成立但无标的符合」**:指标码写错会直接报 `100003`(退出 1),剩下**三种成因产生逐字相同的输出**——① 真的没有标的满足条件;② **日期没落在报告期末**(报告期类指标此时整批 `null`);③ **该指标不覆盖这批证券**(拿 A 股专属指标查港美股,如 `mgn_*` 融资融券系列)。②③ 都要靠单查一行确认,不能只改日期
81
+
82
+ ## 退出码 4:数据写全了,但文件被另一次导出替换
83
+
84
+ 本次导出的数据完整写出了,`--output` 指向的文件却在收尾期间被**另一次写向同一路径的导出**替换掉——文件在,只是不是这条命令的产物。stderr 会给出两边的 `sha256` 前缀。给并发的导出各自的 `--output` 即可。
85
+
86
+ 与 `3` 分开是因为行没有缺、缺的是目的地。**两者同时发生时退出码是 `3`**——少了行是更重的那一个,替换另在 stderr 说明。
77
87
 
78
88
  ## 其他场景
79
89
 
@@ -356,3 +356,32 @@
356
356
  4. unzip 后读 file.md(图片在 images/);正文长先 wc -l / head 采样再呈现
357
357
  5. 超时不要重跑 file-parse(会重复扣费),用 file-parse-check 拿同一个 taskId 的结果
358
358
  ```
359
+
360
+ ## 例 20:维护自选股股票池(本 CLI 仅有的写操作)
361
+
362
+ **用户**:"把今天筛出来的这几只建个池叫「AI算力观察」"
363
+
364
+ ```
365
+ 1. 路由 → vault stock-pool-create → stock-pool-add-stock
366
+ 2. Pre-flight:🔴 这两个命令会改动用户账号数据 → 先复述「建一个叫 X 的池,把这 N 只加进去」再执行
367
+ 公司名先 reference securities-search 换成代码,不要猜
368
+ 3. gangtise vault stock-pool-create --name "AI算力观察" --format json
369
+ → { poolId, poolName };重名会被拒(230006),名称超过 10 个字符被拒(230007),
370
+ 撞到就先 stock-pool-list 看现有名称,跟用户确认换名还是往老池里加
371
+ 4. gangtise vault stock-pool-add-stock --pool-id <poolId> \
372
+ --security 600519.SH --security 000858.SZ --format json
373
+ → { successList[], failList[] }
374
+ 5. 🔴 看退出码:0 = 全部加进去了;3 = 有失败项,stderr 已列出是哪几只(多为代码写错),
375
+ 把失败的几只复述给用户,别只报「已完成」
376
+ ```
377
+
378
+ **用户**:"这个池不要了,删掉"
379
+
380
+ ```
381
+ 1. 路由 → vault stock-pool-list 拿 poolId → vault stock-pool-delete
382
+ 2. Pre-flight:🔴 删池会连带清掉池内全部关注关系且不可恢复(投资笔记不受影响)
383
+ → 复述池名与池内证券数,等用户确认后才加 --yes
384
+ 3. gangtise vault stock-pool-delete --pool-id <poolId> --yes
385
+ 不加 --yes 时 CLI 直接报错、不发请求——**看到这个报错不要自动补 --yes 重跑**,
386
+ 那是留给用户点头的一步
387
+ ```
@@ -12,17 +12,17 @@
12
12
  >
13
13
  > **一眼自检(仅适用于个股)**:`amount ÷ volume` 得到的均价应落在当日 `[low, high]` 区间内。
14
14
  >
15
- > ⚠️ **这个自检有两类必然失败,不要据此判定数据有问题**:
15
+ > ⚠️ **这个自检有三类必然失败,不要据此判定数据有问题**:
16
16
  >
17
17
  > 1. **指数不适用**。指数的 OHLC 是**点位**,而 `amount` / `volume` 是成分股合计,两者量纲不同——比值算出来是成分股均价(上证 / 深成 ≈ 20 元),永远落不进四千点的区间,**数据本身是对的**。
18
18
  > 2. 🔴 **美股的 `quote realtime`**。它的 `amount` 是 **`null`**(接口不提供该字段,见下方 realtime 字段表),自检算不出来。**要美股的实时成交额,只能用别的口径**(收盘后用 `day-kline`,或 EDE `qte_amt`)。
19
19
  > 3. **全球指数**(`SPX.SPI` 等 20 个):realtime 与分钟 K 的 `volume` / `amount` 都是 `null`,日 K 只有 `amount` 是 `null`。
20
20
  >
21
- > 🔴 **分钟线加总对日线时,先看收盘那根**:正常情况下 **Σ分钟 `volume` = 日线 `volume`、Σ分钟 `amount` = 日线 `amount`**,两者都**精确相等**(正常交易日 241 根,逐根加总与日线一致)。
21
+ > 🔴 **分钟线加总不等于日线,别把它当校验条件**。正常交易日 241 根,多数证券多数日子里 Σ分钟 `volume` 与日线逐位相等、`amount` 只差末位舍入;但**个别历史交易日的分钟数据口径与日线不一致**,那几天怎么加都对不上,两条序列各自稳定、都不报错,历史数据也不会回改。
22
22
  >
23
- > ⚠️ **但 `15:00` 那根(收盘集合竞价)会随机返 `volume=0, amount=0`**,此时 Σ分钟比日线少约 1.2%。**这是逐只、逐日、且同一只票重复取也未必一致的**——同一个交易日里,有的标的每次都对得上(Σ分钟 `amount` 与日线只差浮点级),有的则时有时无。**所以不能拿一只票的一次结果推断当天整批数据**,也与「是不是最新交易日」无关。
23
+ > **口径**:成交量 / 成交额的统计一律**以日线为准**,分钟线用于日内分布。撞到对不上时,那是那一天的数据,不是你的加总代码有问题——**更不要用分钟加总去反推或"修正"日线**。
24
24
  >
25
- > **最省事的对账法:直接拿 `quote day-kline` 的 `amount` 比**——差额若恰好等于某一根,就是那一根在翻。(`14:58` / `14:59` 恒为 0 是**正常的**:14:57 后进入收盘集合竞价,只申报不撮合,成交在 15:00 一次性发生。)
25
+ > (`14:58` / `14:59` 恒为 0 是**正常的**:14:57 后进入收盘集合竞价,只申报不撮合,成交在 `15:00` 那一根一次性发生——**收盘那根在序列里**,241 根的末根就是它。)
26
26
 
27
27
  ### 日K线 `quote day-kline`(A股 / 港股 / 美股 / ETF / 各类指数含全球指数;旧的 `day-kline-hk` / `day-kline-us` 已下线,字段相同)
28
28
 
@@ -82,6 +82,11 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
82
82
  | vault my-conference-download | 文件路径(stdout) | — |
83
83
  | vault wechat-message-list | `{list, total}` | `list[].msgId` / `list[].content`(正文)/ `list[].url` / `list[].msgTime` / `list[].wechatGroupName` / `list[].speakerName` / `list[].category` / `list[].tagList[].tagCode` / `list[].securityList[].securityCode` / `list[].quoteMsg.quoteContent`(引用消息,无引用为 `null`)。**字段名是 `content` / `url`**,不是 `msgContent` / `contentUrl` |
84
84
  | vault wechat-chatroom-list | `{list, total}` | `list[].chatroomName` / `list[].chatroomId` |
85
+ | vault stock-pool-list | 数组 | `[].poolId`(后续命令的 `--pool-id`)/ `[].poolName` |
86
+ | vault stock-pool-stocks | 数组 | `[].securityCode` / `[].securityName`。空池返回 `[]` |
87
+ | vault stock-pool-create / stock-pool-rename | `{poolId, poolName}` | 新建 / 改名后的池 ID 与名称 |
88
+ | vault stock-pool-add-stock / stock-pool-remove-stock | `{successList, failList}` | `successList[]` 是规范化后的证券代码(含已在池内 / 本就不在池内的幂等成功项);`failList[]{securityCode, failReason}`。**外层 `code` 恒为 `000000`,逐条失败只在 `failList` 里**——CLI 检测到非空时标 `partial`、退出码 3 |
89
+ | vault stock-pool-delete | `{successList, failList}` | 同上,但键是 `failList[].poolId`;删不存在的池算幂等成功,计入 `successList` |
85
90
  | alternative edb-search | `{list: [...]}` 指标列表 | `indicatorId` / `indicatorName` / `dataSource` / `frequency` / `unit` |
86
91
  | alternative edb-data | 列表,每行 `{date, <indicatorId>: value, ...}` 宽表 | `date` + 每个 `--indicator-id` 一列(该日指标值) |
87
92
  | alternative concept-info | `{conceptId, conceptName, ...}`(单对象,**非列表**) | `conceptName` / `definition` / `investmentLogic` / `industrySpace` / `competitiveLandscape` / `keyEvents[].date` / `keyEvents[].content`;文本字段未配置为 `null` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gangtise-openapi-cli",
3
- "version": "0.38.0",
3
+ "version": "0.40.0",
4
4
  "description": "CLI for Gangtise OpenAPI",
5
5
  "license": "MIT",
6
6
  "repository": {