gangtise-openapi-cli 0.49.0 → 0.51.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.
- package/README.md +45 -8
- package/dist/src/commands/ai.js +16 -1
- package/dist/src/commands/indicator.js +8 -13
- package/dist/src/commands/insight.js +10 -3
- package/dist/src/commands/quote.js +19 -0
- package/dist/src/commands/reference.js +24 -1
- package/dist/src/commands/vault.js +51 -5
- package/dist/src/core/client.js +3 -2
- package/dist/src/core/endpoints.js +62 -0
- package/dist/src/core/errors.js +28 -14
- package/dist/src/core/etfComponents.js +96 -19
- package/dist/src/core/normalize.js +1 -1
- package/gangtise-openapi/SKILL.md +35 -22
- package/gangtise-openapi/references/commands/ai.md +26 -0
- package/gangtise-openapi/references/commands/fund.md +2 -2
- package/gangtise-openapi/references/commands/fundamental.md +1 -1
- package/gangtise-openapi/references/commands/indicator.md +94 -25
- package/gangtise-openapi/references/commands/insight.md +4 -1
- package/gangtise-openapi/references/commands/quote.md +20 -0
- package/gangtise-openapi/references/commands/reference-and-lookup.md +21 -1
- package/gangtise-openapi/references/commands/vault.md +79 -11
- package/gangtise-openapi/references/errors.md +2 -2
- package/gangtise-openapi/references/examples.md +1 -1
- package/gangtise-openapi/references/fields.md +1 -1
- package/gangtise-openapi/references/response-schema.md +12 -4
- package/package.json +1 -1
- package/dist/src/core/calendarType.js +0 -44
|
@@ -146,7 +146,10 @@ gangtise insight forum list [--research-area <id>] [--location <id>]
|
|
|
146
146
|
|
|
147
147
|
- **积分**:列表 **10/条**——务必带 `--size`
|
|
148
148
|
|
|
149
|
-
- 共用:`--keyword` `--start-time` `--end-time` `--from` `--size` `--location`
|
|
149
|
+
- 共用:`--keyword` `--start-time` `--end-time` `--from` `--size` `--location` `--publish-start-time` `--publish-end-time`
|
|
150
|
+
- **两组时间别混**:`--start-time` / `--end-time` 按**举办时间**(`startTime`)筛;`--publish-start-time` / `--publish-end-time` 按**收录时间**(返回字段 `publishTime`,Gangtise 首次收录该日程的时刻)筛。两组可同时传,同时生效(取交集),适合「昨天新收录、下周举办」这类增量同步。格式同 `--start-time`;`--publish-end-time` 只写日期时覆盖当天整天
|
|
151
|
+
- `publishTime` 通常早于举办时间,补录的日程可能晚于举办时间;后续改期、改地点不刷新它;部分记录只精确到日(时分秒为 `00:00:00`),没有收录时刻的为 `null`
|
|
152
|
+
- 账号能看到多久以前的日程按**举办时间**算,与 `publishTime` 无关:举办时间在窗口外的日程,即使最近才收录也查不到
|
|
150
153
|
- `--location`:城市/省份 ID(`reference constant-list --category domesticCity` 查,如 `156440000` 广东省)。传省份 ID 会命中该省
|
|
151
154
|
- 路演 `--category`:`earningsCall` | `strategyMeeting` | `companyAnalysis` | `industryAnalysis` | `fundRoadshow`
|
|
152
155
|
- 调研 `--category`:`single` 单场 | `series` 系列
|
|
@@ -112,6 +112,26 @@ gangtise quote fund-flow [--security <code>] [--start-date <YYYY-MM-DD>] [--end-
|
|
|
112
112
|
- 金额单位:元;占比单位:%(各分类流入占比之和 = 100)
|
|
113
113
|
- 无积分消耗
|
|
114
114
|
|
|
115
|
+
## 板块资金流向 `quote sector-fund-flow`
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
gangtise quote sector-fund-flow --sector <sectorId> [--sector <sectorId2>] [--start-date <YYYY-MM-DD>] [--end-date <YYYY-MM-DD>] [--limit <n>] [--field <name>]
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- 行业 / 概念 / 指数类板块的**日频**资金流向,仅历史数据,免费。每个值是该板块**当日成分股**(历史哪天就用哪天的成分名单,不是现在的)资金流向的加总,**只计沪深京上市公司**——板块里的港股、美股等不计入
|
|
122
|
+
- `--sector`(必填):板块 ID,可重复或逗号分隔;用 `gangtise reference sector-search --keyword <名称>` 查(与 `indicator` 的板块 ID 同一套)。ID 不存在报 `100003`
|
|
123
|
+
- `--start-date` / `--end-date`:`yyyy-MM-dd`;省略时 `end-date` 默认最新已入库交易日、`start-date` 默认往前 1 年。超出账号的数据窗口报 `110003`(区间跨过下界也整段报错,不截短返回)。可回溯范围不在官方权限表里,且可能短于 `quote fund-flow`——长区间先查最早的一小段确认
|
|
124
|
+
- 返回按板块、日期倒序排列,每行 `sectorId` / `tradeDate` 在最前
|
|
125
|
+
- `--limit`:默认 6000,上限 10000(超出本地报错)。**只截返回行数,不减计算量**;返回行数撞上 `--limit` 时结果标 `partial`、退出码 3、stderr 警告
|
|
126
|
+
- 🔴 **查询太重会报 `100006`、不返回部分数据**:计算量随板块数、板块成分股数、日期跨度和字段数增长,没有固定的最大天数。撞上就缩短日期区间、减少 `--sector` 或用 `--field` 少取几项,分成不重叠的区间分批查;**调小 `--limit` 无效**,原样重试也无效(这不是限流)
|
|
127
|
+
- `--field`:不传返回全部;可选(金额单位:元)
|
|
128
|
+
- 小/中/大/特大单:`sector{Small|Medium|Large|Xlarge}{Inflow|Outflow|NetInflow}`
|
|
129
|
+
- 主力(大单 + 特大单):`sectorMain{Inflow|Outflow|NetInflow}`
|
|
130
|
+
- 全单(四类合计):`sectorTotalInflow` / `sectorTotalOutflow`——同 `fund-flow` 的 `totalInflow` / `totalOutflow`;板块只含沪深成分股时两者相等,含北交所成分股时可以不等
|
|
131
|
+
- 字段名写错报 `100005` 并点名(不会静默少一列)
|
|
132
|
+
- ⚠️ 只传 `sectorId` / `tradeDate`、不带任何资金字段时返回 0 行、不报错(CLI 在 stderr 提示)——至少带一个资金字段
|
|
133
|
+
- 与 `fund-flow` 不同,**没有占比字段**,也没有全市场关键字
|
|
134
|
+
|
|
115
135
|
## 指数日 K 线 `quote index-day-kline`(⚠️ 已弃用,改用 `day-kline`)
|
|
116
136
|
|
|
117
137
|
```bash
|
|
@@ -134,6 +134,7 @@ gangtise reference constant-category [--format json]
|
|
|
134
134
|
> | `insight forum` | ✅ | **❌ 返 0** | ✅ |
|
|
135
135
|
> | `vault my-conference-list` | ✅ | **❌ 返 0** | ✅ |
|
|
136
136
|
> | `insight highlight` | ✅ | **❌ 不可用** | ✅ |
|
|
137
|
+
> | `ai expert-intel` | ✅ | **❌ 返 0** | 返 0(情报按公司归类,未见方向类) |
|
|
137
138
|
>
|
|
138
139
|
> 一句话结论:**行业维度一律传中信码**(唯一全端点通吃的一套),方向维度传 `122000xxx`(`pamirs-summary` 不支持方向)。
|
|
139
140
|
|
|
@@ -212,6 +213,25 @@ gangtise reference sector-constituents --sector-id 2000000014 --format json
|
|
|
212
213
|
|
|
213
214
|
单个行业也可以直接 `reference securities-search --keyword 申万银行 --category index` → `821047.SWI`。
|
|
214
215
|
|
|
216
|
+
## 指数成分股权重 `reference index-weight`
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
gangtise reference index-weight --index <code>... --date <yyyy-MM-dd>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
- 免费。`--index`(**必选**,可重复或逗号分隔):指数代码,如 `000300.SH` 沪深300、`000905.SH` 中证500、`000852.SH` 中证1000、`000016.SH` 上证50、`000688.SH` 科创50、`399006.SZ` 创业板指;不确定用 `reference securities-search --keyword <指数名> --category index`
|
|
223
|
+
- `--date`(**必选**):单个交易日。🔴 **只有每月最后一个交易日有数**(如 `2026-09-30`、`2026-10-30`)——其他交易日、非交易日与写错的指数代码都返回空结果、**不报错**;CLI 在 stderr 点名没取到数据的指数。要「最新」权重就取上个月最后一个交易日
|
|
224
|
+
- 超出账号可查范围报 `110003`
|
|
225
|
+
- 不分页、不限条数:一次返回所选指数当日的全部成分股,多个指数合在同一个 `list` 里,按 `indexCode` 区分
|
|
226
|
+
- 返回 `{total, list}`,`list[]`:`indexCode` / `indexName` / `tradeDate` / `securityCode` / `securityName` / `weight`(**单位 %**,最多四位小数)。同一指数的权重合计约为 100,受舍入影响不严格等于 100,校验合计时留容差
|
|
227
|
+
- 与 `reference sector-constituents` 的区别:后者是板块的纯成分名单、不带权重;要权重(基金归因、指数对标)用本接口
|
|
228
|
+
|
|
229
|
+
**示例:**
|
|
230
|
+
```bash
|
|
231
|
+
gangtise reference index-weight --index 000300.SH --date 2026-10-30 --format csv --output hs300-weight.csv
|
|
232
|
+
gangtise reference index-weight --index 000300.SH,000905.SH --date 2026-09-30 --format json
|
|
233
|
+
```
|
|
234
|
+
|
|
215
235
|
## Lookup 本地表
|
|
216
236
|
|
|
217
237
|
**按名称找机构 ID 优先用 `reference institution-search`**(服务端搜索、覆盖全部 5 类机构、带 usageScopes);本地表主要用于**全量枚举**券商/会议机构(institution-search 为搜索型:top≤10、非全量):
|
|
@@ -257,4 +277,4 @@ gangtise raw call insight.research.download --query reportId=<id> --query fileTy
|
|
|
257
277
|
- **endpoint key 不能按命令名猜**(如券商本地表是 `lookup.broker-orgs.list`),先用 `gangtise raw list` 查
|
|
258
278
|
- **JSON 端点**(绝大多数)用 `--body` 传 JSON;**`kind=download` 端点**(各 `*.download`)用 `--query key=value`(可重复)。传反会被 CLI **直接拒绝**(JSON 端点给 `--query`、或 GET 下载端点给 `--body`,都抛 ValidationError,不发请求;POST 下载端点 `tool.file-parse.result` 的参数走 `--body`)
|
|
259
279
|
- `--yes`:删除 / 改动数据的端点必须加才会执行;按条计费的列表省略 `size` 时,也要加它才会越过积分额度保护拉全量
|
|
260
|
-
- **与专用命令一致的只有**自动翻页、重试策略、翻页的完整性标记。K 线全市场分片、多证券分批请求、撞 `limit` 标 `partial`、`--field` 缺列检测、EDE
|
|
280
|
+
- **与专用命令一致的只有**自动翻页、重试策略、翻页的完整性标记。K 线全市场分片、多证券分批请求、撞 `limit` 标 `partial`、`--field` 缺列检测、EDE 解包与拍平都**只在专用命令里**——能用专用命令就别用 `raw call`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vault 命令详细参数(私域数据)
|
|
2
2
|
|
|
3
|
-
列表类命令大多有 `--keyword` `--start-time` `--end-time` `--from` `--size`;`wechat-chatroom-list` 只有 `--from` / `--size
|
|
3
|
+
列表类命令大多有 `--keyword` `--start-time` `--end-time` `--from` `--size`;`wechat-chatroom-list` 只有 `--from` / `--size`,股票池的查询命令都没有这些选项,笔记查询只有 `--from` / `--size`。`my-conference-list` 按条计费,省略 `--size` 时估算全量超过 1000 积分会报错退出 1,确认后加 `--yes` 或改传 `--size N`。
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -83,12 +83,34 @@ gangtise vault wechat-message-list [--keyword <text>] [--security <code>] [--wec
|
|
|
83
83
|
- 🔴 **`--industry` 是收窄工具,不是全量召回**:行业标签由服务端标注,**同一条消息可能挂多个行业,也可能一个都没挂**。同一个关键词加上「本行业」过滤后,命中数会明显少于只用关键词——**少掉的既有没打标签的,也有被标到相邻行业去的**(如半导体相关的消息在计算机 / 机械 / 通信下同样查得到)。所以「按行业筛出 N 条」不能读成「该行业只有 N 条」;要尽量全,用 `--keyword` 取回后本地判断,或把相邻行业码一起查再去重
|
|
84
84
|
- `--wechat-group-id`:先用 `vault wechat-chatroom-list` 查;可重复
|
|
85
85
|
- 按偏移量**最多取到第 10000 条**(`--from` + 条数不能超过 10000),且 `total` 最多也只报到 10000——正好报 10000 时实际条数可能更多,CLI 按封顶处理:标 `partial` + `totalCapped`、退出码 3。要更多请缩短时间范围分段取,每段的 `total` 低于 10000 才说明取全了
|
|
86
|
-
- `--category`:`text` | `image` | `
|
|
86
|
+
- `--category`:`text` | `image` | `document`(PDF、Excel 等文档)| `url` | `audio` | `video`(可重复)。其他取值(如 `documents`、`pdf`、`mp4` 这类文件格式名)报 `100005`,`--tag` / `--industry` 同样整批拒绝、不会忽略筛选返回全部
|
|
87
87
|
- `--tag`:`roadShow` | `research` | `strategyMeeting` | `meetingSummary` | `industryComment` | `companyComment` | `earningsReview`(可重复)
|
|
88
|
-
- 返回字段:`msgId` / **`content`**(正文)/ **`url`**(链接)/ `msgTime` / `wechatGroupId` / `wechatGroupName` / `speakerName` / `category` / `tagList[]{tagCode, tagName}` / `securityList[]{securityCode, securityName}` / `quoteMsg{quoteMsgId, quoteContent, quoteUrl}`。正文取 `content`、链接取 `url`(不是 `msgContent` / `contentUrl`)
|
|
89
|
-
- `
|
|
88
|
+
- 返回字段:`msgId` / **`content`**(正文)/ **`url`**(链接)/ `msgTime` / `wechatGroupId` / `wechatGroupName` / `speakerName` / `category` / `fileInfo{fileName, fileSize}` / `tagList[]{tagCode, tagName}` / `securityList[]{securityCode, securityName}` / `quoteMsg{quoteMsgId, quoteCategory, quoteContent, quoteUrl, quoteFileInfo}`。正文取 `content`、链接取 `url`(不是 `msgContent` / `contentUrl`)
|
|
89
|
+
- `msgId` 是长数字串,可能超过 JavaScript 安全整数范围——**始终按字符串保存和传递**,别转成数字(会被舍入,拿去下载就对不上)
|
|
90
|
+
- `content` 随 `category` 不同:`text` 为正文、`document` 为文件名、`image` 为图片识别出的文字(可能含 AI 摘要段落,也可能为空,不保证逐字准确)、`url` 为链接标题、`audio` / `video` 为附带文字(常为空,不含转写)
|
|
91
|
+
- `fileInfo`:`document` / `image` / `audio` / `video` 消息的文件名与字节数(`fileSize`,未知时为 `null`),其他类型为 `null`。要文件本身用下面的 `wechat-message-download`
|
|
92
|
+
- `quoteMsg`:被引用的消息,无引用时为 `null`;`quoteContent` / `quoteUrl` 也可能为空。做上下文还原时用它把「回复」接回原消息。被引用的是文件消息时,`quoteFileInfo` 给文件名与大小,下载用 `quoteMsgId`
|
|
90
93
|
- 未打标签/未关联证券的消息,`tagList` / `securityList` 返回 `null`(不是空数组)
|
|
91
94
|
|
|
95
|
+
## 群消息文件下载 `vault wechat-message-download`
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
gangtise vault wechat-message-download --msg-id <msgId> [--output <path>]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
- 免费。`--msg-id` 取自 `wechat-message-list` 的 `msgId`(按字符串原样传);只有 `document` / `image` / `audio` / `video` 消息有文件。引用里的文件用 `quoteMsg.quoteMsgId`(先确认 `quoteCategory` 是这四类之一)
|
|
102
|
+
- 一次一个文件。不带 `--output` 时按服务端给的文件名保存(文档、音频一般是原文件名,图片、视频多为一串随机字符),同名自动加 `-1`、`-2`;stdout 是保存路径
|
|
103
|
+
- 内容原样落盘:`.txt` / `.json` / `.html` 等文本类文件也按原字节保存,不做转码。图片是平台保存的版本,不保证原图分辨率;音频、视频只有文件本身,没有转写
|
|
104
|
+
- 报错:`130005` = 该消息是 `text` / `url`,没有文件;`130003` = 消息不存在、本账号无权访问或文件已不可用(三种情况不区分,**重试不会变**,别轮询);`100003` = `--msg-id` 不是纯数字
|
|
105
|
+
- 列表里有 `fileInfo` 不代表文件一定还能下载,以下载结果为准
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# 某个群里最近的文件消息 → 逐个下载
|
|
109
|
+
gangtise vault wechat-message-list --wechat-group-id <群ID> --category document --category image --category audio --category video --size 20 --format json
|
|
110
|
+
gangtise vault wechat-message-download --msg-id 4784255865508301077
|
|
111
|
+
gangtise vault wechat-message-download --msg-id 4784255865508301077 --output ./群文件/研报.pdf
|
|
112
|
+
```
|
|
113
|
+
|
|
92
114
|
## 群 ID 查询 `vault wechat-chatroom-list`
|
|
93
115
|
|
|
94
116
|
```bash
|
|
@@ -101,24 +123,27 @@ gangtise vault wechat-chatroom-list [--room-name <name>] [--from <n>] [--size <n
|
|
|
101
123
|
|
|
102
124
|
## 自选股股票池 `vault stock-pool-*`
|
|
103
125
|
|
|
104
|
-
|
|
126
|
+
查询两个、增删改五个,全部免费。查询可看个人股票池或所属租户的股票池,增删改只操作当前账号本人的个人股票池。
|
|
105
127
|
|
|
106
128
|
### 查询
|
|
107
129
|
|
|
108
130
|
```bash
|
|
109
|
-
gangtise vault stock-pool-list
|
|
110
|
-
gangtise vault stock-pool-stocks [--pool-id <id>]
|
|
131
|
+
gangtise vault stock-pool-list [--space-type 1|2]
|
|
132
|
+
gangtise vault stock-pool-stocks [--space-type 1|2] [--pool-id <id>]
|
|
111
133
|
```
|
|
112
134
|
|
|
113
|
-
- `
|
|
135
|
+
- `--space-type`:`1` 个人自选股股票池(不传即此项)、`2` 所属租户的股票池(终端租户页签下的池;页签名不是池名)。一次只查一种。无租户股票池查询权限时报 `999004`;有权限但没有可见的池返回空列表
|
|
136
|
+
- `stock-pool-list`:查询股票池列表,返回 `poolId` / `poolName` / `spaceType`
|
|
114
137
|
- `stock-pool-stocks`:查询股票池中的证券明细
|
|
115
|
-
- `--pool-id`:股票池 ID,可重复;不传默认 `all
|
|
116
|
-
-
|
|
138
|
+
- `--pool-id`:股票池 ID,可重复;不传默认 `all`(返回该 `--space-type` 下所有可见池中的非重复证券)
|
|
139
|
+
- 🔴 **`--pool-id` 要取自同一 `--space-type` 的 `stock-pool-list`**:另一种空间的 ID 不会被匹配——与其他有效 ID 一起传时被静默忽略,全部不匹配时报 `999004`「股票池不存在或无权访问」。租户池的明细要带 `--space-type 2`
|
|
140
|
+
- 按完整 `securityCode` 去重合并,不标注来自哪个池;要逐池归属就逐池查
|
|
141
|
+
- 单次最多返回 10000 只,超出截断且没有截断标记,返回恰好 10000 只时不能当作已取全(逐池查可降低截断)
|
|
117
142
|
- 返回字段:`securityCode` / `securityName`
|
|
118
143
|
|
|
119
144
|
### 增删改
|
|
120
145
|
|
|
121
|
-
🔴 **这五个命令会改动账号数据**(与上面的云盘管理命令同属写操作);`--pool-id`
|
|
146
|
+
🔴 **这五个命令会改动账号数据**(与上面的云盘管理命令同属写操作);`--pool-id` 一律取自不带 `--space-type` 的 `stock-pool-list`(个人股票池)。
|
|
122
147
|
|
|
123
148
|
```bash
|
|
124
149
|
gangtise vault stock-pool-create --name <名称>
|
|
@@ -146,3 +171,46 @@ gangtise vault stock-pool-delete --pool-id <id> [--pool-id <id>...] --yes
|
|
|
146
171
|
**幂等**:重复加已在池内的证券、移出本就不在池内的证券、删不存在的 `poolId`,都算成功并计入 `successList`,不会报错。唯一不幂等的是 `stock-pool-create`(见上面的重名规则)。
|
|
147
172
|
|
|
148
173
|
**返回字段**:`create` / `rename` 返回 `poolId` / `poolName`;`add-stock` / `remove-stock` / `delete` 返回 `successList[]` + `failList[]{securityCode 或 poolId, failReason}`。
|
|
174
|
+
|
|
175
|
+
## 个股投资笔记 `vault stock-note-*`
|
|
176
|
+
|
|
177
|
+
查询、新增、改写、删除四个命令,全部免费,只操作当前账号本人写的笔记(别人的笔记查不到、改不了、删不到,也不会暴露是否存在)。笔记与证券是多对多:一条笔记关联 1~50 只证券,同一只证券可以有多条笔记,每条笔记以 `stockNoteId` 区分。笔记与自选关注相互独立——取消关注、删股票池都不会删笔记。
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
gangtise vault stock-note-list [--security <code>... | --note-id <id>...] [--from <n>] [--size <n>]
|
|
181
|
+
gangtise vault stock-note-add --security <code> [--security <code>...] --content <正文>
|
|
182
|
+
gangtise vault stock-note-update --note-id <id> --content <新正文>
|
|
183
|
+
gangtise vault stock-note-delete --note-id <id> [--note-id <id>...] --yes
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 查询 `stock-note-list`
|
|
187
|
+
|
|
188
|
+
- 不传筛选 = 本人**全部**笔记(含已取消关注的证券下仍保留的笔记);`--security` 按证券筛,笔记关联的证券里**含其中任一只**即命中;`--note-id` 按笔记 ID 精确查。`--security` 与 `--note-id` 二选一,同传本地报错
|
|
189
|
+
- `--security` / `--note-id` 各最多 100 个;代码大小写、首尾空格不影响匹配,但港股要 5 位(`00700.HK`,`700.HK` 不会补零)、美股要用交易所后缀(`AAPL.O`,`AAPL.US` 不会转换)。**代码写错、不存在或类型不支持时整次报 `120001`**,不会当成「这只票没有笔记」返回空;有效代码没有笔记才是空结果
|
|
190
|
+
- 不存在或不属于本人的笔记 ID 被直接过滤,不计入 `total`、不报错
|
|
191
|
+
- 自动翻页,省略 `--size` 取全部;按 `createTime` 倒序(同秒按 ID 倒序),同时命中多只证券的笔记只出现一次。翻页期间有增删时偏移会变,不保证跨页一致
|
|
192
|
+
- 返回字段:`stockNoteId` / `securityList`(该笔记**完整**的关联证券,按代码升序,不只是你筛的那几只)/ `content`(纯文本原样,保留换行;Markdown 只是文字)/ `createTime` / `updateTime`(北京时间,精确到秒;正文没变的提交不刷新 `updateTime`)
|
|
193
|
+
- 默认输出 json(正文常含换行,表格不便阅读)
|
|
194
|
+
|
|
195
|
+
### 新增 `stock-note-add`
|
|
196
|
+
|
|
197
|
+
- `--security`:1~50 只(按规范化去重后计数),可重复或逗号分隔。可关联 A 股、港股、美股(`.O` / `.N` 等)、ETF、交易所指数、概念指数(`.GT`)、中信行业指数(`.CI`)、全球指数(如 `SPX.SPI`),可混传;**申万行业指数(`.SWI`)不支持**。任一只无效则整条不建,报 `120001` 并点名
|
|
198
|
+
- `--content`:纯文本,不能为空或全是空白,最长 10000 个字符(按 Unicode 码点计,首尾空白和换行都算);原样保存,不裁剪
|
|
199
|
+
- 返回 `stockNoteId` 与实际关联的 `securityList`(规范化代码、升序)
|
|
200
|
+
- 🔴 **关联的证券建好后不能改**:要换关联范围就新增一条、核对无误后再删旧的(两步不是原子操作,中间会短暂同时存在两条)
|
|
201
|
+
- 🔴 **超时或 5xx 不会自动重发,也不要直接重跑**:服务端没有防重机制,同样的请求再提交一次就是第二条笔记。超时后先 `stock-note-list --security <code>` 看是否已经写入
|
|
202
|
+
|
|
203
|
+
### 改写 `stock-note-update`
|
|
204
|
+
|
|
205
|
+
- `--note-id` 取自 `stock-note-list`;`--content` **整体替换**旧正文(不是追加),规则同新增
|
|
206
|
+
- 只改正文,关联证券不变;一条笔记关联多只证券时,改动在每只证券下都可见
|
|
207
|
+
- 成功返回 `{}`;`updateTime` 从查询里看。不存在或不属于本人返回 `130002`「笔记不存在或无权操作」
|
|
208
|
+
- 没有版本控制,并发改写以最后提交的为准
|
|
209
|
+
|
|
210
|
+
### 删除 `stock-note-delete`
|
|
211
|
+
|
|
212
|
+
- **必须显式加 `--yes`**(不加直接报错退出,不发请求);删除的是整条笔记连同它与全部证券的关联,**不可恢复**。`raw call vault.stock-note.delete` 同样要 `--yes`
|
|
213
|
+
- `--note-id` 可重复或逗号分隔,一次最多 100 个;**只接受明确的 ID,没有 `all`**——批量删先 `stock-note-list` 拿 ID 核对
|
|
214
|
+
- 幂等:已删掉的、不存在的、不属于本人的 ID 都进 `successList`(不会删到别人的笔记),重复执行仍算成功
|
|
215
|
+
- 部分失败同股票池写命令:服务端仍返回成功信封、把失败项放进 `failList`,CLI 在 stderr 列出、标 `partial`、**退出码 3**;拿到结果后只需对 `failList` 里的 ID 重试
|
|
216
|
+
- 返回字段:`successList[]` + `failList[]{stockNoteId, failReason}`
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
| `999999` | 系统错误。`indicator`(EDE)的「无数据」不用此码(无数据是保留行列的占位单元格 `null`,见 `commands/indicator.md`;代码或参数名写错报 `100003`、缺必填参数报 `100001`,都会点名),所以这个码基本只剩真故障 | 普通端点自动重试 ×2;🔴 贵档与 `indicator` 端点不重试 | 确认参数无误仍报此码即服务端故障 |
|
|
17
17
|
| `410110` | **异步生成中**(HTTP 400,旧码)。新码 `140001`,CLI 两码都认 | 轮询视为 pending | 继续等 |
|
|
18
18
|
| `410111` | **异步生成失败**(HTTP 400,旧码)。新码 `140002`,CLI 两码都认 | 终态 | **不重试**,换参数 |
|
|
19
|
-
| `130002` | 资源不存在——下载类的常见码:`reportId` 不存在 / 非数字多归此码。另有更具体的 `130003`(资源未生成 /
|
|
19
|
+
| `130002` | 资源不存在——下载类的常见码:`reportId` 不存在 / 非数字多归此码。另有更具体的 `130003`(资源未生成 / 无附件;`vault wechat-message-download` 收到它是消息不存在、无权访问或文件已不可用,不区分原因、重试不会变)与 `130005`(`vault wechat-message-download`:该消息是 text / url,没有文件);`--file-type` 写错由 CLI 在本地报错、不发请求。`vault stock-note-update` 传了不存在或不属于本人的笔记 ID 也报此码(`stock-note-delete` 不报,这类 ID 计入 `successList`) | — | 确认 ID 有效且本账号可见(笔记 ID 用 `vault stock-note-list` 核对);换 `--file-type` 或换一篇验证 |
|
|
20
20
|
| `130001` | 数据未找到,或**该指标无权限**(`indicator` 内层失败会带具体 msg 如"指标无权限") | — | 检查查询条件与指标权限 |
|
|
21
21
|
| `100001` | 缺必填参数——**msg 带字段名**(「缺少必填参数: reportId」) | — | 按 msg 指的字段补上 |
|
|
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` 无论怎么缩都报错);**换接口绕不过去**,要更长历史联系客户经理开通。⚠️ 区间**跨过**下界时,`indicator`、`bond` 与 `fund` 报这个码,`quote` 日 K 与 `valuation-analysis` 则从下界起返回、不报错——核对首行日期 |
|
|
25
|
-
| `100006` | 查询/下载数量超限;**`indicator cross-section` / `time-series` 单次单元格数超 30000**、**`fund` 命令单次超过 10000
|
|
25
|
+
| `100006` | 查询/下载数量超限;**`indicator cross-section` / `time-series` 单次单元格数超 30000**、**`fund` 命令单次超过 10000 行**、**`quote sector-fund-flow` 计算量超限**也是此码(msg 写明限额) | — | 缩短日期范围或调小 `--size`/`--limit`;全市场场景应已自动分片;EDE 按「截面=证券数×指标数、时序=证券数或指标数×日期数」拆批;`fund` 不分页、没有 `--size`,减少 `--security` 只数或缩短日期区间分批查;`quote sector-fund-flow` 缩短日期区间、减少 `--sector` 或 `--field`,**调小 `--limit` 无效**(它只截返回行数,不减计算量) |
|
|
26
26
|
| `240001` | 财报期未披露或超出查询期(`earnings-review` 提交阶段就报,**不扣积分**) | — | 换更早的 `--period`(`2025q3` → `2025interim`) |
|
|
27
27
|
| `250001` | 不支持的数据源 | — | 检查 `resourceType + sourceId` 组合 |
|
|
28
28
|
| `999011` | 开发账号凭证无效(不区分 AK 错还是 SK 错) | 登录即失败,**不重试** | 检查 `GANGTISE_ACCESS_KEY`/`GANGTISE_SECRET_KEY` 是否写反或未 export |
|
|
@@ -269,7 +269,7 @@
|
|
|
269
269
|
--date <最新交易日> --key-by code --format json
|
|
270
270
|
4. 按 security 合并两张宽表(列头即 indicatorCode,各取所需日期的值);不要把不同日期语义的指标塞进同一个 --date。
|
|
271
271
|
5. 计费:search 免费;两次取数各按请求单元格数量计费,每次不足 100 单元格按 100 计。
|
|
272
|
-
6. 无数据(无覆盖 / 非交易日 / 未来日期)一律保留行列并给占位单元格,退出码 0——占位值统一是 null(见 commands/indicator.md);⚠️ 报告期类指标(is_
|
|
272
|
+
6. 无数据(无覆盖 / 非交易日 / 未来日期)一律保留行列并给占位单元格,退出码 0——占位值统一是 null(见 commands/indicator.md);⚠️ 报告期类指标(is_*)的时序与交易日类指标混查、或显式传 ND / TD / WD 时,只有报告期末那几行是真值,别对整列手工求均值。代码写错或参数名写错则直接报 100003 并点名是哪个(指标码拼错、证券后缀错如美股写成 .US、参数名写错、同 code 重复配置),按报错改即可。
|
|
273
273
|
```
|
|
274
274
|
|
|
275
275
|
## 例 15b:帕米尔专家纪要(独立库,筛选项与踩坑都和 summary 不同)
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
| 接口 | 响应里发生什么 | CLI 怎么处理 |
|
|
10
10
|
| :-- | :-- | :-- |
|
|
11
11
|
| `quote realtime` / `day-kline` / `minute-kline` / `fund-flow` | **不报错,字段名和值一起消失**,`fieldList` 里也没有它,列数与值数始终对得上 | 比对请求与返回的列名,缺列标 `partial` + `missingFields`、在 stderr 点名、**退出码 3** |
|
|
12
|
-
| `fundamental main-business` / `valuation-analysis` | 整条报 `100005`,msg 点名写错的名字(`fieldList 枚举值非法:
|
|
12
|
+
| `fundamental main-business` / `valuation-analysis`、`quote sector-fund-flow` | 整条报 `100005`,msg 点名写错的名字(`fieldList 枚举值非法: <名字>` / `fieldList 包含不支持的字段 [<名字>]`) | 原样报错,退出 1 |
|
|
13
13
|
| `bond` / `fund` | 整条报 `100003` 并点名 | 原样报错,退出 1 |
|
|
14
14
|
|
|
15
15
|
**行情这一族才是要留神的那个**:结果只是少一列、看着正常。绕过 CLI 直连时,`fieldList` 与行**始终等长**,只比长度什么都查不出来——要拿**请求的字段名**去比**返回的 `fieldList`**,少了哪个就是那个名字没被认出来。
|
|
@@ -4,7 +4,7 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
|
|
|
4
4
|
|
|
5
5
|
> 例外:`indicator`(EDE)四个接口(`search` / `cross-section` / `time-series` / `screener`)成功时**双层信封**(`data` 里再裹一层 `{code, status, data}`)。内层字段名为 `securityCodeList` / `securityNameList` / `indicatorList[{code,name,dataType}]`(screener 另带 `field`),`values` 是 2D 矩阵:**截面与 screener 为 `[证券][指标]`**、时序为 `[序列][日期]`。
|
|
6
6
|
>
|
|
7
|
-
> **缺数据 vs 代码写错**:无数据 / 无覆盖一律保留行列并给占位单元格——**占位值统一为 `null`**;⚠️ 报告期类指标(`is_
|
|
7
|
+
> **缺数据 vs 代码写错**:无数据 / 无覆盖一律保留行列并给占位单元格——**占位值统一为 `null`**;⚠️ 报告期类指标(`is_*`)的时序与交易日类指标混查、或显式传 `ND` / `TD` / `WD` 时,只有报告期末那几行是真值,其余全是 `null`,详见 `commands/indicator.md`。**代码写错则直接报 `100003` 并点名**(指标 code 拼错 →「指标 xxx 不存在」;证券 code 后缀错 →「xxx 不是有效证券或者板块ID」,美股是 `.O`/`.N`/`.A` 不是 `.US`),**无论同批有没有正确的 code 都会报**。CLI 的 `indicator` 子命令已二次解包、拍平成宽表;服务端没有返回请求里的某个指标或证券时标 `partial` + `omittedIndicators` / `omittedSecurities`、退出码 3(写错的 code 会直接报 `100003`,所以这种情况很少出现)。**`screener` 例外**:把缺列的变量当作无法求值,按表达式的**布尔结构**判断是否还有分支能成立(`A && B` 要两边、`A || B` 只要一边)。一条都不剩 → **退出码 1 且不输出**(那些行以「通过了该条件」的名义呈现,而条件根本无法证明被执行过);仍有分支可求值、或缺的只是输出用的辅助变量 → `partial` + 退出码 3。直接 `raw call indicator.*` 只会剥外层,内层需自行处理。
|
|
8
8
|
|
|
9
9
|
## 通用模式(5 类)
|
|
10
10
|
|
|
@@ -27,7 +27,7 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
|
|
|
27
27
|
| insight summary download | 文件路径(stdout) | — |
|
|
28
28
|
| insight pamirs-summary list | `{list, total}` | `list[].summaryId` / `list[].title` / `list[].brief` / `list[].summaryTime`(纪要生成时间)/ `list[].publishTime`(发布时间)/ `list[].securityList[]{securityCode, securityName}` / `list[].researchAreaList[]{researchAreaId, researchAreaName}` / `list[].conceptList[]{conceptId, conceptName}` / `list[].categoryList` / `list[].marketList`。⚠️ `conceptList` / `categoryList` / `marketList` 三个标签字段**稀疏,且是否有值随记录和查法而变**:不带筛选时经常整条为空,用 `--category` 或 `--market` 任一过滤时回填率明显更高(这两个字段绑定,一起有或一起没有)。所以**别拉全量再本地分组**(会漏记录),也**别据此断言某条记录没有该属性**(为空只说明这次没回填)。详见 `commands/insight.md` |
|
|
29
29
|
| insight pamirs-summary download | 文件路径(stdout) | — |
|
|
30
|
-
| insight roadshow / site-visit / strategy / forum list | `{list, total}` | 各自的 ID:`list[].roadshowId` / `siteVisitId` / `strategyMeetingId` / `forumId`;`list[].title` / `list[].startTime` / `list[].endTime
|
|
30
|
+
| insight roadshow / site-visit / strategy / forum list | `{list, total}` | 各自的 ID:`list[].roadshowId` / `siteVisitId` / `strategyMeetingId` / `forumId`;`list[].title` / `list[].startTime` / `list[].endTime`(举办时间)/ `list[].publishTime`(首次收录时间,可为 `null`)/ `list[].location`;路演、调研、策略会另有 `list[].institutionList[]{institutionId, institutionName}`(论坛没有) |
|
|
31
31
|
| insight research list | `{list, total}` | `list[].reportId` / `list[].title` / `list[].brief`(全文摘要) / `list[].publishTime` / `list[].publisher.brokerName` / `list[].securityList[].rating` |
|
|
32
32
|
| insight research download | 文件路径(stdout) | — |
|
|
33
33
|
| insight foreign-report list | `{list, total}` | `list[].reportId` / `list[].title` / `list[].titleTranslate` / `list[].brief` / `list[].briefTranslate`(中译全文摘要) / `list[].publishTime` / `list[].publisher.brokerName` |
|
|
@@ -61,10 +61,12 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
|
|
|
61
61
|
| reference concept-search | `{returnedCount, list}` | `list[].conceptId` / `list[].conceptName` / `list[].matchScore` |
|
|
62
62
|
| reference sector-search | `{returnedCount, list}` | `list[].sectorId` / `list[].sectorName` / `list[].hierarchy`(层级路径) / `list[].matchScore` |
|
|
63
63
|
| reference sector-constituents | `{total, list}` | `list[].gtsCode` / `list[].gtsName`;total=0 说明 sectorId 不对(先 sector-search 确认) |
|
|
64
|
+
| reference index-weight | `{total, list}`,不分页 | `list[].indexCode` / `indexName` / `tradeDate` / `securityCode` / `securityName` / `weight`(%);多个指数合在一个 `list`,按 `indexCode` 区分;total=0 多为日期不是月末交易日 |
|
|
64
65
|
| quote day-kline(及已弃用的 day-kline-hk / day-kline-us / index-day-kline) | `{fieldList, list}` 或规范化后 `{list: [{...}]}` | `tradeDate` / `securityCode` / `open` / `close` / `pctChange` / `volume` / `amount`(全球指数为 `null`)/ `adjustFactor`(指数为 `null`,ETF 有值);四者字段相同,均不含指数名称 |
|
|
65
66
|
| quote minute-kline | `{list: [{...}]}` | `tradeTime` / `open` / `close` / `volume` |
|
|
66
67
|
| quote realtime | `{fieldList, list, total}` 或规范化后 `{list: [{...}]}` | `securityCode` / `exchange` / `tradeDate` / `tradeTime` / `tradeStatus` / `open` / `high` / `low` / `latestPrice` / `preClose` / `change` / `pctChange` / `volume` / `amount` / `amplitude`(共 15 个,**无 `close`、无市值、无 `turnoverRate` / `volumeRatio`**;美股 `amount`、全球指数 `volume` / `amount` / `amplitude` 为 `null`) |
|
|
67
68
|
| quote fund-flow | `{fieldList, list, total}` 列式 → 规范化后 `{list: [{...}], total}` 宽表 | `securityCode` / `tradeDate` + 请求的字段(`mainNetInflow` / `largeInflow` / `xlargeOutflow` / …) |
|
|
69
|
+
| quote sector-fund-flow | 同 `fund-flow` | `sectorId` / `tradeDate` + 请求的字段(`sectorMainNetInflow` / `sectorLargeInflow` / `sectorTotalOutflow` / …,单位元)。`total` 是本次返回行数,不是满足条件的总数 |
|
|
68
70
|
| fundamental income-statement / balance-sheet / cash-flow(含 quarterly / -hk / -us) | `{total, list: [{...}]}` | `fiscalYear` / `period` / `endDate` / `companyName` / `companyType` / `currency` / `unit` + 各 `--field` 字段;港股/美股另含 `timeCovered`(不规则跨度)。⚠️ A 股 `*-quarterly` 单季表的 `companyType` 返回未映射的数字码(如 `102119999`),`currency` 正常;累计口径的三张表两列均正确。科目数字不受影响 |
|
|
69
71
|
| fundamental main-business | `{fieldList, list}` 列式 → 规范化后 `{list: [{...}]}` | 前 3 列恒定:`periodName` / `periodEndDate` / `categoryName`(分项名,随 `--breakdown` 变)+ `opRevenue` / `opRevenueYoy` / `opRevenueRatio` / `opCost` / `opCostYoy` / `opCostRatio` / `grossProfit` / `grossProfitYoy` / `grossProfitRatio` / `grossMargin` / `grossMarginYoy` / `grossMarginRatio`(共 15 个)。`--field` 只能从后 12 个里选 |
|
|
70
72
|
| fundamental valuation-analysis(仅 A 股) | `{fieldList, list}` 列式 → 规范化后 `{list: [{...}]}` | `tradeDate` / `value` / `percentileRank` / `average` / `median` / `upper1Std` / `lower1Std`(共 7 个);**无 `securityCode`**——`--field` 写不存在的名字(含 `securityCode`)报 `100005`;只传 `tradeDate` 返回 0 行、不报错 |
|
|
@@ -77,6 +79,7 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
|
|
|
77
79
|
| ai theme-tracking | `[{type, date, content}, ...]`(列表,每元素一份报告) | 遍历筛选 `type === "morning" / "night"`;某主题在该日期可能只有一种类型,或两种都没(空列表) |
|
|
78
80
|
| ai hot-topic | `{list, total}` | `list[].title` / `list[].reportDate` / `list[].category` / `list[].topics[].topicTitle` / `list[].topics[].driverEvent` / `list[].topics[].investLogic` |
|
|
79
81
|
| ai management-discuss-* | `{securityCode, reportDate, discussionDimension, content}` | `content` 为字符串(业绩会)或字符串数组(财报) |
|
|
82
|
+
| ai expert-intel | `{list, total}` | `list[].intelId` / `title` / `mainSecurity.securityCode` · `securityName` / `tagList[]`(纯文本)/ `content` / `publishTime` / `securityList[]` / `researchAreaList[].researchAreaName` / `conceptList[].conceptName` |
|
|
80
83
|
| ai management-sentiment-indicator | `{list, total}`,一条 = 一只证券 × 一场业绩会 | `list[].securityCode` / `publishTime` / `sentimentResponsiveness` · `sentimentPolarity` · `sentimentConviction`(0–5)/ `qaCount` / `qaEvasionRatio` · `qaRiskRatio` · `qaUncertaintyRatio`(百分数)/ `questionCategoryList[]` / `source.sourceType` + `source.sourceId` |
|
|
81
84
|
| ai management-sentiment-conclusion | `{list, total}`,粒度同上 | `list[].sentimentSummary.{overallSentiment, questionCategorySentiment, qaSentimentChange}` / `sentimentSignal.*Signal`(文本)/ `qaSentimentContrast[]` / `source` / `previousSource`(无可对比的上一场时为 `null`) |
|
|
82
85
|
| ai management-sentiment-detail | `{list, total}`,一条 = 一条问答,不分页 | `list[].qaId` / `questionCategory` / `questionBrief` / `question` / `answer` / `qaResponsiveness` · `qaPolarity` · `qaConviction`(`5.0` / `2.5` / `0.0` 三档)/ 三组 `*Quote` + `*Reason` |
|
|
@@ -95,13 +98,18 @@ CLI 自动处理 envelope:`{code, msg, data}` 信封会按 `code === "000000"`
|
|
|
95
98
|
| vault record-download | 文件路径(stdout) | — |
|
|
96
99
|
| vault my-conference-list | `{list, total}` | `list[].conferenceId` / `list[].title` / `list[].category` / `list[].institution.institutionName` / `list[].publishTime` |
|
|
97
100
|
| vault my-conference-download | 文件路径(stdout) | — |
|
|
98
|
-
| 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` |
|
|
101
|
+
| 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[].fileInfo.fileName` · `fileSize`(文档 / 图片 / 音频 / 视频消息,其他为 `null`)/ `list[].quoteMsg.quoteMsgId` · `quoteCategory` · `quoteContent` · `quoteFileInfo`(引用消息,无引用为 `null`)。**字段名是 `content` / `url`**,不是 `msgContent` / `contentUrl`;`msgId` 是长数字串,按字符串保存 |
|
|
102
|
+
| vault wechat-message-download | 文件路径(stdout) | — |
|
|
99
103
|
| vault wechat-chatroom-list | `{list, total}` | `list[].chatroomName` / `list[].chatroomId` |
|
|
100
|
-
| vault stock-pool-list | 数组 | `[].poolId`(后续命令的 `--pool-id`)/ `[].poolName` |
|
|
104
|
+
| vault stock-pool-list | 数组 | `[].poolId`(后续命令的 `--pool-id`)/ `[].poolName` / `[].spaceType`(`1` 个人、`2` 租户;查明细时 `--space-type` 要与之一致) |
|
|
101
105
|
| vault stock-pool-stocks | 数组 | `[].securityCode` / `[].securityName`。空池返回 `[]` |
|
|
102
106
|
| vault stock-pool-create / stock-pool-rename | `{poolId, poolName}` | 新建 / 改名后的池 ID 与名称 |
|
|
103
107
|
| vault stock-pool-add-stock / stock-pool-remove-stock | `{successList, failList}` | `successList[]` 是规范化后的证券代码(含已在池内 / 本就不在池内的幂等成功项);`failList[]{securityCode, failReason}`。**外层 `code` 恒为 `000000`,逐条失败只在 `failList` 里**——CLI 检测到非空时标 `partial`、退出码 3 |
|
|
104
108
|
| vault stock-pool-delete | `{successList, failList}` | 同上,但键是 `failList[].poolId`;删不存在的池算幂等成功,计入 `successList` |
|
|
109
|
+
| vault stock-note-list | `{list, total}` | `list[].stockNoteId`(后续命令的 `--note-id`)/ `list[].securityList`(该笔记完整的关联证券,升序)/ `list[].content` / `list[].createTime` / `list[].updateTime`。`total` 是按笔记去重后的真实总数 |
|
|
110
|
+
| vault stock-note-add | `{stockNoteId, securityList}` | 新笔记 ID 与实际关联的规范化证券代码(升序) |
|
|
111
|
+
| vault stock-note-update | `{}` | 成功即空对象;改后的时间从 `stock-note-list` 看 |
|
|
112
|
+
| vault stock-note-delete | `{successList, failList}` | `successList[]` 是笔记 ID(含已不存在的幂等成功项);`failList[]{stockNoteId, failReason}`,非空时 CLI 标 `partial`、退出码 3 |
|
|
105
113
|
| alternative edb-search | `{list: [...]}` 指标列表 | `indicatorId` / `indicatorName` / `dataSource` / `frequency` / `unit` |
|
|
106
114
|
| alternative edb-data | 列表,每行 `{date, <indicatorId>: value, ...}` 宽表 | `date` + 每个 `--indicator-id` 一列(该日指标值) |
|
|
107
115
|
| alternative concept-info | `{conceptId, conceptName, ...}`(单对象,**非列表**) | `conceptName` / `definition` / `investmentLogic` / `industrySpace` / `competitiveLandscape`;**`keyEvents[].date` / `keyEvents[].content` 仅 `--full`**;文本字段未配置为 `null` |
|
package/package.json
CHANGED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { unwrapIndicatorData } from "./indicatorMatrix.js";
|
|
2
|
-
import { runWithConcurrency } from "./transport.js";
|
|
3
|
-
const TRADE_DATE_KEY = "tradeDate";
|
|
4
|
-
const PERIOD_DATE_KEYS = ["reportDate", "fiscalYear"];
|
|
5
|
-
const PROBE_CONCURRENCY = 5;
|
|
6
|
-
export async function resolveCalendarType(client, indicators) {
|
|
7
|
-
const codes = [...new Set(indicators.filter((code) => typeof code === "string" && code.length > 0))];
|
|
8
|
-
if (codes.length === 0)
|
|
9
|
-
return undefined;
|
|
10
|
-
const verdicts = await runWithConcurrency(codes, PROBE_CONCURRENCY, (code) => isTradingDayTyped(client, code));
|
|
11
|
-
return verdicts.every((verdict) => verdict === true) ? "TD" : undefined;
|
|
12
|
-
}
|
|
13
|
-
async function isTradingDayTyped(client, code) {
|
|
14
|
-
let entry;
|
|
15
|
-
try {
|
|
16
|
-
entry = await findIndicator(client, code);
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return false;
|
|
20
|
-
}
|
|
21
|
-
if (!entry)
|
|
22
|
-
return false;
|
|
23
|
-
const keys = paramKeys(entry.parameterList);
|
|
24
|
-
if (keys.length === 0)
|
|
25
|
-
return false;
|
|
26
|
-
if (keys.some((key) => PERIOD_DATE_KEYS.includes(key)))
|
|
27
|
-
return false;
|
|
28
|
-
return keys.includes(TRADE_DATE_KEY);
|
|
29
|
-
}
|
|
30
|
-
async function findIndicator(client, code) {
|
|
31
|
-
const raw = await client.call("indicator.search", { keyword: code, limit: 100 });
|
|
32
|
-
const data = unwrapIndicatorData(raw);
|
|
33
|
-
const list = Array.isArray(data) ? data : data?.list;
|
|
34
|
-
if (!Array.isArray(list))
|
|
35
|
-
return undefined;
|
|
36
|
-
return list.find((item) => !!item && typeof item === "object" && item.indicatorCode === code);
|
|
37
|
-
}
|
|
38
|
-
function paramKeys(parameterList) {
|
|
39
|
-
if (!Array.isArray(parameterList))
|
|
40
|
-
return [];
|
|
41
|
-
return parameterList
|
|
42
|
-
.map((param) => (param && typeof param === "object" ? param.paramKey : undefined))
|
|
43
|
-
.filter((key) => typeof key === "string");
|
|
44
|
-
}
|