gangtise-openapi-cli 0.30.1 → 0.31.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.
@@ -16,7 +16,7 @@
16
16
  | 开高低收 / 成交量等行情与 K 线 | `quote`;免费且支持多证券批量 |
17
17
  | 单证券三大报表全部科目 | 对应 `fundamental` 利润表 / 资产负债表 / 现金流量表命令 |
18
18
 
19
- EDE 不是“搜到就优先”。取数前必须核对:① `indicatorName` + `description` 与目标语义一致;② `scopeList` 覆盖**全部**目标市场和证券类型;③ `parameterList` 的必填参数与枚举可满足。`scopeList` 缺失 / `null` / 空或任一项不符,都视为无法证明覆盖并回退上表的专用接口;专用接口也不支持目标市场时,如实说明当前 CLI 无可用口径,不能用其他语义代替。实测 `valuation-analysis` / `earning-forecast` 仅支持 A 股,港 / 美股估值历史分位与盈利预测当前无可用口径;PE/PB 等核心估值指标 EDE 也只有 A 股(`finc_pe_ttm`/`finc_pb_mrq` 均 `[A股]`),别假定港 / 美股估值能从 EDE 取,一律以 `scopeList` 为准。`search` 免费,EDE 取数按单元格计费;除多证券批量的效率收益外,仍优先免费 / 低价的 `quote` 或 `fundamental`。
19
+ EDE 不是“搜到就优先”。取数前必须核对:① `indicatorName` + `description` 与目标语义一致;② `scopeList` 覆盖**全部**目标市场和证券类型;③ `parameterList` 的必填参数与枚举可满足。`scopeList` 缺失 / `null` / 空或任一项不符,都视为无法证明覆盖并回退上表的专用接口;专用接口也不支持目标市场时,如实说明当前 CLI 无可用口径,不能用其他语义代替。实测 `valuation-analysis` / `earning-forecast` 仅支持 A 股,港 / 美股的**估值历史分位**与**盈利预测**当前无可用口径。但**估值指标本身别照抄旧结论**:`finc_pe_ttm`(PE TTM) 2026-08-03 起港股已有数(腾讯 16.15 / 泡泡玛特 14.93),`finc_pb_mrq`(PB MRQ) 仍只有 A 股。⚠️ **本文里所有「仅 A 股」「无数据」这类否定结论都只是某个时点的抽查**——服务端在持续补数据,正面结论过期会给错数,负面结论过期则会让你白白拒掉一个现在能跑的查询(不报错、不告警,只是少调一次)。**一律以当次 `scopeList` + 抽查为准,本段结论截至 2026-08-03。**`search` 免费,EDE 取数按单元格计费;除多证券批量的效率收益外,仍优先免费 / 低价的 `quote` 或 `fundamental`。
20
20
 
21
21
  ## 指标搜索 `indicator search`
22
22
 
@@ -28,9 +28,9 @@ gangtise indicator search --keyword <text> [--limit <n>]
28
28
  - `--limit`:返回条数上限,默认 50,最大 100
29
29
  - 默认 `--format table` 只适合浏览名称;正式路由 / 取数前必须加 `--format json`,才能完成语义、`scopeList`、`parameterList` 三项校验
30
30
  - 返回字段:`indicatorCode` / `indicatorName` / `description`(算法与口径)/ `scopeList`(该指标适用的市场 + 证券类型 + `usageRestriction`)/ `parameterList`(可传的 `--indicator-param` 参数名及枚举)/ `score`
31
- - **市场范围按指标判断**:`scopeList` 会返回实际覆盖范围,且指标之间不同;不能笼统写成每个指标都覆盖 A / 港 / 美股。实测 `finc_pe_ttm` / `finc_pb_mrq` 仅 A 股,`is_op_rev_ttm` / `is_shnp_ttm` 覆盖 A 股 + 港股(2026-08-01 新增港股,实测有数)。目标列表含任一 scope 外证券时,本批 EDE 校验不通过,应回退专用接口
32
- - **`scopeList[].usageRestriction`**:该指标在具体接口上的限制,`null` = 无限制。如「不支持指标时间序列接口」意味着只能用 `cross-section` / `screener`
33
- - ⚠️ **`scopeList` 是声明不是保证**:`qte_mkt_cptl`/`shr_tot` 声称覆盖港股+美股,实测港股与美股均**无数据**(2026-08-02 复测)。而且无数据是**整列消失**不是返 `null`,批量前抽查一行——CLI 会在 stderr 提示哪些指标/证券被整个略过
31
+ - **市场范围按指标判断**:`scopeList` 会返回实际覆盖范围,且指标之间不同;不能笼统写成每个指标都覆盖 A / 港 / 美股。覆盖面在持续扩,别把抽查结论当常量:截至 **2026-08-03** 实测 `qte_mkt_cptl`/`shr_tot` 已覆盖 A/港/美股,`finc_pe_ttm` 覆盖 A/港股,`finc_pb_mrq` 仍只有 A 股,`is_op_rev_ttm`/`is_shnp_ttm` 覆盖 A/港股。目标列表含任一 scope 外证券时,本批 EDE 校验不通过,应回退专用接口
32
+ - **`scopeList[].usageRestriction`**:该指标在具体接口上的限制,`null` = 无限制。⚠️ **它是提示不是硬约束**——标着「不支持指标时间序列接口」的 `qte_vol_intvl` 实测调时序照样返数据、服务端不拦(2026-08-02)。当成「口径可能不对、结果别当真」看,别指望它会报错
33
+ - ⚠️ **`scopeList` 是声明不是保证**:它可能**超前于数据**——`finc_pb_mrq` 声称覆盖 A股+港股,实测港股无数据(2026-08-03)。反过来也发生过:`qte_mkt_cptl`/`shr_tot` 在 08-02 时声称覆盖港/美股却无数据,08-03 数据补上了。缺数据的**表现形式由证券、指标两个维度共同决定**(详见下方「缺数据的四种形态」):只有当这只证券在同批还有别的指标有数、**且**这个指标对同批还有别的证券有数时,才是 `null` 单元格;否则是整列 / 整行消失(退出码 3)或整表为空。所以「有 `null` 就说明覆盖了」是错的,批量前抽查一行
34
34
  - 美股代码用交易所后缀 `.O`(NASDAQ) / `.N`(NYSE),**不是 `.US`**——实测 `AAPL.US` 查不到数据,须用 `AAPL.O`(官方示例里的 `AAPL.US` 是笔误)
35
35
 
36
36
  ```bash
@@ -47,7 +47,8 @@ gangtise indicator cross-section --indicator <code> [--indicator <code2>] \
47
47
 
48
48
  - `--indicator`(**至少 1 个**):指标编码,来自 `search`,可重复传多个
49
49
  - `--security`(**至少 1 个**):证券代码,如 `600519.SH`(A股)/ `09992.HK`(港股)/ `AAPL.O`(美股,用 `.O`/`.N` 后缀,非 `.US`),可重复传多个。**也接受板块 ID**(`reference sector-search` 返回的 10 位 `sectorId`,如 `1000000287` 中信白酒 → 19 只成分股),代码与板块可混传,服务端取并集去重。⚠️ 中信行业码那类 9 位 ID(`100800109`)**不是** `sectorId`,传进去返 0 只
50
- - `--date`(**必选**):数据日期 `yyyy-MM-dd`。**CLI 把它下发为每个指标各自的 `tradeDate`**(2026-08-01 起服务端取消了根级 date)。日期语义按指标分三类——财务报表指标=报告期末(可为非交易日,实测 `2024-03-31` 可取数)、`finc_pe_ttm` 等日频估值=交易日、`finc_pb_mrq`(MRQ) 等=最近报告期末(交易日取 `null`,详见下方「日期路由」)
50
+ - `--date`(**必选**):数据日期 `yyyy-MM-dd`。**CLI 把它下发为每个指标各自的 `tradeDate`**(2026-08-01 起服务端取消了根级 date)。日期语义按指标分两类——财务报表指标=报告期末(可为非交易日,实测 `2024-03-31` 可取数)、`finc_pe_ttm` / `finc_pb_mrq` 等日频估值=交易日(详见下方「日期路由」)
51
+ - `--date` 必填是 CLI 的**护栏**,不是协议要求:`cross-section` 本身接受 `indicatorParamList: []`(无参指标如 `pty_op_scope` 照常返值,实测 2026-08-02)。但绝大多数指标吃 `tradeDate`,漏传就是一张空表且退出码 0,所以宁可多带一个无害参数。(`screener` 的 `--date` 也必填,同理;那边曾另有一个「空 `parameters` 被丢弃」的服务端缺陷,2026-08-03 已修复,见下方缺陷表)
51
52
  - ⚠️ **吃 `reportDate` 的指标必须显式传**:`--indicator-param "code:reportDate=2024-12-31"`。这类指标收到 `tradeDate` 会**静默返回空结果**(不报错,实测 `is_op_rev_mom`)。CLI 检测到你已为某指标传了 `tradeDate` 或 `reportDate` 就不再注入 `--date`
52
53
  - `sDate`(区间起始日)**不算**替代日期:它和 `tradeDate` 共存(`tradeDate` 是区间终点且 required),传了 `sDate` 后 `--date` 照常下发
53
54
  - `--currency`:币种 `DFT`(原始,默认)/`CNY`/`HKD`/`USD`/`EUR`/`GBP`/`JPY`/`TWD`/`MOP`/`AUD`(**大写**,2026-08-01 起服务端枚举已统一大写)
@@ -79,7 +80,7 @@ gangtise indicator time-series --indicator <code> [--indicator <code2>] \
79
80
  - `--start-date` / `--end-date`(**均必选**):区间端点 `yyyy-MM-dd`。时序的时间范围由这两个参数统管,**不要**再用 `--indicator-param` 传 `tradeDate` 这类单日期参数
80
81
  - `--calendar-type`:日期类型 `ND`(自然日)/`TD`(交易日,默认)/`WD`(工作日)。`TD` 且跨市场时,`date` 列是各市场交易日的**并集**
81
82
  - `--currency` / `--scale`:同 `cross-section`(含根级 `--scale` 的污染坑)
82
- - **输出(宽表)**:每行一个日期,列为 `date / <各序列名>…`;序列在「单证券」时是各**指标**,在「多证券」时是各**证券**
83
+ - **输出(宽表)**:每行一个日期,列为 `date / <各序列名>…`;序列在「单指标」时是各**证券**,在「单证券多指标」时是各**指标**。**板块 ID 算多证券**——传 1 个 `sectorId` 服务端会展开成 N 只成分股,列就是这 N 只(实测中信白酒 → 19 列)
83
84
  - **`--key-by name|code`**(默认 `name`):同 `cross-section`;`code` 模式下单证券列=各 `indicatorCode`、多证券列=各 `securityCode`,批量按 code 回填用它
84
85
  - ⚠️ 部分指标标注**不支持时序接口**:`search` 返回的 `scopeList[].usageRestriction` 会写明(如「不支持指标时间序列接口」),`null` 表示无限制。**但它不是硬约束**——实测 `qte_vol_intvl` 带着该标注调时序照样返回数据,服务端不拦。把它当"口径可能不对、结果别当真"的提示,而不是"会报错"的保证
85
86
 
@@ -107,18 +108,18 @@ gangtise indicator screener --indicator <F1:code> [--indicator <F2:code2>] \
107
108
  - 比较:`==` `>` `<` `>=` `<=` `!=`
108
109
  - 文本:`contains` / `notcontains`(不区分大小写,**仅对 `dataType: string` 的指标有效**)
109
110
  - 逻辑:`&&` `||`,分组 `(` `)`
110
- - `--date`(**必选**):下发为**每个**指标的 `tradeDate`(已带 `tradeDate`/`reportDate` 的不覆盖)。之所以必填且无条件下发:**screener 会丢弃任何 `parameters` 为空数组的指标**——`pty_op_scope` 这种无参指标按官方格式传 `[]` 时永远 0 命中,随便挂个(对它无意义的)`tradeDate` 就正常返回。CLI 已自动处理,你只要记得传 `--date`
111
+ - `--date`(**必选**):下发为**每个**指标的 `tradeDate`(已带 `tradeDate`/`reportDate` 的不覆盖)。绝大多数指标吃 `tradeDate`,漏传就是一张空表且退出码 0,所以必填。对无参指标(如 `pty_op_scope`)多挂一个 `tradeDate` 无害,因此不做例外
111
112
  - `--indicator-param`:格式是 **`F1:key=value`(按变量,不是按 code)**。引用了没绑定的变量会直接报错,不会静默丢弃
112
113
  - `--expression` 里引用未绑定的变量,CLI **本地就拦**(不发请求、不计费);服务端也会报 `100003`
113
114
  - **输出(宽表)**:同 `cross-section`,每行一只**命中**的证券,列为 `security / name / <各指标名>…`;无命中返回空表
114
115
  - **积分**:与 `cross-section` 同价(按单元格计),但计费基数是**筛选前**的范围 × 指标数,别拿全市场板块随手试
115
116
 
116
- ### 已知服务端缺陷(2026-08-02 实测,已报后台)
117
+ ### 已知服务端缺陷(2026-08-03 复测,已报后台)
117
118
 
118
119
  | 现象 | 影响 | 现在怎么办 |
119
120
  | :--- | :--- | :--- |
120
- | **同一 `indicatorCode` 绑到两个变量** → 返回空结果 | 「同一指标比两个日期」这类用法暂时不可用 | CLI 会在 stderr 警告。拆成两次 `cross-section` 再本地比 |
121
- | **`contains` / `notcontains` 需要指标带参数才生效** | 官方文档的招牌示例 `F3 contains '酒'`(`parameters: []`)0 命中 | CLI 已通过必填 `--date` 自动绕过,正常可用 |
121
+ | **同一 `indicatorCode` 绑到多个变量** → 整份结果不可信 | 服务端把这些绑定**全部按其中最早的那个日期**取数,该值落到它们的第一列、其余列 `null`(实测 `F1@07-31 + F2@07-30` → F1 列返回 07-30 的 1361.76,F1 自己的 1350.6 根本没出现)。所以**活下来的数字未必属于它标注的变量**;命中的证券集合同样不可信(针对 null 变量的条件等于没筛);同一请求还有约 1/3 概率返回空集 | CLI 标 `unreliable: true` + `duplicatedIndicators` + **退出码 3**,并在 stderr 警告。**这类结果不能直接用于结论**,拆成两次 `cross-section` 再本地比 |
122
+ | ~~`contains` / `notcontains` 需要指标带参数才生效~~ | 官方文档的招牌示例 `F3 contains '酒'`(`parameters: []`)曾 0 命中 | **✅ 2026-08-03 服务端已修复**,`parameters: []` 现可直接用。CLI 仍无条件下发 `--date`(对无参指标无害、能扛回滚),此行仅作记录 |
122
123
 
123
124
  ```bash
124
125
  # 文本筛选:白酒板块里经营范围含「酒」的公司
@@ -158,16 +159,34 @@ gangtise indicator cross-section --indicator qte_close --security 600519.SH \
158
159
 
159
160
  ## 必填参数与错误码(取数前必读)
160
161
 
161
- **缺数据的三种形态(2026-08-02 实测,务必分清)**:
162
+ **缺数据的四种形态(务必分清)**:
162
163
 
163
164
  | 缺的范围 | 服务端怎么返 | 后果 |
164
165
  | :--- | :--- | :--- |
165
166
  | **部分**缺(某证券的某指标) | 该单元格 `null`,行列都在 | 安全,一眼可见 |
166
- | 某指标对 universe 内**所有**证券都无数据 | 该指标**整列**从 `indicatorList` 消失 | 🔴 `--key-by code` 回填时 key 根本不存在 |
167
- | 某证券对**所有**指标都无数据 | 该证券**整行**从 `securityCodeList` 消失 | 🔴 跨市场批量静默少行,退出码仍 0 |
168
- | 整个查询无数据 | `securityCodeList`/`values` 皆 `[]`(`Total: 0`),不再报 `999999` | 🔴 **参数写错也长这样** |
167
+ | 某指标对 universe 内**所有**证券都无数据 | 该指标**整列**从 `indicatorList` 消失 | CLI 标 `partial` + `omittedIndicators` + **退出码 3**;`--key-by code` 回填时该 key 根本不存在。**`screener` 按表达式布尔结构判**:缺列的变量视为无法求值,整个表达式再无可成立分支时 → **退出码 1 且不输出**;仍有分支可求值(如 `F1 || F2` 只缺 F1)→ `partial` + 退出码 3(见 screener 小节) |
168
+ | 某证券对**所有**指标都无数据 | 该证券**整行**从 `securityCodeList` 消失 | CLI 标 `partial` + `omittedSecurities` + **退出码 3** |
169
+ | 整个查询无数据 | `securityCodeList`/`values` 皆 `[]`(`Total: 0`),不再报 `999999` | **退出码 0**、不标 partial(什么都没被丢)。但 🔴 **参数写错也长这样**,stderr 会提醒这一歧义 |
169
170
 
170
- 实测:3 个指标查港股 `09992.HK` 只回 1 个指标(市值/股本整列消失);`qte_mkt_cptl` 查 `600519.SH`+`09992.HK` 只回 1 行。**CLI 会在 stderr 打印被整个略过的指标 / 证券**(`--format json` 下 stdout 仍是干净 JSON),看到警告就去核对 `scopeList` 和日期语义。
171
+ ⚠️ 由 ②③ 与 ④ 的分界推出一个不直觉但自洽的结果:**同一个 scope 落空,单查是 0、混查是 3**——`finc_pb_mrq` 只查 `09992.HK` 时整体全空(退出 0),和 `600519.SH` 一起查时泡泡玛特整行被丢(退出 3 + `omittedSecurities`)。全空时没有任何证据能区分「无覆盖」和「无数据」,只有存在对照物时才有。**想确认某标的是否被某指标覆盖,就把它和一个已知有数的标的一起查。**
172
+
173
+ 同一个覆盖缺口(`finc_pb_mrq` 无港股数据),会因**同批里还查了什么**而落进不同的档。2026-08-03 实测四种:
174
+
175
+ | 查法 | 服务端返回 | CLI |
176
+ | :--- | :--- | :--- |
177
+ | `--indicator finc_pb_mrq --security 09992.HK` | 四个数组全空 | **退出 0**,不标 partial(第 ④ 档:什么都没被丢,就是没数据) |
178
+ | 上面 + `--security 600519.SH` | 只回茅台 1 行,泡泡玛特整行消失 | **退出 3** + `partial` + `omittedSecurities: ["09992.HK"]`(第 ③ 档) |
179
+ | `finc_pb_mrq` + `qte_close`,只查 `09992.HK` | 回 1 行,`indicatorList` 里没有 `finc_pb_mrq` | **退出 3** + `partial` + `omittedIndicators: ["finc_pb_mrq"]`(第 ② 档:`qte_close` 保住了这只证券,但 PB 对同批**每一只**证券都无数) |
180
+ | `finc_pb_mrq` + `qte_close` × `600519.SH` + `09992.HK` | 回 2 行,泡泡玛特的 `市净率(MRQ)` 为 `null` | **退出 0**(第 ① 档:行由 `qte_close` 保住、列由茅台保住,缺口降级成单元格) |
181
+
182
+ **判据是两个维度各自独立的,别只看一维**:
183
+
184
+ - 单元格 `null` ⟺ 该**证券**在同批还有别的指标有数 **且** 该**指标**对同批还有别的证券有数
185
+ - 整列消失 ⟺ 该指标对同批**所有**证券都无数
186
+ - 整行消失 ⟺ 该证券对同批**所有**指标都无数
187
+ - 整表为空 ⟺ 两者同时成立,即请求矩阵里**没有任何有数单元格**(单指标单证券的缺口是最简形态,多证券 × 多指标全缺同样如此)
188
+
189
+ 所以「和一只有数的标的一起查就会变成 `null`」是错的——上表第 2 行正是反例:加了茅台,泡泡玛特那行照样整行消失,因为批次里只有 PB 这一个指标。**要把「整行消失」降级成 `null` 单元格,得加的是有覆盖的指标,不是有数据的证券。**标 `partial` 的那档会在 stderr 打印被略过的 code(`--format json` 下 stdout 仍是干净 JSON)。脚本按 `!= 0` 判失败的要注意:3 表示「有数据但不完整」,不是硬失败。
171
190
 
172
191
  取数报错主要是这几个码:
173
192
 
@@ -194,20 +213,20 @@ gangtise indicator cross-section --indicator qte_close --security 600519.SH \
194
213
  ## 取数最佳实践
195
214
 
196
215
  - **先 search 做三项校验**:看 `indicatorName` + `description` 确认语义和口径,看 `scopeList` 确认覆盖全部目标市场 / 证券类型(并看 `usageRestriction` 有无接口限制),再看 `parameterList` 补齐必填参数(required)并核对专属参数**名称**与枚举(`adjustType`/`scale`/`currency` 等);任一不符就回退专用接口。**参数名以 search 返回为准,不要照抄文档示例**——服务端调过参数名,传错名是静默失效不是报错。
197
- - **`scopeList` 声称覆盖 ≠ 真有数**:`qte_mkt_cptl`/`shr_tot` 的 `scopeList` 写着 A股+港股+美股,但实测港股(`09992.HK`/`00700.HK`)返回 `null`(2026-08-01)。同一次调用里 A 股正常、港股行情类(`qte_close`/`qte_vol`)也正常,说明是这两个指标的港股数据没到位。跨市场批量取数后**逐市场抽查一行**,别默认 scopeList 就是事实。
216
+ - **`scopeList` 声称覆盖 ≠ 真有数**:截至 2026-08-03,`finc_pb_mrq` 的 `scopeList` 写着 A股+港股,实测港股无数据。它的表现按上面「缺数据的四种形态」走,由证券与指标**两个维度**共同决定:只查它 + 港股 → 整表为空(退出 0);只加一只 A 股 → 港股仍整行消失(退出 3,批次里只有这一个指标);只加一个有港股覆盖的指标 → PB 整列消失(退出 3);两者都加 → 才降级成 `null` 单元格(退出 0)。跨市场批量取数后**逐市场抽查一行**,别默认 scopeList 就是事实——反过来也一样,`qte_mkt_cptl`/`shr_tot` 在 08-02 还是港/美无数据、08-03 就补上了,**否定结论同样会过期**。
198
217
  - **公司类型决定有没有这个科目**:财务科目分公司类型——银行有「存放同业」、券商有「客户资金存款」、保险有「预收保费」,一般企业没有。某指标对茅台返回 `null`(无此科目),换到对应类型证券(招行/中信/平安)就有数。
199
218
  - **日期路由**:
200
219
  - 财务报表类(`bs_`/`is_`/`cf_`/`div_`/`shr_`,以及 description 明确按报告期统计的 `finc_`)→ 用**报告期末**(Q1 `2026-03-31`、年报 `2025-12-31`,无需是交易日)
201
- - 日频估值类(如 `finc_pe_ttm`)→ 用最新已入库的交易日;但 `finc_pb_mrq`(市净率 MRQ) 等 MRQ 口径**只在报告期末打值**,交易日会取到 `null`,要用季度末日期(实测 `2026-07-22` PB 空、`2026-03-31` 有)。别因 code 都以 `finc_` 开头就一律套报告期末、也别一律套交易日——按 `description`/实测区分
220
+ - 日频估值类(如 `finc_pe_ttm` / `finc_pb_mrq`)→ 用最新已入库的**交易日**。⚠️ **MRQ 口径已改**:`finc_pb_mrq` 过去只在报告期末打值、交易日取 `null`,2026-08-02 复测**任意交易日都有数且逐日变动**(茅台 `07-31`=6.2325、`07-22`=6.0221、`06-30`=5.4706、`03-31`=7.0634;五粮液/宁德时代同样)。**别再照旧文档改用季度末日期**——那会拿到几个月前的陈值(茅台季末 7.0634 比当日 6.2325 高 13.5%,估值指标上就是错数)。别因 code 都以 `finc_` 开头就一律套报告期末,按 `description`/实测区分
202
221
  - 现金流量表附注/间接法科目(多数 `cf_`)→ **只在年报/半年报披露**,季报日期取不到,改用年报日期 `2025-12-31`
203
222
  - 行情类(`qte_` 等)→ 用**交易日**,但常规行情仍应改走 `quote`
204
- - **混合日期语义要拆查询**:同时要“某报告期营收 / EPS”和“估值 PE / PB”时,按各自有效日期分别调用 `cross-section` 再按 `security` 合并(财务=报告期末、PE=最新交易日、PB(MRQ)=最近报告期末);不要把不同日期语义的指标塞进同一个 `--date`
223
+ - **混合日期语义要拆查询**:同时要“某报告期营收 / EPS”和“估值 PE / PB”时,按各自有效日期分别调用 `cross-section` 再按 `security` 合并(财务=报告期末、PE/PB=最新交易日);不要把不同日期语义的指标塞进同一个 `--date`
205
224
  - **探索性取数**:只有**部分**缺值才返回 `null` 且保留行列;整指标 / 整证券无数据是**整列 / 整行消失**,整个查询无数据是**空表**(不再报 `999999`)。看趋势用 `time-series` + 覆盖报告期的区间,但不能把缺值当成通过语义 / scope 校验。
206
225
  - **名称反查 code 要核对,别取首条**:存在同显示名的兄弟指标——单季 `cf_finc_exp_qtr` 与累计 `cf_finc_exp` 都叫「财务费用」,`bs_fmt`/`cf_fmt`/`is_fmt` 都叫「报表格式」。`search` 按名称模糊匹配,目标 code 高概率在 top1 但不绝对,要看 `indicatorCode` 确认。
207
226
  - **批量查询做失败拆分**:某指标**缺必填参数**或入参错误时会整批报 `140002`,逐指标单查能定位是哪个指标缺参/不可查。留意 stderr 的「整列/整行被略过」警告——那不是报错,但同样是这批数据不完整的信号。
208
- - **市值量纲(复测 2026-08-01)**:`qte_mkt_cptl`(总市值)**实测仅 A 股有数**——`scopeList` 已声称覆盖港/美股,但港股实测仍返 `null`(`shr_tot` 总股本同样);**默认返原始「元」**(茅台 ≈ `1.7e12`,即 1.7 万亿),别误当天文数字。用 `scale` 数字码缩放(`0`元 / `3`千 / `4`万 / `6`百万 / `8`亿 / `9`十亿——`scale=8` → `16883` 亿元)、`currency` 换币种(**大写** `DFT`本币 / `CNY` / `HKD` / `USD` …)。**跨证券比市值前先统一 `scale`+`currency`**。
227
+ - **市值量纲(复测 2026-08-03)**:`qte_mkt_cptl`(总市值)与 `shr_tot`(总股本)**A/港/美股均已有数**(08-02 时港美股还是空的,服务端已补:泡泡玛特 2165.47 亿 / 腾讯 43207.64 亿 / 苹果 45128.55 亿);**默认返原始「元」**(茅台 ≈ `1.7e12`,即 1.7 万亿),别误当天文数字。用 `scale` 数字码缩放(`0`元 / `3`千 / `4`万 / `6`百万 / `8`亿 / `9`十亿——`scale=8` → `16883` 亿元)、`currency` 换币种(**大写** `DFT`本币 / `CNY` / `HKD` / `USD` …)。**跨证券比市值前先统一 `scale`+`currency`**。
209
228
  - **币种与汇率(复测 2026-08-01,已修复)**:`DFT`(原始币种)识别正确——A股=CNY、港股行情=HKD、美股=USD;汇率换算自洽(互逆且三角一致,误差 <0.003%)。⚠️ 但**同一只港股,行情类的原始币种是 HKD、财务类可能是 CNY**(如泡泡玛特财报以人民币计),跨市场比财务数据时显式传 `--currency CNY` 别依赖 `DFT`。另:财务类指标的汇率按**报告期**折算、行情类按查询日折算,两者隐含汇率会有细微差异,属正常口径差别。
210
- - **EDE 财务指标的 `reportType`(2026-08-01 裁决完毕,悬案关闭)**:服务端 enum label 已改正,现在 **label 与实际取数一致**,直接按 label 传即可:
229
+ - **EDE 财务指标的 `reportType`(2026-08-01 裁决)**:`enumList` 的 label 已与实际取数**一致**,按 label 传即可。⚠️ 但同一份 `search` 响应里的 `paramDescription` 仍留着**相反的旧映射文字**——**以 `enumList` 和下方实测值为准,别读 `paramDescription`**:
211
230
 
212
231
  | value | 口径 | 说明 |
213
232
  |-------|---------|------|
@@ -53,7 +53,7 @@ gangtise quote realtime [--security <code>] [--field <name>]
53
53
  - 返回**最新时刻**的行情快照(最新价/开高低/涨跌/成交量额/振幅)
54
54
  - 非交易时间返回最近一个交易日的收盘快照;停牌证券返回停牌前最后一个有效快照
55
55
  - **实测全量字段(16 个,2026-07-24)**:`securityCode` `exchange` `tradeDate` `tradeTime` `open` `high` `low` `latestPrice` `preClose` `change` `pctChange` `volume` `amount` `turnoverRate` `amplitude` `volumeRatio`
56
- - **没有 `close`**——收盘价语义用 `latestPrice`(非交易时间即为收盘价),或改用 `quote day-kline` 的 `close`;**也没有市值**,总市值走 `indicator cross-section --indicator qte_mkt_cptl`(仅 A 股)
56
+ - **没有 `close`**——收盘价语义用 `latestPrice`(非交易时间即为收盘价),或改用 `quote day-kline` 的 `close`;**也没有市值**,总市值走 `indicator cross-section --indicator qte_mkt_cptl`(2026-08-03 起 A/港/美股均有数)
57
57
  - 字段速查:见 `references/fields.md` 中的"实时行情"小节
58
58
 
59
59
  ## A股资金流向 `quote fund-flow`
@@ -226,7 +226,7 @@
226
226
 
227
227
  **用户**:"把茅台、五粮液、宁德时代 2025 年营收和已实现 EPS,与最新 PE/PB 做成一张表"
228
228
 
229
- > 示例日期为**截至 2026-07-23 的实测快照**:`2026-07-22`=当时最新交易日、`2026-03-31`=当时最近有 PB 的报告期末;实跑时替换为当下的最新交易日 / 最近报告期末。
229
+ > 示例日期为**截至 2026-08-02 的实测快照**:`2026-07-31`=当时最新交易日。PE 与 PB 现在同为日频(`finc_pb_mrq` 2026-08-02 复测任意交易日都有数),实跑时替换为当下的最新交易日即可。
230
230
 
231
231
  ```
232
232
  1. 路由 → indicator:多证券批量取一组已实现财务 / 估值指标;不是逐只 fundamental,也不是 EDB。
@@ -241,23 +241,21 @@
241
241
  - scopeList:覆盖全部三只 A 股;缺失/null/空也视为不通过
242
242
  - parameterList:补 required 参数并核对枚举
243
243
  任一不符 → 回退相应专用接口。
244
- 3. 三类指标日期语义不同 → 拆三次截面,均加 `--key-by code`(列头用 indicatorCode,跨三张表按 code 稳定合并、免受同名/服务端重排干扰;省略 reportType 即取合并口径,label 与取数已一致:1=合并 2=合并(调整) 3=母公司 4=母公司(调整)):
244
+ 3. 两类指标日期语义不同 → 拆两次截面,均加 `--key-by code`(列头用 indicatorCode,跨表按 code 稳定合并、免受同名/服务端重排干扰;省略 reportType 即取合并口径,label 与取数已一致:1=合并 2=合并(调整) 3=母公司 4=母公司(调整)):
245
245
  a) 财务(营收/EPS)用报告期末 2025-12-31:
246
246
  gangtise indicator cross-section \
247
247
  --indicator is_op_rev --indicator is_eps_bas \
248
248
  --security 600519.SH --security 000858.SZ --security 300750.SZ \
249
249
  --date 2025-12-31 --key-by code --format json
250
- b) PE 日频,用最新交易日 2026-07-22(此日 PB 为 null,勿并入):
251
- gangtise indicator cross-section --indicator finc_pe_ttm \
250
+ b) 估值 PE + PB 同为日频,用同一个最新交易日即可(2026-08-02 复测 finc_pb_mrq
251
+ 在任意交易日都有数;旧文档说它只在报告期末打值,照那样改用季末日期会拿到
252
+ 几个月前的陈值):
253
+ gangtise indicator cross-section --indicator finc_pe_ttm --indicator finc_pb_mrq \
252
254
  --security 600519.SH --security 000858.SZ --security 300750.SZ \
253
- --date 2026-07-22 --key-by code --format json
254
- c) PB(MRQ) 只在报告期末打值,用最近报告期末 2026-03-31:
255
- gangtise indicator cross-section --indicator finc_pb_mrq \
256
- --security 600519.SH --security 000858.SZ --security 300750.SZ \
257
- --date 2026-03-31 --key-by code --format json
258
- 4. 按 security 合并三张宽表(列头即 indicatorCode,各取所需日期的值);不要把不同日期语义的指标塞进同一个 --date。
259
- 5. 计费:search 免费;三次取数各按请求单元格数量计费,每次不足 100 单元格按 100 计。
260
- 6. 无数据:单元格缺值返回 null 且不丢证券行;整个查询无数据返回空表(不再报 999999)——空表也可能是参数名/日期语义写错,先核对 parameterList、日期语义、scopeList 和公司类型。
255
+ --date 2026-07-31 --key-by code --format json
256
+ 4. 按 security 合并两张宽表(列头即 indicatorCode,各取所需日期的值);不要把不同日期语义的指标塞进同一个 --date。
257
+ 5. 计费:search 免费;两次取数各按请求单元格数量计费,每次不足 100 单元格按 100 计。
258
+ 6. 无数据分四档:**部分**缺 → 单元格 null 且行列都在;某指标对所有证券无数据 → 整列消失;某证券对所有指标无数据 → 整行消失(后两种 CLI 会标 partial + 退出码 3 并在 stderr 列出被略过的 code);整查询无数据 → 空表(不再报 999999)。空表也可能是参数名/日期语义写错,先核对 parameterList、日期语义、scopeList 和公司类型。
261
259
  ```
262
260
 
263
261
  ## 例 16:A 股资金流向(个股 vs 全市场按日分片)
@@ -2,7 +2,9 @@
2
2
 
3
3
  CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"` 解包,stdout 直接是 `data`。无 envelope 的响应原样透传。
4
4
 
5
- > 例外:`indicator`(EDE)三个接口成功时**双层信封**(`data` 里再裹一层 `{code, status, data}`),内层字段名为 `securityCodeList/securityNameList/indicatorCodeList/indicatorNameList/dataTypes`,`values` 是 2D 矩阵(截面 `[指标][证券]`、时序 `[序列][日期]`);无数据为 `null` 单元格。`indicator` 子命令已在客户端二次解包并拍平成宽表;但直接 `raw call indicator.*` 只会剥外层,需自行处理内层。
5
+ > 例外:`indicator`(EDE)四个接口(`search` / `cross-section` / `time-series` / `screener`)成功时**双层信封**(`data` 里再裹一层 `{code, status, data}`)。内层字段名 2026-08-01 起为 `securityCodeList` / `securityNameList` / `indicatorList[{code,name,dataType}]`(screener 另带 `field`),`values` 是 2D 矩阵:**截面与 screener 为 `[证券][指标]`**(该版转置过,此前是 `[指标][证券]`)、时序仍为 `[序列][日期]`。
6
+ >
7
+ > 缺数据分四档:**部分**缺 → 单元格 `null`;某指标对所有证券都无数据 → 该指标**整列**从 `indicatorList` 消失;某证券对所有指标都无数据 → 该证券**整行**从 `securityCodeList` 消失;整查询无数据 → 全空数组。CLI 的 `indicator` 子命令已二次解包、拍平成宽表,并在整列/整行被略过时标 `partial` + `omittedIndicators`/`omittedSecurities` + 退出码 3。**`screener` 例外**:把缺列的变量当作无法求值,按表达式的**布尔结构**判断是否还有分支能成立(`A && B` 要两边、`A || B` 只要一边)。一条都不剩 → **退出码 1 且不输出**(那些行以「通过了该条件」的名义呈现,而条件根本无法证明被执行过);仍有分支可求值、或缺的只是输出用的辅助变量 → `partial` + 退出码 3。重复绑定同一指标另标 `unreliable` + `duplicatedIndicators` + 退出码 3;直接 `raw call indicator.*` 只会剥外层,内层与缺数据形态需自行处理。
6
8
 
7
9
  ## 通用模式(5 类)
8
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gangtise-openapi-cli",
3
- "version": "0.30.1",
3
+ "version": "0.31.0",
4
4
  "description": "CLI for Gangtise OpenAPI",
5
5
  "license": "MIT",
6
6
  "repository": {