gangtise-openapi-cli 0.37.1 → 0.39.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.
@@ -2,11 +2,11 @@
2
2
 
3
3
  通用:`--field` 可重复(`--field open --field close`),可用字段见 `references/fields.md`。
4
4
 
5
- **`--field` 字段名必须核对**(v0.28.3 起传错直接报错):上游对不存在的字段名有两套处理——day-kline / minute-kline / fund-flow 把字段名和值一起丢掉(安全);但 `quote realtime`(及 `fundamental main-business` / `valuation-analysis`)**只丢值、字段名照请求回显**,按位置拍平就把值贴到了错误的字段上。实测 `quote realtime --field securityCode --field close --field turnoverRate`:realtime 根本没有 `close`,返回的 2 个值被拍成 `close = 28.5573`(那是换手率,茅台真实价 1297.41)——不报错、数字看着合理、却完全是另一个指标。CLI 现在长度不匹配就直接失败(退出码 1),不输出错位数据。**不确定字段名就别传 `--field`**(返回全量最稳)。
5
+ **`--field` 字段名必须核对**:上游对不存在的字段名有两套处理——day-kline / minute-kline / fund-flow / realtime 把字段名和值**一起丢掉**(不报错,结果里就是少一列);`fundamental main-business` / `valuation-analysis` 则**只丢值、字段名照请求回显**,按位置拍平就把值贴到了错误的字段上。CLI 对后一种长度不匹配直接失败(退出码 1),不输出错位数据;对前一种比对请求与返回的列名,**缺列就标 `partial` + `missingFields`、退出码 3 并在 stderr 点名是哪几列**(字段名写错或已下线,按 `references/fields.md` 核对)。**不确定字段名就别传 `--field`**(返回全量最稳)。另外 `--field` 只返回你点名的列,`day-kline` / `minute-kline` / `realtime` **不会自动附带身份列**:日 K 要把 `securityCode` / `tradeDate`、分钟 K 要把 `securityCode` / `tradeTime`、实时行情要把 `securityCode`(需要时点再加 `tradeDate` / `tradeTime`)一起写进 `--field`,否则行无法归属;`fund-flow` 会自动附带 `securityCode` / `tradeDate`。
6
6
 
7
7
  **关键规则**:查"最近"K线必须显式 `--start-date`/`--end-date` 拉范围,再从 `tradeDate` 取尾部最近 N 条;不要只用 `--limit N`(会截取查询窗口开头)。
8
8
 
9
- 🔴 **全市场关键字换了(2026-08-14)**:`quote day-kline` 的 `--security all` **已不再支持**,改为三个市场关键字之一——`aShares` / `hkStocks` / `usStocks`,且**必须单独传**(不能与证券代码或另一个关键字混填)。传 `all` 或混填 CLI 会直接报错并提示正确写法。三个已下线的旧命令(`day-kline-hk` / `day-kline-us` / `index-day-kline`)仍认 `all`。
9
+ 🔴 **全市场关键字**:`quote day-kline` 不认 `--security all`,只认三个市场关键字之一——`aShares` / `hkStocks` / `usStocks`,且**必须单独传**(不能与证券代码或另一个关键字混填)。传 `all` 或混填 CLI 会直接报错并提示正确写法。三个已下线的旧命令(`day-kline-hk` / `day-kline-us` / `index-day-kline`)仍认 `all`。
10
10
 
11
11
  **自动分片**:全市场关键字跨日期范围时 CLI 自动按日切片并并发执行,合并结果返回,无需手动分批。分片粒度按各市场单个交易日的行数规模定,保证单请求不撞 10000 行的 API 上限:
12
12
 
@@ -20,17 +20,17 @@
20
20
 
21
21
  分片路径会自动把 `limit` 抬到 10000(API 上限),避免默认 6000 行截断;按日分片自动跳过周六日。
22
22
 
23
- **日K线历史性**(v0.14.0 起 API 文档明确):所有日K线接口仅返回**历史数据**,不提供实时行情。盘中实时数据请改用 `quote realtime`。当日数据入库时间:A 股约 15:30、港股约 16:30、美股约 07:00(北京时间)。
23
+ **日K线历史性**:所有日K线接口仅返回**历史数据**,不提供实时行情。盘中实时数据请改用 `quote realtime`。当日数据入库时间:A 股约 15:30、港股约 16:30、美股约 07:00(北京时间)。
24
24
 
25
25
  ---
26
26
 
27
- ## 日 K 线(统一,A 股 / 港股 / 美股 / 指数) `quote day-kline`
27
+ ## 日 K 线(统一,A 股 / 港股 / 美股 / ETF / 指数) `quote day-kline`
28
28
 
29
29
  ```bash
30
30
  gangtise quote day-kline [--security <code>] [--start-date <YYYY-MM-DD>] [--end-date <YYYY-MM-DD>] [--limit <n>] [--field <name>]
31
31
  ```
32
32
 
33
- **2026-08-14 起这一个命令覆盖全部品种**,港股 / 美股 / 指数不用再换命令,也可以在一次请求里混着传:
33
+ **这一个命令覆盖全部品种**——港股 / 美股 / ETF / 各类指数不用换命令,也可以在一次请求里混着传:
34
34
 
35
35
  | 品种 | 代码格式 | 示例 |
36
36
  | :-- | :-- | :-- |
@@ -40,18 +40,38 @@ gangtise quote day-kline [--security <code>] [--start-date <YYYY-MM-DD>] [--end-
40
40
  | 交易所指数 | `.SH` `.SZ` `.BJ` | `000001.SH` 上证指数、`399006.SZ` 创业板指 |
41
41
  | 概念指数 | `.GT` | `880134.GT` 机器人 |
42
42
  | 行业指数 | `.CI` 中信 / `.SWI` 申万(一二三级) | `821031.SWI` |
43
-
44
- - **全市场**:`--security aShares` / `hkStocks` / `usStocks`,**必须单独传**(见文件开头)。⚠️ 指数**不支持**全市场关键字,必须逐个传代码
43
+ | ETF(沪深) | `.SH` `.SZ` | `512800.SH` 银行ETF、`159887.SZ` 银行ETF富国 |
44
+ | 全球指数 | 数据源后缀(`.SPI` `.N` `.O` `.NKI` `.HI` `.FRA` …),共 20 个,清单见下表 | `SPX.SPI` 标普500、`N225.NKI` 日经225、`HSI.HI` 恒生 |
45
+
46
+ **全球指数清单(20 个,`realtime` / `day-kline` / `minute-kline` 三接口通用)**——代码后缀是数据源码,不是交易所后缀,照抄即可:
47
+
48
+ | 代码 | 名称 | 代码 | 名称 |
49
+ | :-- | :-- | :-- | :-- |
50
+ | `SPX.SPI` | 标普500 | `DJI.SPI` | 道琼斯 |
51
+ | `IXIC.O` | 纳指综合 | `NYA.N` | 纽约综指 |
52
+ | `GSPTSE.SPI` | 加拿大 S&P/TSX | `MXX.SPI` | 墨西哥 IPC |
53
+ | `N225.NKI` | 日经225 | `HSI.HI` | 恒生指数 |
54
+ | `KS11.KRX` | 韩国 KOSPI | `AORD.AUS` | 澳洲综合 |
55
+ | `NZ50.SPI` | 新西兰50 | `FTSE.FI` | 英国富时100 |
56
+ | `GDAXI.FRA` | 德国 DAX | `MIB.FI` | 富时意大利 MIB |
57
+ | `IBEX.MAD` | 西班牙 IBEX35 | `AEX.AMS` | 荷兰 AEX |
58
+ | `SSMI.SWX` | 瑞士 SMI | `BFX.BRU` | 比利时 BEL20 |
59
+ | `ATX.WBO` | 奥地利 ATX | `OMXSPI.OME` | 瑞典斯德哥尔摩 |
60
+
61
+ 全球指数三接口共同的口径:**成交量额类字段为 `null`**(realtime 的 `volume` / `amount` / `amplitude`;分钟 K 的 `volume` / `amount`;日 K 只有 `amount`,`volume` 正常返回),`adjustFactor` 为 `null`;**`tradeDate` / `tradeTime` 是交易所当地时间**(如标普500 的收盘快照 `tradeTime` 是 `16:01`),不是北京时间。
62
+
63
+ - **全市场**:`--security aShares` / `hkStocks` / `usStocks`,**必须单独传**(见文件开头)。⚠️ **关键字只覆盖个股**:指数不支持全市场关键字,**`aShares` 也不含 ETF**——ETF 与各类指数都要逐个传代码
45
64
  - 混市场查询时各证券只返回其所属交易所的交易日:春节期间 A 股休市而美股正常,则当期只有美股行;美国独立日反之
46
- - `--limit` 默认 6000,上限 10000
65
+ - `--limit` 默认 6000,上限 10000。**显式多证券且「证券数 × 交易日数」超过 `--limit` 时,CLI 自动逐只请求并按传入顺序合并**(每只各自受 `--limit` 约束,撞上的标 `partial` + `truncatedSecurities`);估算不超限时仍是单请求
47
66
  - 常用字段:`open` `high` `low` `close` `pctChange` `volume` `amount` `adjustFactor`
48
- - `adjustFactor` 复权因子:后复权价 = 不复权价 × `adjustFactor`;前复权价 = 不复权价 × `adjustFactor` ÷ 最新交易日的 `adjustFactor`。**指数无复权因子,该字段为 `null`**
67
+ - `adjustFactor` 复权因子:后复权价 = 不复权价 × `adjustFactor`;前复权价 = 不复权价 × `adjustFactor` ÷ 最新交易日的 `adjustFactor`。**指数无复权因子,该字段为 `null`**;ETF 有,EDE 的 `qte_adj_factor` 同样覆盖场内基金
68
+ - ETF 的 `volume` 单位是「份」(由「万份」× 10000 换算,可能有细微误差)
49
69
 
50
70
  ## ⚠️ 已下线的三个旧命令(仍可调用)
51
71
 
52
- `quote day-kline-hk` / `quote day-kline-us` / `quote index-day-kline` 的能力已并入上面的 `day-kline`,官方于 2026-08-14 把它们从菜单下线,接口仍可调用。**新代码一律用 `day-kline`**,理由不止是少记三个命令:
72
+ `quote day-kline-hk` / `quote day-kline-us` / `quote index-day-kline` 的能力已并入上面的 `day-kline`,已从菜单下线,接口仍可调用。**新代码一律用 `day-kline`**,理由不止是少记三个命令:
53
73
 
54
- - 旧命令**不校验证券代码**——传错代码返回 `{"total":0}` 而不是报错,与「该票该区间真无数据」无法区分;`day-kline` 会报 `120001`
74
+ - 旧命令**不校验证券代码**——传错代码返回空结果(`{"total":0,"list":[]}`)而不是报错,与「该票该区间真无数据」无法区分;`day-kline` 会报 `120001`
55
75
  - 参数与字段和 `day-kline` 完全一致(`--security` / `--start-date` / `--end-date` / `--limit` / `--field`),迁移只是换命令名
56
76
  - 三者的全市场关键字仍是 `all`(不是 `aShares` 那套)
57
77
 
@@ -61,13 +81,17 @@ gangtise quote day-kline [--security <code>] [--start-date <YYYY-MM-DD>] [--end-
61
81
  gangtise quote realtime [--security <code>] [--field <name>]
62
82
  ```
63
83
 
64
- - **覆盖三大市场 + 指数**:A 股 / 港股 / 美股个股与交易所指数(`.SH`/`.SZ`/`.BJ`)、概念指数(`.GT`)、行业指数(`.CI`/`.SWI`)可混合传入(如 `--security 600519.SH --security 00700.HK --security 000001.SH --security 880134.GT`)
65
- - **全市场关键字**:`--security aShares` 全部 A 股 / `hkStocks` 全部港股 / `usStocks` 全部美股,**必须单独传**(不能与代码或另一个关键字混填,CLI 会本地拦截);建议配合 `--field` 精简返回字段。⚠️ 指数不支持全市场关键字
84
+ - **覆盖三大市场 + ETF + 指数**:A 股 / 港股 / 美股个股、沪深 ETF(`512800.SH`)、交易所指数(`.SH`/`.SZ`/`.BJ`)、概念指数(`.GT`)、行业指数(`.CI`/`.SWI`)、20 个全球指数(`SPX.SPI` / `N225.NKI` / `HSI.HI`…,清单见上方日 K 一节)可混合传入(如 `--security 600519.SH --security 00700.HK --security 512800.SH --security 880134.GT --security SPX.SPI`)
85
+ - **全市场关键字**:`--security aShares` 全部 A 股 / `hkStocks` 全部港股 / `usStocks` 全部美股,**必须单独传**(不能与代码或另一个关键字混填,CLI 会本地拦截);建议配合 `--field` 精简返回字段。⚠️ 关键字只覆盖个股:指数不支持全市场关键字,`aShares` 也不含 ETF
66
86
  - 指数返回的是点位,无货币单位;概念 / 行业指数交易时间与 A 股一致
87
+ - **`tradeDate` / `tradeTime` 的时区**:A 股 / 港股 / ETF / 沪深各类指数为北京时间;**美股与全球指数是交易所当地时间**(美股收盘快照的 `tradeTime` 是 `16:00`,不是北京时间的凌晨)
88
+ - `tradeStatus`(交易状态,中文:未开市 / 盘前集合竞价 / 连续竞价 / 收盘集合竞价 / 收盘 / 休市 / 停牌暂停交易 / 停牌)**仅 A 股 / 港股个股有值**,美股、ETF、各类指数为 `null`
89
+ - **`null` 的字段**:美股 `amount`(接口不提供,要美股成交额用 `day-kline` 或 EDE `qte_amt`);全球指数 `volume` / `amount` / `amplitude` 三个都是 `null`
67
90
  - 返回**最新时刻**的行情快照(最新价/开高低/涨跌/成交量额/振幅)
68
91
  - 非交易时间返回最近一个交易日的收盘快照;停牌证券返回停牌前最后一个有效快照
69
- - **实测全量字段(16 个,2026-07-24)**:`securityCode` `exchange` `tradeDate` `tradeTime` `open` `high` `low` `latestPrice` `preClose` `change` `pctChange` `volume` `amount` `turnoverRate` `amplitude` `volumeRatio`
70
- - **没有 `close`**——收盘价语义用 `latestPrice`(非交易时间即为收盘价),或改用 `quote day-kline` 的 `close`;**也没有市值**,总市值走 `indicator cross-section --indicator qte_mkt_cptl`(2026-08-03 起 A/港/美股均有数)
92
+ - **全量字段(15 个)**:`securityCode` `exchange` `tradeDate` `tradeTime` `tradeStatus` `open` `high` `low` `latestPrice` `preClose` `change` `pctChange` `volume` `amount` `amplitude`
93
+ - ⚠️ **`turnoverRate` / `volumeRatio` 不是 realtime 的字段**:传了会连字段名一起被静默丢掉,不报错、结果里就是没这两列。换手率走 EDE `indicator cross-section --indicator qte_turn`(A 股);量比在 EDE 里没有对应指标
94
+ - **没有 `close`**——收盘价语义用 `latestPrice`(非交易时间即为收盘价),或改用 `quote day-kline` 的 `close`;**也没有市值**,总市值走 `indicator cross-section --indicator qte_mkt_cptl`(A/港/美股均有数)
71
95
  - 字段速查:见 `references/fields.md` 中的"实时行情"小节
72
96
 
73
97
  ## A股资金流向 `quote fund-flow`
@@ -97,8 +121,8 @@ gangtise quote index-day-kline [--security <code>] [--start-date <YYYY-MM-DD>] [
97
121
  - 沪深京指数:如 `000001.SH` 上证综指、`399001.SZ` 深成指;`--security all` 全市场指数(**仍是 `all`,不是 `aShares` 那套**)
98
122
  - `--limit` 默认 6000,上限 10000
99
123
  - 常用字段:`securityCode` `securityName` `tradeDate` `open` `high` `low` `close` `preClose` `change` `pctChange` `volume` `amount`
100
- - `securityName` 为指数名称(如 `上证指数`),v0.15.0 起返回
101
- - **还值得用它的两个场景**(都是 `day-kline` 做不到的,实测 2026-08-13):
124
+ - `securityName` 为指数名称(如 `上证指数`)
125
+ - **还值得用它的两个场景**(都是 `day-kline` 做不到的):
102
126
  1. **一次拿全部沪深京指数**(`--security all`)——`day-kline` 的指数必须逐个传代码
103
127
  2. **要指数名称**——`index-day-kline` 返回 `securityName`(如「上证指数」),`day-kline` **没有这个字段**,查指数只拿得到代码
104
128
  - 反过来 `day-kline` 独有 `adjustFactor`(复权因子),但指数本来就没有复权,该字段查指数时恒为 `null`
@@ -109,8 +133,10 @@ gangtise quote index-day-kline [--security <code>] [--start-date <YYYY-MM-DD>] [
109
133
  gangtise quote minute-kline --security <code> [--start-time <datetime>] [--end-time <datetime>] [--limit <n>] [--field <name>]
110
134
  ```
111
135
 
112
- - 支持**沪深** A 股个股(`.SH` / `.SZ`,不含北交所)、交易所指数(`.SH` / `.SZ`)、概念指数(`.GT`)、行业指数(`.CI` / `.SWI`),2026-08-14 起扩展;**必须传 `--security`**(否则返回 `100003`,msg 为「securityCode不可为空」;2026-07-20 实测)
113
- - **一次只能查一只**(参数是 `securityCode` 单值,不是列表),要多只就循环调用
136
+ - 支持**沪深** A 股个股(`.SH` / `.SZ`,不含北交所)、沪深 ETF(`512800.SH`)、交易所指数(`.SH` / `.SZ`)、概念指数(`.GT`)、行业指数(`.CI` / `.SWI`)、20 个全球指数(`SPX.SPI` / `N225.NKI` / `HSI.HI`…,清单见日 K 一节);**必须传 `--security`**(否则返回 `100003`「securityCode不可为空」)
137
+ - `--security` 可重复传多只:接口一次只收一只,CLI 逐只并发请求后按传入顺序合并;任一只撞上 `--limit` 时结果标 `partial` + `truncatedSecurities`、退出码 3
114
138
  - `--start-time` / `--end-time`:`yyyy-MM-dd HH:mm:ss`(兼容 `yyyy-MM-dd` 自动补全)
115
139
  - `--limit` 默认 6000,上限 10000
116
140
  - 常用字段:`securityCode` `tradeTime` `open` `high` `low` `close` `change` `pctChange` `volume` `amount`
141
+ - **全球指数**:`volume` / `amount` 为 `null`;`tradeTime` 与 `--start-time` / `--end-time` 都按**交易所当地时间**(如日经225 一天的分钟线是 `09:01`–`15:30`,德国 DAX 是 `09:01`–`17:30`)
142
+ - **ETF**:流动性低的 ETF 在无成交的分钟 `volume` 返 `0`、价格顺延上一分钟收盘
@@ -45,7 +45,7 @@ gangtise reference institution-search --keyword <text> [--category <name>] [--to
45
45
 
46
46
  - 用途:查机构 ID,拿到的 `institutionId` 用于各接口的 `--institution`(牵头机构)/ `--broker`(券商 / 观点机构)入参。**每条结果自带 `usageScopes[{apiName, paramName}]`,服务端直接标明该 ID 用于哪个接口的哪个参数**——拿不准某 ID 该喂给谁时以此为准
47
47
  - `--keyword`(**必选**):机构名称 / 简称(如 `招商证券`、`华泰`、`摩根`)
48
- - `--category`:机构分类,缩小范围(可重复;不传查所有分类)。5 个分类与既有命令参数的对应(均实测有效):
48
+ - `--category`:机构分类,缩小范围(可重复;不传查所有分类)。5 个分类与既有命令参数的对应:
49
49
 
50
50
  | category | CLI 命令 · 参数 | 用途 |
51
51
  |----------|----------------|------|
@@ -55,7 +55,7 @@ gangtise reference institution-search --keyword <text> [--category <name>] [--to
55
55
  | `foreignOpinionInstitution` | `insight foreign-opinion list --broker` | 外资机构观点 |
56
56
  | `leadInstitution` | `--institution`(`summary` / `roadshow` / `site-visit` / `strategy` / `vault my-conference` list) | 纪要 / 路演 / 调研 / 线下策略会 / 我的会议的牵头机构 |
57
57
 
58
- 注:API 文档 `categoryList` 只列了前 4 类,但 `foreignOpinionInstitution` 同样是有效过滤值(实测确认,服务端接受且返回该类)
58
+ 注:API 文档 `categoryList` 只列了前 4 类,但 `foreignOpinionInstitution` 同样是有效过滤值(服务端接受且返回该类)
59
59
  - `--top`:默认 10,**上限 10**;结果按 `matchScore`(`0~1`)降序
60
60
  - 免费调用
61
61
  - 返回字段:`institutionId` / `institutionName` / `category` / `usageScopes[{apiName, paramName}]`(该机构适用的接口及参数)/ `matchScore`
@@ -104,12 +104,12 @@ gangtise reference constant-category [--format json]
104
104
  | `usShareAnnouncementCategory` | 美股公告分类(`103980xxx` 段) | tree(2 级) | `insight announcement-us --category` |
105
105
  | `regionCategory` | 区域分类 | flat | `insight foreign-report --region` |
106
106
 
107
- > **行业 / 研究方向过滤——选哪套 category(⭐ 权威口径,其他文件引用此处、勿重复枚举命令清单以免漂移;全部为逐端点实测,2026-08-08):**
107
+ > **行业 / 研究方向过滤——选哪套 category(⭐ 权威口径,其他文件引用此处、勿重复枚举命令清单以免漂移;逐端点核对):**
108
108
  >
109
109
  > 先记住三套码的归属,**别把行业码算到 `gangtiseIndustry` 头上**:`citicIndustry` = 30 条行业码 `1008001xx`;`swIndustry` = 31 条行业码 `104xx0000`;`gangtiseIndustry` = **只有 6 条方向码** `122000xxx`(宏观 `122000001` / 策略 `122000002` / 固收 `122000003` / 金工 `122000004` / 海外 `122000005` / 其他 `122000007`),里面**没有任何行业**,去它那里找「食品饮料」永远找不到。
110
110
  >
111
111
  > - **`--industry`(industryList)→ 用 `citicIndustry`(`1008001xx`)**:opinion / research / foreign-report / official-account 正确过滤。`swIndustry`(`104xx0000`)在这 4 个上**也生效,但不是等效**——两套码的行业成分不同,4 个里有 2 个结果集对不上(research / foreign-report 完全一致;**opinion 与 official-account 传两套码取回的条数相差约 2%–5%**)。所以**统一用中信码**,同一批查询里别把两套码混着传。方向码 `122000xxx` 在 `--industry` 上一律返 0。⚠️ 一个例外:`insight foreign-opinion` / `independent-opinion` 的 `--industry` **只认申万码 `104xx0000`**,传中信码报 `100005 枚举值非法`(详见 `insight.md`)。`vault wechat-message-list` 反过来**只认中信码**,传申万码报 `100005`(详见 `vault.md`)。
112
- > - **`--research-area`(researchAreaList)→ 用 `citicIndustry` 行业码 `1008001xx`,方向再叠 `gangtiseIndustry` 的 `122000xxx`**。⚠️ **申万码 `104xx0000` 只有 `summary` / `pamirs-summary` 认**,其余端点返 0(与传乱码表现一致,不报错)。逐端点实测(同一行业分别传三套码,✅ = 正常过滤,❌ = 返 0):
112
+ > - **`--research-area`(researchAreaList)→ 用 `citicIndustry` 行业码 `1008001xx`,方向再叠 `gangtiseIndustry` 的 `122000xxx`**。⚠️ **申万码 `104xx0000` 只有 `summary` / `pamirs-summary` 认**,其余端点返 0(与传乱码表现一致,不报错)。逐端点对照(同一行业分别传三套码,✅ = 正常过滤,❌ = 返 0):
113
113
  >
114
114
  > | 端点 | 中信 `1008001xx` | 申万 `104xx0000` | 方向 `122000xxx` |
115
115
  > | :--- | :---: | :---: | :---: |
@@ -207,7 +207,7 @@ gangtise lookup broker-org list # 券商机构全量(--broker 用;
207
207
  gangtise lookup meeting-org list # 会议/牵头机构全量(--institution 用;130 条静态表)
208
208
  ```
209
209
 
210
- 行业 / 区域 / 公告分类 / 研究方向 / 题材 ID / 申万行业代码已改用 API:`reference constant-list` / `reference concept-search` / `reference sector-constituents`(v0.16.0 起移除对应 lookup 子命令)。
210
+ 行业 / 区域 / 公告分类 / 研究方向 / 题材 ID / 申万行业代码已改用 API:`reference constant-list` / `reference concept-search` / `reference sector-constituents`(对应 lookup 子命令已移除)。
211
211
 
212
212
  ### 常见行业别名映射
213
213
 
@@ -15,10 +15,10 @@ gangtise tool file-parse-check --task-id <id> [--output <out.zip>]
15
15
 
16
16
  - `--file`(**必填**):待解析的 PDF。CLI 在上传前本地校验:文件存在、非空、后缀 `.pdf`、≤100MB——不合格直接报 `ValidationError`,不发请求也不扣分
17
17
  - `--wait`:阻塞轮询到结果就绪(预算 ≈316s,覆盖官方「单文件约 3 分钟」)。**外层工具/命令超时要设到 ≥360s**,否则外层先超时(任务仍在服务端跑,之后 `file-parse-check` 照样能取)
18
- - `--output`:结果 ZIP 落盘路径。省略时用服务端返回的文件名(实测形如 `<taskId>.md.zip`),无则 `file-parse-<taskId>.zip`
18
+ - `--output`:结果 ZIP 落盘路径。省略时用服务端返回的文件名(形如 `<taskId>.md.zip`),无则 `file-parse-<taskId>.zip`
19
19
  - 服务端限制:单文件 ≤100MB、≤500 页,同一用户最多 10 个并发任务
20
20
  - **积分**:**提交时按实际页数一次性扣费,0.8 积分/页**(50 页 = 40 积分);取结果免费。提交端点标 `no-replay`——超时/5xx 不自动重放,避免同一文件重复扣费。**重跑 `file-parse` 会重新扣费,取结果请一律用 `file-parse-check --task-id`**
21
- - 未就绪时 `file-parse-check` 输出 `{"taskId": "...", "status": "pending"}` 且退出码 0(服务端返 `140001` RESULT_GENERATING,HTTP 409,实测 2026-07-25),隔 ~1 分钟再取即可
21
+ - 未就绪时 `file-parse-check` 输出 `{"taskId": "...", "status": "pending"}` 且退出码 0(服务端返 `140001` RESULT_GENERATING,HTTP 409),隔 ~1 分钟再取即可
22
22
 
23
23
  ZIP 内容:
24
24
 
@@ -50,12 +50,12 @@ gangtise vault wechat-message-list [--keyword <text>] [--security <code>] [--wec
50
50
  - 数据权限:仅用户已绑定并激活群消息助理、且助理已入群的群消息
51
51
  - `--security`:按证券代码过滤(如 `000001.SZ`),可重复
52
52
  - `--industry`:**只认中信码**(`1008001xx`,见 `reference constant-list --category citicIndustry`)。⚠️ 申万码(`104xx0000`)与任何不认识的值都报 `100005 枚举值非法`——**换中信码即可**。返回行里不含行业标签字段,过滤在服务端完成
53
- - 🔴 **`--industry` 是收窄工具,不是全量召回**:行业标签由服务端标注,**同一条消息可能挂多个行业,也可能一个都没挂**。实测同一个关键词加上「本行业」过滤后,命中数掉到三到四成——**少掉的既有没打标签的,也有被标到相邻行业去的**(如半导体相关的消息在计算机 / 机械 / 通信下同样查得到)。所以「按行业筛出 N 条」不能读成「该行业只有 N 条」;要尽量全,用 `--keyword` 取回后本地判断,或把相邻行业码一起查再去重
53
+ - 🔴 **`--industry` 是收窄工具,不是全量召回**:行业标签由服务端标注,**同一条消息可能挂多个行业,也可能一个都没挂**。同一个关键词加上「本行业」过滤后,命中数只剩三到四成——**少掉的既有没打标签的,也有被标到相邻行业去的**(如半导体相关的消息在计算机 / 机械 / 通信下同样查得到)。所以「按行业筛出 N 条」不能读成「该行业只有 N 条」;要尽量全,用 `--keyword` 取回后本地判断,或把相邻行业码一起查再去重
54
54
  - `--wechat-group-id`:先用 `vault wechat-chatroom-list` 查;可重复
55
55
  - `--category`:`text` | `image` | `documents` | `url`(可重复)
56
56
  - `--tag`:`roadShow` | `research` | `strategyMeeting` | `meetingSummary` | `industryComment` | `companyComment` | `earningsReview`(可重复)
57
- - 返回字段(实测 2026-07-25):`msgId` / **`content`**(正文)/ **`url`**(链接)/ `msgTime` / `wechatGroupId` / `wechatGroupName` / `speakerName` / `category` / `tagList[]{tagCode, tagName}` / `securityList[]{securityCode, securityName}` / `quoteMsg{quoteMsgId, quoteContent, quoteUrl}`。正文取 `content`、链接取 `url`(不是 `msgContent` / `contentUrl`)
58
- - `quoteMsg`(2026-07-24 新增):被引用的消息,无引用时为 `null`;`quoteContent` / `quoteUrl` 也可能为空。做上下文还原时用它把「回复」接回原消息
57
+ - 返回字段:`msgId` / **`content`**(正文)/ **`url`**(链接)/ `msgTime` / `wechatGroupId` / `wechatGroupName` / `speakerName` / `category` / `tagList[]{tagCode, tagName}` / `securityList[]{securityCode, securityName}` / `quoteMsg{quoteMsgId, quoteContent, quoteUrl}`。正文取 `content`、链接取 `url`(不是 `msgContent` / `contentUrl`)
58
+ - `quoteMsg`:被引用的消息,无引用时为 `null`;`quoteContent` / `quoteUrl` 也可能为空。做上下文还原时用它把「回复」接回原消息
59
59
  - 未打标签/未关联证券的消息,`tagList` / `securityList` 返回 `null`(不是空数组)
60
60
 
61
61
  ## 群 ID 查询 `vault wechat-chatroom-list`
@@ -0,0 +1,135 @@
1
+ # 错误码、退出码与常见困境自救
2
+
3
+ > 主文件 `SKILL.md` 只保留最高频的几个码;这里是全表。
4
+ > **退出码语义**:`0` 完整成功(含合法空结果)/ `3` 有数据但不完整(`partial: true`)/ `1` 硬失败。
5
+ > 报错行末尾的 `[trace <id>]` 是 Gangtise 支持定位问题的唯一凭据,**报障时带上它**。
6
+
7
+ ## 错误码怎么读
8
+
9
+ 服务端错误码分三层:`999xxx` 服务统一层 / `1xxxxx` 业务通用层 / `2xxxxx` 接口专有层,信封带 `errorType` 和 `traceId`。**新旧两代码并存**,按「错误处理层」而不是按业务模块划分:参数校验层与路由层发新码(信封 `code` 是 JSON 数字、带 `errorType`),token 过滤器、方法路由层与异步生成状态仍发旧码(字符串、无 `errorType`)。这判断的是单条错误路径,不是整个接口——同一个 Insight 接口内,参数校验发 `100003`、路由不存在发 `999010`、方法用错仍发 `900002`。成功响应也没有 `errorType`,别拿它当判据。CLI 对两代都认。不属于任何已识别路由的未知路径不返回统一信封,是纯文本 `default backend - 404`。
10
+
11
+ ## 常用码(按遇到概率排)
12
+
13
+ | 错误码 | 含义 | CLI 行为 | Agent 是否介入 |
14
+ |--------|------|---------|--------------|
15
+ | `100003` | 参数值非法——**最宽的兜底码**:类型错、`limit` 越界都归这里。**msg 通常已指明字段**(如「请求体字段类型不匹配: size 期望类型 Integer」「limit 最小为 1,最大为 10000」),先读 msg 再猜 | — | 按 msg 指的字段改;msg 没指明才对照 `--help` 查枚举拼写,**不要重试同命令** |
16
+ | `999999` | 系统错误。`indicator`(EDE)的「无数据」不用此码(无数据是保留行列的占位单元格 `null`,见 `commands/indicator.md`;空表另有含义:整轴 code 未识别或参数名写错),所以这个码基本只剩真故障 | 普通端点自动重试 ×2;🔴 贵档与 `indicator` 端点不重试 | 确认参数无误仍报此码即服务端故障 |
17
+ | `410110` | **异步生成中**(HTTP 400,旧码)。新码 `140001`,CLI 两码都认 | 轮询视为 pending | 继续等 |
18
+ | `410111` | **异步生成失败**(HTTP 400,旧码)。新码 `140002`,CLI 两码都认 | 终态 | **不重试**,换参数 |
19
+ | `130002` | 资源不存在——下载类的常见码:`reportId` 不存在 / 非数字多归此码。另有更具体的 `130003`(资源未生成 / 无附件)与 `130005`(`fileType` 非法) | — | 确认 ID 有效且本账号可见;换 `--file-type` 或换一篇验证 |
20
+ | `130001` | 数据未找到,或**该指标无权限**(`indicator` 内层失败会带具体 msg 如"指标无权限") | — | 检查查询条件与指标权限 |
21
+ | `100001` | 缺必填参数——**msg 带字段名**(「缺少必填参数: reportId」) | — | 按 msg 指的字段补上 |
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
+ | `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
+ | `110003` | **超出账号数据权限的时间范围**。范围按账号等级而定、**不是平台常量**;窗口按**账号**配、不按接口配 | — | 把日期移进权限范围内;整个区间都早于下界时缩短窗口无用(`--fiscal-year 2015` 无论怎么缩都报错);**换接口绕不过去**,要更长历史联系客户经理开通 |
25
+ | `100006` | 查询/下载数量超限(旧码 `430007`);`fund-flow` 全市场不传日期即此码 | — | 缩短日期范围或调小 `--size`/`--limit`;全市场场景应已自动分片 |
26
+ | `240001` | 财报期未披露或超出查询期(`earnings-review` 提交阶段就报,**不扣积分**) | — | 换更早的 `--period`(`2025q3` → `2025interim`) |
27
+ | `250001` | 不支持的数据源(旧码 `433007`) | — | 检查 `resourceType + sourceId` 组合 |
28
+ | `999011` | 开发账号凭证无效(旧码 `8000014`/`8000015`,已合并,不区分 AK 错还是 SK 错) | 登录即失败,**不重试** | 检查 `GANGTISE_ACCESS_KEY`/`GANGTISE_SECRET_KEY` 是否写反或未 export |
29
+ | `999010` | 接口地址不存在 | — | `raw call` 的 key 可能已下线,用 `gangtise raw list` 核对 |
30
+ | `999004` | 无资源权限。**整库未开通与单条记录不可见都走这个码**——`insight pamirs-summary list`(专家纪要库需单独购买)未开通时即报此码 | — | `list` 撞上多为整库未开通,先确认该数据库是否已购买;`download` 撞上再考虑换一条本账号可见的记录 |
31
+ | `0000001008` | Token 服务端失效(他处登录挤掉)——**旧码,token 自愈依赖它** | **强制重新登录并重试一次** | 无 AK/SK 时无法自愈,提示重新登录 |
32
+ | `0000001007` | 请求未携带 Bearer token | — | 检查 `GANGTISE_TOKEN` / AK/SK 是否已 export |
33
+ | `900002` | **请求方法不正确**(msg「请求类型有误」,HTTP 405) | — | `raw call` 时确认该 endpoint 是 GET 还是 POST |
34
+ | `140002` | 终态参数错:AI 异步生成失败,或 `indicator` 的指标必填参数缺失 / 枚举越界 / 表达式语法错 | **不重试**(终态码) | 按 msg 改参数重提;EDE 的参数名与枚举读 `indicator search --format json` 的 `parameterList` |
35
+
36
+ ## ⚠️ 几类「不报错」的坑(最难发现,逐条都关系到拿没拿到对的数)
37
+
38
+ - **日期用「年在前」写法**:`YYYY-MM-DD`(首选)、`YYYY/MM/DD`、`YYYYMMDD` 三种 CLI 都收,并**统一归一成 `YYYY-MM-DD` 再发出**;时间加 `[ HH:mm[:ss]]`(秒可省、空格或 `T` 分隔)或用 10/13 位时间戳。🔴 **「年在后」写法(`01-07-2026`、`07/01/2026`)CLI 直接报 `ValidationError`,这是有意的**——接口本身会解析它,且**一律按美式「月在前」**(`01-07-2026` = 1 月 7 日,`07-01-2026` = 7 月 1 日)。按欧洲/国际习惯写 `01-07-2026` 想表达「7 月 1 日」的,会拿到差半年的数据且**不报错**;本地拒掉才有信号,还省一次请求与计费。绕过 CLI 直连接口时务必自己统一用 `YYYY-MM-DD`
39
+ - **财报接口的日期按「报告期末」过滤**,不是公告日:`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
+ - **非法证券代码**:`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
+ - **枚举值拼错基本都会报 `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` 等仍是自由字符串,拼错不报错也不生效——这些要自己核对。**拼错的筛选条件会伪装成"结果正常",枚举拼写要自己保证**
42
+ - **`viewpoint-debate` 传敏感内容不会被提前拦截**——不返回 `240002`,而是照常受理、扣满 50 积分、生成阶段才以 `410111` 失败。**提交前自己把关措辞**
43
+ - **`ai one-pager` 的非法 `mode` 被静默忽略**,照常生成并扣 50 积分
44
+
45
+ ## 官方文档列出、但未见触发的码
46
+
47
+ 遇到再查,多数被上面的兜底码接管。
48
+
49
+ | 错误码 | 含义 | 实际行为 |
50
+ |--------|------|---------|
51
+ | `999001` / `999002` | 缺 token / token 无效 | 实际返回旧码 `0000001007` / `0000001008` |
52
+ | `999007` / `999008` / `999009` | 方法/媒体类型/请求体不支持 | 实际返回 `900002` / `999999` / `100003` |
53
+ | `999003` / `999005` / `999006` | 无接口权限 / 积分不足 / 限流 | 需特定账号状态才会出现 |
54
+ | `999012`–`999016` | 账号禁用/过期、租户失效、无长期 token、IP 不合规 | 需特定账号状态才会出现 |
55
+ | `100002` / `100004` / `100005` | 类型错 / 分页非法 / 枚举非法 | 类型错归 `100003`。**`100005`(枚举非法)与 `100006`(`size` 超 50)在各 list 端点上普遍触发**(`official-account` / `research` / `foreign-report` / 三个 opinion / `summary`)。仍按未传处理的只剩「该端点不支持的字段名」,见上方「不报错的坑」 |
56
+ | `130004` | 下载 ID 非数字 | 多归 `130002` |
57
+ | `140001` / `140002` | 结果生成中 / 处理失败 | 异步端点仍用 `410110` / `410111` |
58
+ | `210001` / `220001` / `230001` | 研报/观点/分享文件不支持下载 | 未见触发 |
59
+ | `230002` | 微信账号未绑定(私域)。⚠️ **`vault wechat-*` 就在该模块下、够得着**:要求先绑定并激活群消息助理且助理已入群 | 已绑定账号不会遇到 |
60
+ | `240002` / `240003` | 敏感词 / 模式不支持 | 敏感词走 `410111`;`one-pager` 的非法 `mode` 被静默忽略 |
61
+ | `903301` / `10011401` | 今日调用上限 / 白名单未开通 | 历史遗留,未见触发。不臆断对应新码——`10011401` 按语义更接近 `999003`(未开通接口权限)而非 `999016`(IP 限制),别据此去查 IP |
62
+
63
+ ## 非错误码
64
+
65
+ | 情形 | CLI 行为 | Agent 是否介入 |
66
+ |------|---------|--------------|
67
+ | HTTP 5xx / `ECONNRESET` / 超时 | **自动指数退避重试 ×2**(🔴 贵档端点不重放) | 仍失败提示用户 |
68
+ | `ValidationError` | 本地参数校验失败 | 检查 `--from` / `--size` / `--limit` 数值,**不要重试同命令** |
69
+
70
+ ## 退出码 3:结果少了数据
71
+
72
+ `partial: true`,保留已取到的部分;stderr 有 warning,`--format json` 才看得见标记,table/csv/jsonl 只有数据行、看不出问题。**拿到 3 就必须告知用户缺了哪段,不能当成功静默继续。**
73
+
74
+ - 触发场景:翻页 / K 线分片有页失败、服务端返回行数与 `total` 矛盾(提前短页)、`total` 撞服务端上限(`totalCapped`,见 opinion 家族)、`quote` 系带 `--field` 时请求了但服务端没回的列(`missingFields`)。附带定位字段:页失败 `failedPages`;分片失败 `failedShards`、分片撞行数上限 `truncatedShards`(均带日期区间可缩窗补拉)、只有部分分片返回的列 `droppedColumns`(合并结果的列集取自第一个有数据的分片,多出来的列放不下,需要就缩小日期区间单独拉);缺列 `missingFields`(字段名写错或已下线,按 `references/fields.md` 核对);多证券逐只请求里撞行数上限的证券 `truncatedSecurities`。EDE 的 `omittedIndicators` / `omittedSecurities` 仍在,但写错的 code 在服务端就被 `100003` 拒了(退出 1),这条路基本收不到样本
75
+ - **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 股专属指标查港美股,如 `mgn_*` 融资融券系列)。②③ 都要靠单查一行确认,不能只改日期
77
+
78
+ ## 退出码 4:数据写全了,但文件被另一次导出替换
79
+
80
+ 本次导出的数据完整写出了,`--output` 指向的文件却在收尾期间被**另一次写向同一路径的导出**替换掉——文件在,只是不是这条命令的产物。stderr 会给出两边的 `sha256` 前缀。给并发的导出各自的 `--output` 即可。
81
+
82
+ 与 `3` 分开是因为行没有缺、缺的是目的地。**两者同时发生时退出码是 `3`**——少了行是更重的那一个,替换另在 stderr 说明。
83
+
84
+ ## 其他场景
85
+
86
+ - CLI 未安装 → `npm install -g gangtise-openapi-cli`
87
+ - 空结果(list 为空数组) → 建议扩大时间范围、换关键词、去掉部分筛选
88
+ - 模糊公司名匹配多只("平安" → 中国平安 / 平安银行 / ...) → 列出让用户选
89
+ - 下载文件路径冲突 → 询问覆盖
90
+
91
+ ## Troubleshooting(常见困境自救)
92
+
93
+ 按问题→诊断顺序依次尝试,第一条解决就停。
94
+
95
+ **`securities-search` 找不到公司**
96
+ 1. 试拼音 / 首字母(如"贵州茅台"试 `gzmt`)
97
+ 2. 去掉"股份/有限公司/集团"等后缀重试
98
+ 3. 不传 `--category` 查所有分类(可能是 fund / DR)
99
+ 4. 还不行 → 请用户提供精确代码
100
+
101
+ **`list` 全空但参数看着对**
102
+ 1. 时间窗太窄 → 扩到 30 天试
103
+ 2. `--security` 后缀拼错(如 `300750` 漏了 `.SZ`)
104
+ 3. 行业 ID 用错体系:`--industry`(用 `citicIndustry` 码 `1008001xx`)/ `--research-area`(行业同样用 `citicIndustry` 码 `1008001xx`,方向才用 `gangtiseIndustry` 码 `122000xxx`——`gangtiseIndustry` 里**只有 6 条方向码、没有行业**)/ `--gts-code`(申万 `821xxx.SWI`)。申万数字码 `104xx0000` 用于 `--research-area` 时多数端点返 0,详见 `references/commands/reference-and-lookup.md`
105
+ 4. `--rating` / `--category` 等枚举值拼错(参考对应命令的 references 文件)
106
+
107
+ **`999011` 凭证无效**(旧码 `8000014`/`8000015`;不区分是 AK 错还是 SK 错,**登录直接失败、CLI 不重试**)
108
+ 1. `echo $GANGTISE_ACCESS_KEY` 验环境变量是否 export
109
+ 2. AK 和 SK 是否写反
110
+ 3. 账号是否到期 / 异常(`gangtise auth status`;对应 `999012`/`999013`)
111
+
112
+ **异步任务 `410111` 反复**(生成失败,终态)
113
+ 1. `viewpoint-debate`:先检查观点措辞——敏感内容不会被提前拦截,会扣满 50 积分再以 `410111` 失败
114
+ 2. `earnings-review`:换更早的 `--period`(如 `2025q3` → `2025interim`)
115
+ 3. `report-date` 用已发布的标准期:`xxxx-06-30` / `xxxx-12-31`
116
+ 4. 若提交阶段就返回 `240001`(财报期未披露),说明该期不可查且**未扣积分**,别再换参数试
117
+ 5. 直接告知用户该期数据暂不可用
118
+
119
+ **K 线返回的不是"最近"几条** → 只用 `--limit` 截的是窗口开头。必须改用 `--start-date`/`--end-date` 拉范围,再从结果尾部按 `tradeDate` 取最近 N 条。
120
+
121
+ **翻页很慢 / 卡住** → `--verbose` 看哪一页慢;可 `GANGTISE_PAGE_CONCURRENCY=10` 提速,或缩小时间范围。
122
+
123
+ **全市场 K 线报 `100006`**(旧码 `430007`)→ 单日数据仍超 10K 行(极端情况)→ 临时改用更窄的 `--start-date`/`--end-date`,或改为单只 `--security` 单独拉。
124
+
125
+ **`quote day-kline --security all` 被 CLI 拒**(`'all' is not a whole-market keyword`)→ 服务端不支持该写法 → 换成 `aShares` / `hkStocks` / `usStocks` 之一,单独传。
126
+
127
+ **AI agent 命令(one-pager 等)超时** → 服务端生成耗时长,CLI 默认 30s → `GANGTISE_TIMEOUT_MS=120000` 后重试。
128
+
129
+ **估值结果出现大量 `null`** → 最新交易日数据未入库 → 加 `--skip-null` 过滤掉 `value` / `percentileRank` 为 null 的行。
130
+
131
+ **下载文件名乱码 / 截断** → terminal locale 或 shell quoting 问题 → 显式 `--output ./<title>.<ext>` 避开。
132
+
133
+ **同一公司既是股票又是 DR** → `securities-search` 默认返回所有分类 → 加 `--category stock` 收敛。
134
+
135
+ **`sector-constituents` 返回 0 条** → sectorId 不对(题材 conceptId 与板块 sectorId 是两套 ID,不通用)→ 先 `reference sector-search --keyword <名>` 拿 `sectorId` 重试。
@@ -1,6 +1,6 @@
1
1
  # 典型执行示例
2
2
 
3
- 每个示例展示从用户语句到完整命令的全流程。Skill 主文件不再内嵌示例;遇到不确定的场景时来这里查同类。
3
+ 每个示例展示从用户语句到完整命令的全流程。示例集中在这里,Skill 主文件只放规则;遇到不确定的场景时来这里查同类。
4
4
 
5
5
  ---
6
6
 
@@ -74,7 +74,7 @@
74
74
  **用户**:"比亚迪 A 股和港股最近的日 K 线"
75
75
 
76
76
  ```
77
- 1. 路由 → quote day-kline(2026-08-14 起一个命令覆盖 A/港/美股,跨市场可一次查完)
77
+ 1. 路由 → quote day-kline(一个命令覆盖 A/港/美股,跨市场可一次查完)
78
78
  2. 比亚迪 A 股 002594.SZ,港股 01211.HK
79
79
  "最近" → K 线默认今日往前 45 天(保证含最近 10 个交易日)
80
80
  3. Pre-flight:认证 OK
@@ -152,6 +152,8 @@
152
152
  --format json
153
153
  5. 返回最新时刻快照;非交易时间返回最近一个交易日的收盘快照
154
154
  注意:日 K 线(day-kline)不返回盘中数据,问"现在/此刻"必须走 realtime
155
+ 沪深 ETF(512800.SH)与 20 个全球指数(SPX.SPI 标普500 / N225.NKI 日经225 / HSI.HI 恒生…)同样走 realtime,
156
+ 代码清单见 references/commands/quote.md;全球指数 volume/amount/amplitude 为 null,tradeTime 是交易所当地时间
155
157
  ```
156
158
 
157
159
  ## 例 11:美股日 K 线(历史)
@@ -159,10 +161,10 @@
159
161
  **用户**:"苹果过去一个月的日 K 线"
160
162
 
161
163
  ```
162
- 1. 路由 → quote day-kline-us(仅历史;盘中数据走 realtime)
164
+ 1. 路由 → quote day-kline(仅历史;盘中数据走 realtime。day-kline-us 已下线,不校验代码)
163
165
  2. 苹果 AAPL.O;"过去一个月" → 今日往前 30 天
164
166
  3. Pre-flight:认证 OK;当日数据约 07:00(北京时间)入库
165
- 4. gangtise quote day-kline-us --security AAPL.O \
167
+ 4. gangtise quote day-kline --security AAPL.O \
166
168
  --start-date 2026-04-22 --end-date 2026-05-22 \
167
169
  --field tradeDate --field open --field close --field volume --field pctChange --format json
168
170
  5. 按 tradeDate 排序展示
@@ -226,7 +228,7 @@
226
228
 
227
229
  **用户**:"把茅台、五粮液、宁德时代 2025 年营收和已实现 EPS,与最新 PE/PB 做成一张表"
228
230
 
229
- > 示例日期为**截至 2026-08-02 的实测快照**:`2026-07-31`=当时最新交易日。PE 与 PB 现在同为日频(`finc_pb_mrq` 2026-08-02 复测任意交易日都有数),实跑时替换为当下的最新交易日即可。
231
+ > 示例里的 `2026-07-31` 是写作时的最新交易日,实跑时替换为当下的最新交易日即可;PE 与 PB 同为日频。
230
232
 
231
233
  ```
232
234
  1. 路由 → indicator:多证券批量取一组已实现财务 / 估值指标;不是逐只 fundamental,也不是 EDB。
@@ -247,11 +249,12 @@
247
249
  --indicator is_op_rev --indicator is_eps_bas \
248
250
  --security 600519.SH --security 000858.SZ --security 300750.SZ \
249
251
  --date 2025-12-31 --key-by code --format json
250
- b) 估值 PE + PB 同为日频,用同一个最新交易日即可(2026-08-02 复测 finc_pb_mrq
251
- 在任意交易日都有数;用季末日期会拿到几个月前的陈值)。
252
+ b) 估值 PE + PB 同为日频,用同一个最新交易日即可(finc_pb_mrq 在任意交易日都有数;
253
+ 用季末日期会拿到几个月前的陈值)。
252
254
  ⚠️ 要估值指标的历史序列做分位/回测,两个接口都拉一遍交叉核:EDE 按正式财报
253
- 披露日切换财报口径,fundamental valuation-analysis 按业绩快报切,同一天取到
254
- 的值可能不同(已验证 PE TTM;PB 是 MRQ 口径,规则未单独验证)。详见 indicator.md:
255
+ 披露日切换财报口径且历史期用含重述后的最新数据回算,fundamental valuation-analysis
256
+ 按业绩快报切、保留当时披露的原始数据,同一天取到的值可能不同(PE TTM 已核对;
257
+ PB 是 MRQ 口径,切换规则未单独核对)。详见 indicator.md:
255
258
  gangtise indicator cross-section --indicator finc_pe_ttm --indicator finc_pb_mrq \
256
259
  --security 600519.SH --security 000858.SZ --security 300750.SZ \
257
260
  --date 2026-07-31 --key-by code --format json
@@ -270,7 +273,7 @@
270
273
  2. 检索(全文 + 按相关度):
271
274
  gangtise insight pamirs-summary list --keyword PCB --search-type 2 --rank-type 1 \
272
275
  --size 20 --format json
273
- - --search-type 2 = 全文(标题搜索是 1,命中少很多:PCB 标题 36 / 全文 113)
276
+ - --search-type 2 = 全文(标题搜索是 1,命中少很多)
274
277
  - --rank-type 1 在有 keyword 时按相关度挑条目;要最新就用 2。差别多大取决于关键词本身,
275
278
  --search-type 不影响 rank-type 1 挑哪些条目(这里加 2 是为了扩大命中面,不是为了排序)
276
279
  - 筛选项比 summary 少:没有 --source / --institution / --participant-role
@@ -298,7 +301,7 @@
298
301
  → 主力 = 大单 + 特大单;字段族 {small|medium|large|xlarge}{Inflow|Outflow|NetInflow|InflowRatio}
299
302
  单只无翻页:撞 --limit(默认 6000/上限 10000)会标 partial + 退出码 3 → 缩小日期区间
300
303
  3. 全市场:--security aShares
301
- ⚠️ aShares 必须显式传 --start-date/--end-date(缺日期本地报错;否则单请求被服务端 430012 拒)
304
+ ⚠️ aShares 必须显式传 --start-date/--end-date(缺日期本地报错)
302
305
  单日约 5500 行,CLI 按日自动分片并发合并、无需手动分批(宽区间落盘再采样):
303
306
  gangtise quote fund-flow --security aShares \
304
307
  --start-date 2026-07-06 --end-date 2026-07-06 --format jsonl --output aShares_flow.jsonl
@@ -1,31 +1,30 @@
1
1
  # CLI 可选字段速查
2
2
 
3
- > 按命令分组,`--field` 参数可重复传入。不传 `--field` 时返回全部字段。
3
+ > 按命令分组,`--field` 参数可重复传入。不传 `--field` 时返回全部字段。`quote` 系传了 `--field` 就只回点名的列、不自动附带身份列(`fund-flow` 除外,它自动带 `securityCode` / `tradeDate`):日 K 要一起写进 `securityCode` / `tradeDate`,分钟 K 是 `securityCode` / `tradeTime`,实时行情是 `securityCode`。
4
4
 
5
5
  ---
6
6
 
7
7
  ## Quote 行情
8
8
 
9
- > ⚠️ **`volume` 的单位是「股」**。四个端点同一口径——`day-kline` / `realtime` / `minute-kline` / `index-day-kline`,A股 / 港股 / 美股一致,历史数据同口径。
9
+ > ⚠️ **`volume` 的单位是「股」**(ETF 为「份」)。四个端点同一口径——`day-kline` / `realtime` / `minute-kline` / `index-day-kline`,A股 / 港股 / 美股一致,历史数据同口径。
10
10
  >
11
- > 🔴 **存量脚本里若对 `volume` 做过 `× 100` 还原股数,要撤掉**——现在会差 100 倍,而数字看着仍然「像个成交量」,不会报错。
11
+ > 🔴 **存量脚本里若对 `volume` 做过 `× 100` 还原股数,要撤掉**——会差 100 倍,而数字看着仍然「像个成交量」,不会报错。
12
12
  >
13
13
  > **一眼自检(仅适用于个股)**:`amount ÷ volume` 得到的均价应落在当日 `[low, high]` 区间内。
14
14
  >
15
- > ⚠️ **这个自检有两类必然失败,不要据此判定数据有问题**:
15
+ > ⚠️ **这个自检有三类必然失败,不要据此判定数据有问题**:
16
16
  >
17
17
  > 1. **指数不适用**。指数的 OHLC 是**点位**,而 `amount` / `volume` 是成分股合计,两者量纲不同——比值算出来是成分股均价(上证 / 深成 ≈ 20 元),永远落不进四千点的区间,**数据本身是对的**。
18
- > 2. 🔴 **美股的 `quote realtime`**。它的 `amount` **恒为 `0`**(见下方 realtime 字段表),自检值必然算出 0。**要美股的实时成交额,只能用别的口径**(收盘后用 `day-kline`,或 EDE `qte_amt`)。
18
+ > 2. 🔴 **美股的 `quote realtime`**。它的 `amount` 是 **`null`**(接口不提供该字段,见下方 realtime 字段表),自检算不出来。**要美股的实时成交额,只能用别的口径**(收盘后用 `day-kline`,或 EDE `qte_amt`)。
19
+ > 3. **全球指数**(`SPX.SPI` 等 20 个):realtime 与分钟 K 的 `volume` / `amount` 都是 `null`,日 K 只有 `amount` 是 `null`。
19
20
  >
20
- > 🔴 **分钟线加总对日线时,先看收盘那根**:正常情况下 **Σ分钟 `volume` = 日线 `volume`、Σ分钟 `amount` = 日线 `amount`**,两者都**精确相等**(正常交易日 241 根,逐根加总与日线一致)。
21
+ > **分钟线加总对日线**:Σ分钟 `volume` 与日线 `volume` **精确相等**(正常交易日 241 根);Σ分钟 `amount` 与日线 `amount` 只差**浮点尾差**(逐根相加的累积误差,相对量级 1e-8 以内),别按「逐位相同」判等。
21
22
  >
22
- > ⚠️ **但 `15:00` 那根(收盘集合竞价)会随机返 `volume=0, amount=0`**,此时 Σ分钟比日线少约 1.2%。**这是逐只、逐日、且同一只票重复取也未必一致的**——同一个交易日里,有的标的每次都对得上(Σ分钟 `amount` 与日线只差浮点级),有的则时有时无。**所以不能拿一只票的一次结果推断当天整批数据**,也与「是不是最新交易日」无关。
23
- >
24
- > **最省事的对账法:直接拿 `quote day-kline` 的 `amount` 比**——差额若恰好等于某一根,就是那一根在翻。(`14:58` / `14:59` 恒为 0 是**正常的**:14:57 后进入收盘集合竞价,只申报不撮合,成交在 15:00 一次性发生。)
23
+ > (`14:58` / `14:59` 恒为 0 是**正常的**:14:57 后进入收盘集合竞价,只申报不撮合,成交在 `15:00` 那一根一次性发生——**收盘那根在序列里**,241 根的末根就是它。)
25
24
 
26
- ### 日K线 `quote day-kline`(A股 / 港股 / 美股 / 各类指数;旧的 `day-kline-hk` / `day-kline-us` 已下线,字段相同)
25
+ ### 日K线 `quote day-kline`(A股 / 港股 / 美股 / ETF / 各类指数含全球指数;旧的 `day-kline-hk` / `day-kline-us` 已下线,字段相同)
27
26
 
28
- 各市场字段相同(货币单位随市场:A股=元、港股=港元、美股=美元;**指数为点位、无货币单位,且 `adjustFactor` 恒为 `null`**):
27
+ 各市场字段相同(货币单位随市场:A股=元、港股=港元、美股=美元、ETF=元且 `volume` 为「份」;**指数为点位、无货币单位,且 `adjustFactor` 恒为 `null`**——ETF 有 `adjustFactor`;**全球指数 `amount` 恒为 `null`**,`volume` 正常):
29
28
 
30
29
  | 字段 | 含义 | 字段 | 含义 |
31
30
  |------|------|------|------|
@@ -36,30 +35,28 @@
36
35
  | `pctChange` | 涨跌幅(%) | `volume` | 成交量(股) |
37
36
  | `amount` | 成交总额 | `adjustFactor` | 复权因子 |
38
37
 
39
- ### 实时行情(`quote realtime`,A股/港股/美股)
38
+ ### 实时行情(`quote realtime`,A股/港股/美股/ETF/各类指数含全球指数)
40
39
 
41
40
  | 字段 | 含义 | 字段 | 含义 |
42
41
  |------|------|------|------|
43
- | `securityCode` | 证券代码 | `exchange` | 交易所代码(SH/SZ/BJ/HK/NYSE/NASDAQ/AMEX) |
44
- | `tradeDate` | 交易日期 | `tradeTime` | 最新行情时间 HH:mm:ss |
45
- | `latestPrice` | 最新价 | `preClose` | 昨收价 |
42
+ | `securityCode` | 证券代码 | `exchange` | 交易所 / 指数类型代码(SH/SZ/BJ/HK/NYSE/NASDAQ/AMEX/GT/CI/SWI;全球指数为数据源码,如 SPI/N/O/NKI/HI/FRA) |
43
+ | `tradeDate` | 交易日期 | `tradeTime` | 最新行情时间 HH:mm:ss(**美股与全球指数为交易所当地时间**) |
44
+ | `tradeStatus` | 交易状态(中文:未开市/连续竞价/收盘/停牌…)——**仅 A 股 / 港股个股有值**,其余 `null` | `latestPrice` | 最新价 |
46
45
  | `open` | 开盘价 | `high` | 最高价 |
47
- | `low` | 最低价 | `change` | 涨跌额 |
48
- | `pctChange` | 涨跌幅(%) | `volume` | 成交量(股,当日累计) |
49
- | `amount` | 成交总额(当日累计)🔴 **美股恒 0** | `amplitude` | 振幅(%) |
50
- | `turnoverRate` | 换手率(%)🔴 **美股恒 0** | `volumeRatio` | 量比 🔴 **美股恒 0** |
46
+ | `low` | 最低价 | `preClose` | 昨收价 |
47
+ | `change` | 涨跌额 | `pctChange` | 涨跌幅(%) |
48
+ | `volume` | 成交量(股,ETF 为份,当日累计)——全球指数 `null` | `amount` | 成交总额(当日累计)——**美股与全球指数 `null`** |
49
+ | `amplitude` | 振幅(%)——全球指数 `null` | | |
51
50
 
52
- > 🔴 **美股的 `amount` / `turnoverRate` / `volumeRatio` 这三个字段恒为 `0`,A股 / 港股正常。** 全市场拉取核对过(2026-08-24):美股有成交的记录里这三个字段全部为 `0`,同一时刻的港股与 A 股则没有一行是 `0`。
53
- >
54
- > ⚠️ **`0` 不是「没有成交」**——同一行的 `volume` 是有值的(如 `DTSS.O` `volume=174` 而 `amount=0`)。**取美股实时成交额会静默拿到 `0`、退出码 0、无告警**,直接写进结论就是错数。要美股成交额:收盘后用 `quote day-kline`,或用 EDE `indicator cross-section --indicator qte_amt`。
51
+ > ⚠️ **美股的 `amount` 是 `null`**(接口不提供该字段)。要美股成交额:收盘后用 `quote day-kline`,或用 EDE `indicator cross-section --indicator qte_amt`。全球指数的 `volume` / `amount` / `amplitude` 三个都是 `null`。
55
52
 
56
- **以上 16 个就是全部**(实测 2026-07-24):**无 `close`**(用 `latestPrice`)、**无市值**(走 `indicator cross-section --indicator qte_mkt_cptl`)。realtime 传了不存在的字段名不会被忽略——上游只丢值、字段名照回显,CLI 检测到长度不匹配会直接报错(v0.28.3 起)。
53
+ **以上 15 个就是全部**:**无 `close`**(用 `latestPrice`)、**无市值**(走 `indicator cross-section --indicator qte_mkt_cptl`)、**无 `turnoverRate` / `volumeRatio`**(传了会连字段名一起被静默丢掉,不报错、结果里就是没这两列;换手率走 EDE `qte_turn`,A 股)。realtime 对不存在的字段名是名和值一起丢:CLI 比对请求与返回的列名,**缺列标 `partial` + `missingFields`、退出码 3**(字段名写错或已下线)。
57
54
 
58
55
  ### 指数日K线(沪深京 `quote index-day-kline`)
59
56
 
60
57
  | 字段 | 含义 | 字段 | 含义 |
61
58
  |------|------|------|------|
62
- | `securityCode` | 指数代码 | `securityName` | 指数名称(如 上证指数,v0.15.0 起) |
59
+ | `securityCode` | 指数代码 | `securityName` | 指数名称(如 上证指数) |
63
60
  | `tradeDate` | 交易日期 | `open` | 开盘价 |
64
61
  | `high` | 最高价 | `low` | 最低价 |
65
62
  | `close` | 收盘价 | `preClose` | 昨收价 |
@@ -30,7 +30,7 @@
30
30
 
31
31
  ## 申万行业(--industry 参数)
32
32
 
33
- 完整列表用 `reference constant-list --category swIndustry`(31 条)。⚠️ 申万码(`104xx0000`)只在**部分** insight list 上可作 `--industry` 使用,且**与中信码不等效**——两套码行业成分不同,实测 opinion 与 official-account 上取回的结果集就对不上(同一行业相差约 2%–5%),别混用;用于 `--research-area` 时**只有 `summary` / `pamirs-summary` 认,其余端点返 0**(不报错,与传乱码表现一致)。`vault wechat-message-list` 的 `--industry` **只认中信码**,传申万码报 `100005`——哪套码用于哪些命令的**权威口径见 `references/commands/reference-and-lookup.md`「行业 / 研究方向过滤——选哪套 category」**(含逐端点实测矩阵),勿在此重复枚举。拿不准就统一用上方中信码。
33
+ 完整列表用 `reference constant-list --category swIndustry`(31 条)。⚠️ 申万码(`104xx0000`)只在**部分** insight list 上可作 `--industry` 使用,且**与中信码不等效**——两套码行业成分不同,opinion 与 official-account 上取回的结果集就对不上(同一行业约相差 2%–5%),别混用;用于 `--research-area` 时**只有 `summary` / `pamirs-summary` 认,其余端点返 0**(不报错,与传乱码表现一致)。`vault wechat-message-list` 的 `--industry` **只认中信码**,传申万码报 `100005`——哪套码用于哪些命令的**权威口径见 `references/commands/reference-and-lookup.md`「行业 / 研究方向过滤——选哪套 category」**(含逐端点对照矩阵),勿在此重复枚举。拿不准就统一用上方中信码。
34
34
 
35
35
  | ID | 行业 | ID | 行业 | ID | 行业 |
36
36
  |----|------|----|------|----|------|
@@ -113,7 +113,7 @@
113
113
 
114
114
  ⚠️ **`gangtiseIndustry` 里只有下面这 6 条方向码,不含任何行业码**——`constant-list --category gangtiseIndustry` 返回的就是 6 条,去它那里找「食品饮料」找不到,行业码要查 `citicIndustry`。
115
115
 
116
- **6 个研究方向(citicIndustry 没有,已实测正确过滤):**
116
+ **6 个研究方向(citicIndustry 没有):**
117
117
 
118
118
  | ID | 方向 | ID | 方向 |
119
119
  |----|------|----|------|
@@ -121,7 +121,7 @@
121
121
  | 122000003 | 固收 | 122000004 | 金工 |
122
122
  | 122000005 | 海外 | 122000007 | 其他 |
123
123
 
124
- 行业维度的 ID 直接用上方「中信行业分类」表(`1008001xx`),这是唯一在全部 7 个端点上都生效的一套。⚠️ **申万码 `104xx0000` 用于 `--research-area` 只有 `summary` / `pamirs-summary` 认**,opinion / roadshow / site-visit / forum / my-conference 一律返 0(与传乱码表现一致,不报错)。反过来方向码 `122000xxx` 在 `pamirs-summary` 上返 0。完整实测矩阵见 `commands/reference-and-lookup.md`。
124
+ 行业维度的 ID 直接用上方「中信行业分类」表(`1008001xx`),这是唯一在全部 7 个端点上都生效的一套。⚠️ **申万码 `104xx0000` 用于 `--research-area` 只有 `summary` / `pamirs-summary` 认**,opinion / roadshow / site-visit / forum / my-conference 一律返 0(与传乱码表现一致,不报错)。反过来方向码 `122000xxx` 在 `pamirs-summary` 上返 0。完整对照矩阵见 `commands/reference-and-lookup.md`。
125
125
 
126
126
  ---
127
127