gangtise-openapi-cli 0.14.1 → 0.14.2

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,13 @@
4
4
 
5
5
  ## Changelog
6
6
 
7
+ ### v0.14.2 — 2026-05-22
8
+
9
+ **Bug fix(A 股 / HK 全市场 K 线同源问题)**
10
+ - `quote day-kline --security all` 由 2 天/片改为 **1 天/片**(A 股全市场单日约 5500 行)
11
+ - `quote day-kline-hk --security all` 由 3 天/片改为 **2 天/片**(港股全市场单日约 2770 行)
12
+ - 根治性修复:`callKlineWithSharding` 在 `--security all` 路径上,若用户未显式传 `--limit`,强制写入 `limit: 10000`(API 上限),不再走默认 6000——这样即便分片日数估算偏大,每个 shard 也能拿满 10K 行。用户自己传的 `--limit` 仍然保留生效。
13
+
7
14
  ### v0.14.1 — 2026-05-22
8
15
 
9
16
  **Bug fix**
@@ -279,7 +286,7 @@ gangtise ai knowledge-batch --query 比亚迪 --query 最近热门概念
279
286
  - **流式输出**:`jsonl`/`csv` 格式且 `--output` 指定时,超过 1000 行自动切换为逐行写盘,避免一次性构建百 MB 字符串。
280
287
  - **自动重试**:5xx / `ECONNRESET` / `ETIMEDOUT` / `999999` 系统错误自动指数退避重试 2 次。
281
288
  - **Token 自愈**:调用返回 8000014/8000015 时自动强制刷新 Token 并重试一次。
282
- - **K线自动分片**:`quote day-kline --security all` 等全市场查询自动按日期切分(A股 2 天/片、美股 1 天/片、HK 3 天/片、指数 30 天/片),并发执行后合并结果。
289
+ - **K线自动分片**:`quote day-kline --security all` 等全市场查询自动按日期切分(A股 1 天/片、美股 1 天/片、HK 2 天/片、指数 30 天/片),并发执行后合并结果。分片时如果用户未传 `--limit`,自动注入 `limit: 10000`(API 上限)避免默认 6000 截断。
283
290
  - **Token 内存缓存**:Token 在进程内存中缓存,避免每次请求读盘。
284
291
  - **`--verbose`**:打印每个请求的方法、路径、状态码、耗时和响应大小到 stderr,方便定位慢查询。
285
292
 
package/dist/src/cli.js CHANGED
@@ -278,11 +278,11 @@ program.addCommand(insight);
278
278
  const quote = new Command("quote").description("Quote APIs");
279
279
  quote.command("day-kline").option("--security <code>", "Security code (A-share: .SH/.SZ/.BJ, or 'all' for full market)", collectList, []).option("--start-date <date>", "Start date (default: 1 year before end-date)").option("--end-date <date>", "End date (default: latest)").option("--limit <number>", "Max rows per request (default: 6000, max: 10000)").option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
280
280
  const client = await createClient();
281
- await printData(await callKlineWithSharding(client, "quote.day-kline", buildQuoteKlineBody(options), { shardDays: 2 }), parseOutputFormat(options.format), options.output);
281
+ await printData(await callKlineWithSharding(client, "quote.day-kline", buildQuoteKlineBody(options), { shardDays: 1 }), parseOutputFormat(options.format), options.output);
282
282
  });
283
283
  quote.command("day-kline-hk").option("--security <code>", "Security code (HK stock: .HK, or 'all' for full market)", collectList, []).option("--start-date <date>", "Start date (default: 1 year before end-date)").option("--end-date <date>", "End date (default: latest)").option("--limit <number>", "Max rows per request (default: 6000, max: 10000)").option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
284
284
  const client = await createClient();
285
- await printData(await callKlineWithSharding(client, "quote.day-kline-hk", buildQuoteKlineBody(options), { shardDays: 3 }), parseOutputFormat(options.format), options.output);
285
+ await printData(await callKlineWithSharding(client, "quote.day-kline-hk", buildQuoteKlineBody(options), { shardDays: 2 }), parseOutputFormat(options.format), options.output);
286
286
  });
287
287
  quote.command("day-kline-us").option("--security <code>", "Security code (US stock: e.g. AAPL.O, or 'all' for full market)", collectList, []).option("--start-date <date>", "Start date (default: 1 year before end-date)").option("--end-date <date>", "End date (default: latest)").option("--limit <number>", "Max rows per request (default: 6000, max: 10000)").option("--field <field>", "Field", collectList, []).option("--format <format>", "Output format", "table").option("--output <path>").action(async (options) => {
288
288
  const client = await createClient();
@@ -1,5 +1,9 @@
1
1
  import { runWithConcurrency } from "./transport.js";
2
2
  const DAY_MS = 86_400_000;
3
+ /** API-side row cap (per docs). Used to lift the default 6000-row cap on
4
+ * `--security all` queries so a 2-day A-share shard (~11K rows) isn't
5
+ * silently truncated. Single-security queries are untouched. */
6
+ const ALL_MARKET_LIMIT = 10_000;
3
7
  function parseDate(value) {
4
8
  // Accept yyyy-MM-dd; reject anything else so we can fall back to a single request.
5
9
  if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
@@ -42,21 +46,24 @@ export async function callKlineWithSharding(client, endpointKey, body, config) {
42
46
  if (!isAllMarket(body) || !body.startDate || !body.endDate) {
43
47
  return client.call(endpointKey, body);
44
48
  }
49
+ // `--security all` returns thousands of rows per day; lift the default 6000-row
50
+ // cap to the API max so single-shard requests aren't silently truncated.
51
+ const allMarketBody = { ...body, limit: body.limit ?? ALL_MARKET_LIMIT };
45
52
  const start = parseDate(body.startDate);
46
53
  const end = parseDate(body.endDate);
47
54
  if (!start || !end || end < start) {
48
- return client.call(endpointKey, body);
55
+ return client.call(endpointKey, allMarketBody);
49
56
  }
50
57
  const totalDays = Math.floor((end.getTime() - start.getTime()) / DAY_MS) + 1;
51
58
  if (totalDays <= config.shardDays) {
52
- return client.call(endpointKey, body);
59
+ return client.call(endpointKey, allMarketBody);
53
60
  }
54
61
  const shards = buildShards(start, end, config.shardDays);
55
62
  if (process.env.GANGTISE_VERBOSE === "1" || process.env.GANGTISE_VERBOSE === "true") {
56
63
  process.stderr.write(`[gangtise] sharding ${endpointKey} into ${shards.length} requests (${config.shardDays} day(s) each)\n`);
57
64
  }
58
65
  const results = await runWithConcurrency(shards, config.concurrency ?? 5, async (shard) => {
59
- return client.call(endpointKey, { ...body, startDate: shard.startDate, endDate: shard.endDate });
66
+ return client.call(endpointKey, { ...allMarketBody, startDate: shard.startDate, endDate: shard.endDate });
60
67
  });
61
68
  let fieldList;
62
69
  let header = null;
@@ -1,2 +1,2 @@
1
1
  // Auto-generated — DO NOT EDIT
2
- export const CLI_VERSION = "0.14.1";
2
+ export const CLI_VERSION = "0.14.2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gangtise-openapi-cli",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "description": "CLI for Gangtise OpenAPI",
5
5
  "license": "MIT",
6
6
  "repository": {