gangtise-openapi-cli 0.12.0 → 0.13.1

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 CHANGED
@@ -4,6 +4,20 @@
4
4
 
5
5
  ## Changelog
6
6
 
7
+ ### v0.13.0 — 2026-05-15
8
+
9
+ **新增接口**
10
+ - `fundamental income-statement-hk / balance-sheet-hk / cash-flow-hk` — 港股三大报表(中国会计准则)
11
+ - `alternative edb-search` — 行业指标列表搜索(按关键词匹配指标名称,返回 indicatorId 等元信息)
12
+ - `alternative edb-data` — 行业指标时序数据(批量按 indicatorId 拉取时间序列,最多 10 个指标)
13
+ - `vault stock-pool-list` — 查询用户自选股股票池列表(poolId / poolName)
14
+ - `vault stock-pool-stocks` — 查询股票池证券明细(支持 `--pool-id all` 全量查询)
15
+
16
+ **接口变更**
17
+ - `fundamental income-statement / balance-sheet / cash-flow / income-statement-quarterly / cash-flow-quarterly` 名称调整为 A股报表(路径不变)
18
+ - `ai management-discuss-announcement` `--dimension` 新增 `all` 选项,返回报告中完整的管理层讨论内容(内容可能较长)
19
+ - `vault wechat-message-list` 新增 `--security <code>` 参数(按证券代码过滤),返回结果增加 `securityList` 字段
20
+
7
21
  ### v0.12.0 — 2026-05-10
8
22
 
9
23
  **性能 / 架构**
@@ -111,10 +125,20 @@ Skill 目录结构:
111
125
 
112
126
  ```
113
127
  gangtise-openapi/
114
- ├── SKILL.md # 主 skill 文件(命令参考、参数枚举、使用规则)
128
+ ├── SKILL.md # 主 skill 文件(必备规则、速查表、按需引用 references)
115
129
  └── references/
116
- ├── fields.md # 字段中英文对照速查表
117
- └── lookup-ids.md # 常用 ID 速查表(行业/券商/机构/公告分类等)
130
+ ├── commands/ # 按命令组拆分的详细参数文档(agent 按需 Read)
131
+ │ ├── ai.md # AI 能力命令(one-pager / earnings-review / viewpoint-debate 等)
132
+ │ ├── alternative.md # 行业指标数据库(EDB search / EDB data)
133
+ │ ├── fundamental.md # 财务数据命令(A股/港股三大报表 / 估值 / 盈利预测 / 股东)
134
+ │ ├── insight.md # 投研内容命令(研报 / 观点 / 纪要 / 公告 / 外资)
135
+ │ ├── quote.md # 行情命令(A股/港股/指数 K 线)
136
+ │ ├── reference-and-lookup.md # GTS Code 搜索与枚举速查
137
+ │ └── vault.md # 云盘/录音/会议/群消息/股票池
138
+ ├── examples.md # 典型场景的端到端示例
139
+ ├── fields.md # K线/财务字段中英文对照速查表
140
+ ├── lookup-ids.md # 常用 ID 速查表(行业/券商/机构/公告分类等)
141
+ └── response-schema.md # 各接口响应字段说明
118
142
  ```
119
143
 
120
144
  安装:
@@ -166,8 +190,9 @@ cp -r gangtise-openapi ~/.hermes/skills/gangtise-openapi
166
190
  | **Quote** | `day-kline` / `day-kline-hk` | A股/港股日K线 |
167
191
  | | `index-day-kline` | 沪深京指数日K线 |
168
192
  | | `minute-kline` | A股分钟K线 |
169
- | **Fundamental** | `income-statement` / `balance-sheet` / `cash-flow` | 三大财务报表(累计) |
170
- | | `income-statement-quarterly` / `cash-flow-quarterly` | 利润表/现金流量表(单季度) |
193
+ | **Fundamental** | `income-statement` / `balance-sheet` / `cash-flow` | A股三大财务报表(累计) |
194
+ | | `income-statement-quarterly` / `cash-flow-quarterly` | A股利润表/现金流量表(单季度) |
195
+ | | `income-statement-hk` / `balance-sheet-hk` / `cash-flow-hk` | 港股三大财务报表(中国会计准则) |
171
196
  | | `main-business` | 主营构成(按地区/产品拆分) |
172
197
  | | `valuation-analysis` | 估值分析 |
173
198
  | | `earning-forecast` | 盈利预测(一致预期) |
@@ -189,6 +214,9 @@ cp -r gangtise-openapi ~/.hermes/skills/gangtise-openapi
189
214
  | | `record-list` / `record-download` | 录音速记列表与下载 |
190
215
  | | `my-conference-list` / `my-conference-download` | 我的会议列表与下载 |
191
216
  | | `wechat-message-list` / `wechat-chatroom-list` | 群消息列表与群ID查询 |
217
+ | | `stock-pool-list` / `stock-pool-stocks` | 自选股股票池列表与证券明细 |
218
+ | **Alternative** | `edb-search` | 行业指标搜索(按关键词匹配,返回 indicatorId 等元信息) |
219
+ | | `edb-data` | 行业指标时序数据(批量拉取,最多10个指标) |
192
220
  | **Raw** | `call` | 原始接口调用(可访问任意 endpoint) |
193
221
 
194
222
  ## 命令概览
@@ -200,6 +228,7 @@ cp -r gangtise-openapi ~/.hermes/skills/gangtise-openapi
200
228
  - `gangtise fundamental ...`
201
229
  - `gangtise ai ...`
202
230
  - `gangtise vault ...`
231
+ - `gangtise alternative ...`
203
232
  - `gangtise reference ...`
204
233
  - `gangtise raw call ...`
205
234
 
@@ -390,6 +419,14 @@ gangtise fundamental cash-flow-quarterly --security-code 600519.SH --fiscal-year
390
419
  gangtise fundamental top-holders --security-code 600519.SH --holder-type top10 --fiscal-year 2025 --format json
391
420
  # 前十大流通股东(按日期范围)
392
421
  gangtise fundamental top-holders --security-code 600519.SH --holder-type top10Float --start-date 2025-01-01 --end-date 2025-12-31 --period q3 --format json
422
+
423
+ # 港股三大报表(中国会计准则,--security-code 用港股代码)
424
+ gangtise fundamental income-statement-hk --security-code 09992.HK --fiscal-year 2025 --period annual --field netProfit --field basicEPS
425
+ gangtise fundamental income-statement-hk --security-code 09992.HK --fiscal-year 2023 --fiscal-year 2024 --fiscal-year 2025 --period annual --field netProfit
426
+ gangtise fundamental balance-sheet-hk --security-code 09992.HK --fiscal-year 2025 --period h1 --field totalCurrAssets --field totalNonCurrAssets --field totalCurrLiab --field totalNonCurrLiab
427
+ gangtise fundamental cash-flow-hk --security-code 09992.HK --fiscal-year 2025 --period annual --field netOpCashFlows --field netInvCashFlows --field netFinCashFlows
428
+ # 最新一期完整港股利润表
429
+ gangtise fundamental income-statement-hk --security-code 09992.HK --format json
393
430
  ```
394
431
 
395
432
  ### AI
@@ -408,8 +445,11 @@ gangtise ai hot-topic --start-date 2026-03-22 --end-date 2026-03-27 --category m
408
445
  # 不传 --category 默认查全部类型(早报+午报+盘中快报+晚报),--with-related-securities 和 --with-close-reading 默认开启,可用 --no-with-related-securities / --no-with-close-reading 关闭
409
446
  gangtise ai hot-topic --start-date 2026-04-15 --end-date 2026-04-17
410
447
  gangtise ai research-outline --security-code 600519.SH
411
- # 管理层讨论-财报
448
+ # 管理层讨论-财报(三个细分维度)
412
449
  gangtise ai management-discuss-announcement --report-date 2025-06-30 --security-code 000001.SZ --dimension businessOperation
450
+ gangtise ai management-discuss-announcement --report-date 2025-12-31 --security-code 000001.SZ --dimension financialPerformance
451
+ # 传入 all 返回完整管理层讨论内容(内容较长,谨慎使用)
452
+ gangtise ai management-discuss-announcement --report-date 2025-12-31 --security-code 000001.SZ --dimension all
413
453
  # 管理层讨论-业绩会
414
454
  gangtise ai management-discuss-earnings-call --report-date 2025-06-30 --security-code 000001.SZ --dimension financialPerformance
415
455
  # 观点PK(异步,返回 dataId)
@@ -443,6 +483,39 @@ gangtise vault my-conference-download --conference-id 43319 --content-type asr
443
483
  # 群消息:先按群名称查群ID,再按群ID查消息
444
484
  gangtise vault wechat-chatroom-list --room-name "AI学习群,投研分享群" --size 50
445
485
  gangtise vault wechat-message-list --keyword AI应用 --wechat-group-id ueKEGyhdjFGkjyebh --category text --category url --tag roadShow --tag meetingSummary --size 50
486
+ # 按证券代码过滤群消息
487
+ gangtise vault wechat-message-list --security 000001.SZ --security 300750.SZ --size 50
488
+
489
+ # 自选股股票池
490
+ gangtise vault stock-pool-list
491
+ # 查询指定股票池中的证券
492
+ gangtise vault stock-pool-stocks --pool-id 808477293
493
+ # 查询所有股票池中的全量证券(默认行为)
494
+ gangtise vault stock-pool-stocks
495
+ ```
496
+
497
+ ### Alternative(行业指标数据库 EDB)
498
+
499
+ ```bash
500
+ # Step 1:按关键词搜索指标,获取 indicatorId
501
+ gangtise alternative edb-search --keyword 空调 --limit 50 --format table
502
+ gangtise alternative edb-search --keyword "海尔销量"
503
+
504
+ # Step 2:按 indicatorId 拉取时间序列数据(最多10个指标)
505
+ gangtise alternative edb-data \
506
+ --indicator-id S14001618 \
507
+ --indicator-id S14001620 \
508
+ --start-date 2024-01-01 \
509
+ --end-date 2024-12-31 \
510
+ --format table
511
+
512
+ # 导出为 CSV
513
+ gangtise alternative edb-data \
514
+ --indicator-id S14001618 \
515
+ --start-date 2023-01-01 \
516
+ --end-date 2024-12-31 \
517
+ --format csv \
518
+ --output ./indicator.csv
446
519
  ```
447
520
 
448
521
  ### Raw
package/dist/src/cli.js CHANGED
@@ -303,6 +303,9 @@ addFinancialReport("income-statement-quarterly", "fundamental.income-statement-q
303
303
  addFinancialReport("balance-sheet", "fundamental.balance-sheet");
304
304
  addFinancialReport("cash-flow", "fundamental.cash-flow");
305
305
  addFinancialReport("cash-flow-quarterly", "fundamental.cash-flow-quarterly", "Period: q1/q2/q3/q4/latest");
306
+ addFinancialReport("income-statement-hk", "fundamental.income-statement-hk", "Period: q1/h1/q3/h2/nsd/annual/latest");
307
+ addFinancialReport("balance-sheet-hk", "fundamental.balance-sheet-hk", "Period: q1/h1/q3/h2/nsd/annual/latest");
308
+ addFinancialReport("cash-flow-hk", "fundamental.cash-flow-hk", "Period: q1/h1/q3/h2/nsd/annual/latest");
306
309
  fundamental.command("main-business").requiredOption("--security-code <code>").option("--start-date <date>").option("--end-date <date>").addOption(new Option("--breakdown <type>", "Breakdown: product/industry/region").choices(["product", "industry", "region"]).default("product")).option("--period <type>", "Period: interim/annual", collectList, []).option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
307
310
  const client = await createClient();
308
311
  await printData(await client.call("fundamental.main-business", { securityCode: options.securityCode, startDate: options.startDate, endDate: options.endDate, breakdown: options.breakdown, periodList: maybeArray(options.period), fieldList: maybeArray(options.field) }), parseOutputFormat(options.format), options.output);
@@ -412,7 +415,7 @@ ai.command("hot-topic").option("--from <number>", "Starting offset", "0").option
412
415
  withCloseReading: options.withCloseReading === false ? undefined : true,
413
416
  }), parseOutputFormat(options.format), options.output);
414
417
  });
415
- ai.command("management-discuss-announcement").requiredOption("--report-date <date>", "Report date (yyyy-MM-dd, e.g. 2025-06-30)").requiredOption("--security-code <code>", "Security code (e.g. 000001.SZ)").addOption(new Option("--dimension <name>", "Discussion dimension").choices(["businessOperation", "financialPerformance", "developmentAndRisk"]).makeOptionMandatory()).option("--format <format>", "Output format", "json").option("--output <path>").action(async (options) => {
418
+ ai.command("management-discuss-announcement").requiredOption("--report-date <date>", "Report date (yyyy-MM-dd, e.g. 2025-06-30)").requiredOption("--security-code <code>", "Security code (e.g. 000001.SZ)").addOption(new Option("--dimension <name>", "Discussion dimension: businessOperation/financialPerformance/developmentAndRisk/all").choices(["businessOperation", "financialPerformance", "developmentAndRisk", "all"]).makeOptionMandatory()).option("--format <format>", "Output format", "json").option("--output <path>").action(async (options) => {
416
419
  const client = await createClient();
417
420
  await printData(await client.call("ai.management-discuss-announcement", {
418
421
  reportDate: options.reportDate,
@@ -499,7 +502,7 @@ vault.command("my-conference-download").requiredOption("--conference-id <id>").r
499
502
  resolveOutputPath: (result) => resolveTitle(client, result, "vault.my-conference.list", "conferenceId", options.conferenceId),
500
503
  });
501
504
  });
502
- vault.command("wechat-message-list").option("--from <number>", "Starting offset", "0").option("--size <number>", "Total rows to return; omit to fetch all").option("--start-time <datetime>").option("--end-time <datetime>").option("--keyword <text>").option("--wechat-group-id <id>", "WeChat group ID", collectList, []).option("--industry <id>", "Industry ID", collectList, []).option("--category <name>", "Message type: text/image/documents/url", collectList, []).option("--tag <name>", "Tag: roadShow/research/strategyMeeting/meetingSummary/industryComment/companyComment/earningsReview", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
505
+ vault.command("wechat-message-list").option("--from <number>", "Starting offset", "0").option("--size <number>", "Total rows to return; omit to fetch all").option("--start-time <datetime>").option("--end-time <datetime>").option("--keyword <text>").option("--security <code>", "Security code (e.g. 000001.SZ)", collectList, []).option("--wechat-group-id <id>", "WeChat group ID", collectList, []).option("--industry <id>", "Industry ID", collectList, []).option("--category <name>", "Message type: text/image/documents/url", collectList, []).option("--tag <name>", "Tag: roadShow/research/strategyMeeting/meetingSummary/industryComment/companyComment/earningsReview", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
503
506
  const client = await createClient();
504
507
  await printData(await client.call("vault.wechat-message.list", buildWechatMessageListBody(options)), parseOutputFormat(options.format), options.output);
505
508
  });
@@ -507,8 +510,42 @@ vault.command("wechat-chatroom-list").option("--from <number>", "Starting offset
507
510
  const client = await createClient();
508
511
  await printData(await client.call("vault.wechat-chatroom.list", buildWechatChatroomListBody(options)), parseOutputFormat(options.format), options.output);
509
512
  });
513
+ vault.command("stock-pool-list").option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
514
+ const client = await createClient();
515
+ await printData(await client.call("vault.stock-pool.list", {}), parseOutputFormat(options.format), options.output);
516
+ });
517
+ vault.command("stock-pool-stocks").option("--pool-id <id>", "Pool ID; repeat for multiple; use 'all' for all pools", collectList, ["all"]).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
518
+ const client = await createClient();
519
+ await printData(await client.call("vault.stock-pool.stocks", { poolIdList: options.poolId }), parseOutputFormat(options.format), options.output);
520
+ });
510
521
  program.addCommand(vault);
511
522
  program.addCommand(ai);
523
+ const alternative = new Command("alternative").description("Alternative data APIs");
524
+ alternative.command("edb-search").requiredOption("--keyword <text>", "Search keyword (e.g. '空调')").option("--limit <number>", "Max results (default: 100, max: 200)", "100").option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
525
+ const client = await createClient();
526
+ await printData(await client.call("alternative.edb-search", {
527
+ keyword: options.keyword,
528
+ limit: parseNumberOption(options.limit, "--limit", { integer: true, min: 1 }),
529
+ }), parseOutputFormat(options.format), options.output);
530
+ });
531
+ alternative.command("edb-data").option("--indicator-id <id>", "Indicator ID (repeat, max 10)", collectList, []).requiredOption("--start-date <date>", "Start date (yyyy-MM-dd)").requiredOption("--end-date <date>", "End date (yyyy-MM-dd)").option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
532
+ const client = await createClient();
533
+ const raw = await client.call("alternative.edb-data", {
534
+ indicatorIdList: options.indicatorId,
535
+ startDate: options.startDate,
536
+ endDate: options.endDate,
537
+ });
538
+ let data = raw;
539
+ if (raw && Array.isArray(raw.fieldList) && Array.isArray(raw.dataList)) {
540
+ const list = raw.dataList.map((row) => raw.fieldList.reduce((acc, field, i) => {
541
+ acc[field] = row[i];
542
+ return acc;
543
+ }, {}));
544
+ data = { list, total: list.length };
545
+ }
546
+ await printData(data, parseOutputFormat(options.format), options.output);
547
+ });
548
+ program.addCommand(alternative);
512
549
  program.command("raw").description("Raw API calls").addCommand(new Command("call").argument("<endpointKey>").option("--body <json>").option("--query <key=value>", "Query string pair", collectKeyValue, {}).option("--format <format>", "Output format", "json").option("--output <path>").action(async (endpointKey, options) => {
513
550
  const endpoint = ENDPOINTS[endpointKey];
514
551
  if (!endpoint) {
@@ -15,6 +15,7 @@ export function buildWechatMessageListBody(options) {
15
15
  startTime: options.startTime,
16
16
  endTime: options.endTime,
17
17
  keyword: options.keyword,
18
+ securityList: maybeArray(options.security),
18
19
  wechatGroupIdList: maybeArray(options.wechatGroupId),
19
20
  industryIdList: maybeArray(options.industry),
20
21
  categoryList: maybeArray(options.category),
@@ -246,35 +246,56 @@ export const ENDPOINTS = {
246
246
  method: "POST",
247
247
  path: "/application/open-fundamental/financial-report/income-statement/accumulated",
248
248
  kind: "json",
249
- description: "Query income statement (accumulated)",
249
+ description: "Query A-share income statement (accumulated)",
250
250
  },
251
251
  "fundamental.income-statement-quarterly": {
252
252
  key: "fundamental.income-statement-quarterly",
253
253
  method: "POST",
254
254
  path: "/application/open-fundamental/financial-report/income-statement/quarterly",
255
255
  kind: "json",
256
- description: "Query income statement (quarterly)",
256
+ description: "Query A-share income statement (quarterly)",
257
257
  },
258
258
  "fundamental.balance-sheet": {
259
259
  key: "fundamental.balance-sheet",
260
260
  method: "POST",
261
261
  path: "/application/open-fundamental/financial-report/balance-sheet/accumulated",
262
262
  kind: "json",
263
- description: "Query balance sheet (accumulated)",
263
+ description: "Query A-share balance sheet (accumulated)",
264
264
  },
265
265
  "fundamental.cash-flow": {
266
266
  key: "fundamental.cash-flow",
267
267
  method: "POST",
268
268
  path: "/application/open-fundamental/financial-report/cash-flow-statement/accumulated",
269
269
  kind: "json",
270
- description: "Query cash flow statement (accumulated)",
270
+ description: "Query A-share cash flow statement (accumulated)",
271
271
  },
272
272
  "fundamental.cash-flow-quarterly": {
273
273
  key: "fundamental.cash-flow-quarterly",
274
274
  method: "POST",
275
275
  path: "/application/open-fundamental/financial-report/cash-flow-statement/quarterly",
276
276
  kind: "json",
277
- description: "Query cash flow statement (quarterly)",
277
+ description: "Query A-share cash flow statement (quarterly)",
278
+ },
279
+ "fundamental.income-statement-hk": {
280
+ key: "fundamental.income-statement-hk",
281
+ method: "POST",
282
+ path: "/application/open-fundamental/financial-report/income-statement/hk",
283
+ kind: "json",
284
+ description: "Query HK income statement (China GAAP)",
285
+ },
286
+ "fundamental.balance-sheet-hk": {
287
+ key: "fundamental.balance-sheet-hk",
288
+ method: "POST",
289
+ path: "/application/open-fundamental/financial-report/balance-sheet/hk",
290
+ kind: "json",
291
+ description: "Query HK balance sheet (China GAAP)",
292
+ },
293
+ "fundamental.cash-flow-hk": {
294
+ key: "fundamental.cash-flow-hk",
295
+ method: "POST",
296
+ path: "/application/open-fundamental/financial-report/cash-flow-statement/hk",
297
+ kind: "json",
298
+ description: "Query HK cash flow statement (China GAAP)",
278
299
  },
279
300
  "fundamental.main-business": {
280
301
  key: "fundamental.main-business",
@@ -473,4 +494,33 @@ export const ENDPOINTS = {
473
494
  kind: "json",
474
495
  description: "List WeChat group chatroom IDs",
475
496
  },
497
+ "vault.stock-pool.list": {
498
+ key: "vault.stock-pool.list",
499
+ method: "POST",
500
+ path: "/application/open-vault/stock-pool/getPoolList",
501
+ kind: "json",
502
+ description: "List user stock pool IDs and names",
503
+ },
504
+ "vault.stock-pool.stocks": {
505
+ key: "vault.stock-pool.stocks",
506
+ method: "POST",
507
+ path: "/application/open-vault/stock-pool/getStockList",
508
+ kind: "json",
509
+ description: "List securities in stock pool(s)",
510
+ },
511
+ // ─── alternative ───
512
+ "alternative.edb-search": {
513
+ key: "alternative.edb-search",
514
+ method: "POST",
515
+ path: "/application/open-alternative/EDB/search",
516
+ kind: "json",
517
+ description: "Search industry indicator list by keyword",
518
+ },
519
+ "alternative.edb-data": {
520
+ key: "alternative.edb-data",
521
+ method: "POST",
522
+ path: "/application/open-alternative/EDB/getData",
523
+ kind: "json",
524
+ description: "Get industry indicator time-series data by indicator ID list",
525
+ },
476
526
  };
@@ -1,2 +1,2 @@
1
1
  // Auto-generated — DO NOT EDIT
2
- export const CLI_VERSION = "0.12.0";
2
+ export const CLI_VERSION = "0.13.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gangtise-openapi-cli",
3
- "version": "0.12.0",
3
+ "version": "0.13.1",
4
4
  "description": "CLI for Gangtise OpenAPI",
5
5
  "license": "MIT",
6
6
  "repository": {