@tigeropenapi/tigeropen 0.1.0 → 0.4.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.
Files changed (141) hide show
  1. package/README.md +475 -104
  2. package/dist/cjs/client/api-request.js +16 -10
  3. package/dist/cjs/client/api-response.js +23 -3
  4. package/dist/cjs/client/case-convert.js +35 -0
  5. package/dist/cjs/client/http-client.js +47 -21
  6. package/dist/cjs/client/index.js +6 -2
  7. package/dist/cjs/config/client-config.js +130 -49
  8. package/dist/cjs/config/domain.js +21 -2
  9. package/dist/cjs/config/index.js +3 -1
  10. package/dist/cjs/index.js +1 -1
  11. package/dist/cjs/model/contract.js +1 -2
  12. package/dist/cjs/model/enums.js +89 -7
  13. package/dist/cjs/model/order-helpers.js +9 -9
  14. package/dist/cjs/model/order-status.js +46 -0
  15. package/dist/cjs/model/order.js +5 -2
  16. package/dist/cjs/model/position.js +1 -2
  17. package/dist/cjs/model/quote-requests.js +11 -0
  18. package/dist/cjs/model/quote.js +7 -0
  19. package/dist/cjs/model/trade-requests.js +13 -0
  20. package/dist/cjs/model/trade.js +2 -0
  21. package/dist/cjs/push/index.js +6 -3
  22. package/dist/cjs/push/pb/AssetData.js +208 -0
  23. package/dist/cjs/push/pb/KlineData.js +184 -0
  24. package/dist/cjs/push/pb/OptionTopData.js +427 -0
  25. package/dist/cjs/push/pb/OrderStatusData.js +592 -0
  26. package/dist/cjs/push/pb/OrderTransactionData.js +256 -0
  27. package/dist/cjs/push/pb/PositionData.js +316 -0
  28. package/dist/cjs/push/pb/PushData.js +219 -0
  29. package/dist/cjs/push/pb/QuoteBBOData.js +160 -0
  30. package/dist/cjs/push/pb/QuoteBasicData.js +329 -0
  31. package/dist/cjs/push/pb/QuoteData.js +507 -0
  32. package/dist/cjs/push/pb/QuoteDepthData.js +220 -0
  33. package/dist/cjs/push/pb/Request.js +278 -0
  34. package/dist/cjs/push/pb/Response.js +97 -0
  35. package/dist/cjs/push/pb/SocketCommon.js +86 -0
  36. package/dist/cjs/push/pb/StockTopData.js +199 -0
  37. package/dist/cjs/push/pb/TickData.js +202 -0
  38. package/dist/cjs/push/pb/TradeTickData.js +308 -0
  39. package/dist/cjs/push/pb/index.js +49 -0
  40. package/dist/cjs/push/proto-message.js +135 -0
  41. package/dist/cjs/push/push-client.js +361 -163
  42. package/dist/cjs/push/push-message.js +8 -60
  43. package/dist/cjs/push/varint.js +76 -0
  44. package/dist/cjs/quote/index.js +3 -2
  45. package/dist/cjs/quote/quote-client.js +440 -94
  46. package/dist/cjs/signer/signer.js +10 -10
  47. package/dist/cjs/trade/trade-client.js +197 -62
  48. package/dist/esm/client/api-request.js +14 -8
  49. package/dist/esm/client/api-response.js +22 -3
  50. package/dist/esm/client/case-convert.js +31 -0
  51. package/dist/esm/client/http-client.js +48 -22
  52. package/dist/esm/client/index.js +3 -2
  53. package/dist/esm/config/client-config.js +131 -51
  54. package/dist/esm/config/domain.js +20 -2
  55. package/dist/esm/config/index.js +2 -2
  56. package/dist/esm/index.js +1 -1
  57. package/dist/esm/model/contract.js +1 -2
  58. package/dist/esm/model/enums.js +87 -6
  59. package/dist/esm/model/order-helpers.js +9 -9
  60. package/dist/esm/model/order-status.js +43 -0
  61. package/dist/esm/model/order.js +5 -2
  62. package/dist/esm/model/position.js +1 -2
  63. package/dist/esm/model/quote-requests.js +10 -0
  64. package/dist/esm/model/quote.js +6 -0
  65. package/dist/esm/model/trade-requests.js +12 -0
  66. package/dist/esm/model/trade.js +1 -0
  67. package/dist/esm/push/index.js +4 -2
  68. package/dist/esm/push/pb/AssetData.js +205 -0
  69. package/dist/esm/push/pb/KlineData.js +181 -0
  70. package/dist/esm/push/pb/OptionTopData.js +424 -0
  71. package/dist/esm/push/pb/OrderStatusData.js +589 -0
  72. package/dist/esm/push/pb/OrderTransactionData.js +253 -0
  73. package/dist/esm/push/pb/PositionData.js +313 -0
  74. package/dist/esm/push/pb/PushData.js +216 -0
  75. package/dist/esm/push/pb/QuoteBBOData.js +157 -0
  76. package/dist/esm/push/pb/QuoteBasicData.js +326 -0
  77. package/dist/esm/push/pb/QuoteData.js +504 -0
  78. package/dist/esm/push/pb/QuoteDepthData.js +217 -0
  79. package/dist/esm/push/pb/Request.js +275 -0
  80. package/dist/esm/push/pb/Response.js +94 -0
  81. package/dist/esm/push/pb/SocketCommon.js +83 -0
  82. package/dist/esm/push/pb/StockTopData.js +196 -0
  83. package/dist/esm/push/pb/TickData.js +199 -0
  84. package/dist/esm/push/pb/TradeTickData.js +305 -0
  85. package/dist/esm/push/pb/index.js +25 -0
  86. package/dist/esm/push/proto-message.js +127 -0
  87. package/dist/esm/push/push-client.js +329 -164
  88. package/dist/esm/push/push-message.js +7 -56
  89. package/dist/esm/push/varint.js +72 -0
  90. package/dist/esm/quote/index.js +2 -2
  91. package/dist/esm/quote/quote-client.js +439 -94
  92. package/dist/esm/signer/signer.js +10 -10
  93. package/dist/esm/trade/trade-client.js +197 -62
  94. package/dist/types/client/api-request.d.ts +12 -11
  95. package/dist/types/client/api-response.d.ts +15 -7
  96. package/dist/types/client/case-convert.d.ts +16 -0
  97. package/dist/types/client/http-client.d.ts +26 -14
  98. package/dist/types/client/index.d.ts +3 -2
  99. package/dist/types/config/client-config.d.ts +29 -13
  100. package/dist/types/config/domain.d.ts +9 -0
  101. package/dist/types/config/index.d.ts +2 -2
  102. package/dist/types/index.d.ts +1 -1
  103. package/dist/types/model/contract.d.ts +13 -29
  104. package/dist/types/model/enums.d.ts +60 -6
  105. package/dist/types/model/order-helpers.d.ts +21 -20
  106. package/dist/types/model/order-status.d.ts +14 -0
  107. package/dist/types/model/order.d.ts +101 -55
  108. package/dist/types/model/position.d.ts +26 -24
  109. package/dist/types/model/quote-requests.d.ts +344 -0
  110. package/dist/types/model/quote.d.ts +572 -0
  111. package/dist/types/model/trade-requests.d.ts +195 -0
  112. package/dist/types/model/trade.d.ts +235 -0
  113. package/dist/types/push/callbacks.d.ts +32 -51
  114. package/dist/types/push/index.d.ts +5 -3
  115. package/dist/types/push/pb/AssetData.d.ts +47 -0
  116. package/dist/types/push/pb/KlineData.d.ts +43 -0
  117. package/dist/types/push/pb/OptionTopData.d.ts +76 -0
  118. package/dist/types/push/pb/OrderStatusData.d.ts +100 -0
  119. package/dist/types/push/pb/OrderTransactionData.d.ts +51 -0
  120. package/dist/types/push/pb/PositionData.d.ts +63 -0
  121. package/dist/types/push/pb/PushData.d.ts +46 -0
  122. package/dist/types/push/pb/QuoteBBOData.d.ts +35 -0
  123. package/dist/types/push/pb/QuoteBasicData.d.ts +66 -0
  124. package/dist/types/push/pb/QuoteData.d.ts +94 -0
  125. package/dist/types/push/pb/QuoteDepthData.d.ts +37 -0
  126. package/dist/types/push/pb/Request.d.ts +44 -0
  127. package/dist/types/push/pb/Response.d.ts +30 -0
  128. package/dist/types/push/pb/SocketCommon.d.ts +64 -0
  129. package/dist/types/push/pb/StockTopData.d.ts +37 -0
  130. package/dist/types/push/pb/TickData.d.ts +44 -0
  131. package/dist/types/push/pb/TradeTickData.d.ts +53 -0
  132. package/dist/types/push/pb/index.d.ts +39 -0
  133. package/dist/types/push/proto-message.d.ts +33 -0
  134. package/dist/types/push/push-client.d.ts +100 -68
  135. package/dist/types/push/push-message.d.ts +7 -147
  136. package/dist/types/push/varint.d.ts +23 -0
  137. package/dist/types/quote/index.d.ts +2 -2
  138. package/dist/types/quote/quote-client.d.ts +154 -47
  139. package/dist/types/signer/signer.d.ts +6 -6
  140. package/dist/types/trade/trade-client.d.ts +106 -38
  141. package/package.json +11 -6
@@ -1,106 +1,451 @@
1
1
  import { createApiRequest } from '../client/api-request';
2
+ import { unmarshalData } from '../client/api-response';
2
3
  /**
3
- * 行情查询客户端,封装所有行情相关 API。
4
+ * Parse an OCC-style option identifier like "AAPL 260619C00150000"
5
+ * into its component parts.
4
6
  */
7
+ export function parseOptionIdentifier(identifier) {
8
+ const trimmed = identifier.trim();
9
+ const spaceIdx = trimmed.indexOf(' ');
10
+ if (spaceIdx === -1) {
11
+ throw new Error(`invalid option identifier: ${identifier}`);
12
+ }
13
+ const symbol = trimmed.substring(0, spaceIdx);
14
+ const rest = trimmed.substring(spaceIdx + 1).trim();
15
+ if (rest.length < 15) {
16
+ throw new Error(`option code too short: ${rest}`);
17
+ }
18
+ const datePart = rest.substring(0, 6);
19
+ const rightChar = rest.substring(6, 7);
20
+ const strikePart = rest.substring(7);
21
+ const yy = parseInt(datePart.substring(0, 2), 10);
22
+ const mm = parseInt(datePart.substring(2, 4), 10);
23
+ const dd = parseInt(datePart.substring(4, 6), 10);
24
+ const expiryMs = Date.UTC(2000 + yy, mm - 1, dd);
25
+ const right = rightChar === 'C' ? 'CALL' : rightChar === 'P' ? 'PUT' : '';
26
+ if (!right)
27
+ throw new Error(`invalid right character: ${rightChar}`);
28
+ const strikeInt = parseInt(strikePart, 10);
29
+ if (Number.isNaN(strikeInt))
30
+ throw new Error(`invalid strike digits: ${strikePart}`);
31
+ const strike = strikeInt / 1000;
32
+ return { symbol, expiryMs, right, strike };
33
+ }
34
+ /** Market data client wrapping all quote-related APIs. */
5
35
  export class QuoteClient {
6
36
  constructor(httpClient) {
7
37
  this.httpClient = httpClient;
8
38
  }
39
+ async callInto(method, bizParams, version) {
40
+ const request = createApiRequest(method, bizParams, version);
41
+ const response = await this.httpClient.executeRequest(request);
42
+ return unmarshalData(response.data);
43
+ }
9
44
  /**
10
- * 内部通用方法:构造请求、发送、返回 data 字段
45
+ * Some endpoints return either a list or a single object depending on the
46
+ * server response shape (future_contract_by_contract_code /
47
+ * future_continuous_contracts). Unify into an array.
11
48
  */
12
- async execute(method, bizParams) {
13
- const request = createApiRequest(method, bizParams);
14
- const response = await this.httpClient.executeRequest(request);
15
- return response.data;
16
- }
17
- // === 基础行情方法 ===
18
- /** 获取市场状态 */
19
- async marketState(market) {
20
- return this.execute('market_state', { market });
21
- }
22
- /** 获取实时报价 */
23
- async quoteRealTime(symbols) {
24
- return this.execute('quote_real_time', { symbols });
25
- }
26
- /** 获取 K 线数据 */
27
- async kline(symbol, period) {
28
- return this.execute('kline', { symbols: [symbol], period });
29
- }
30
- /** 获取分时数据 */
31
- async timeline(symbols) {
32
- return this.execute('timeline', { symbols });
33
- }
34
- /** 获取逐笔成交数据 */
35
- async tradeTick(symbols) {
36
- return this.execute('trade_tick', { symbols });
37
- }
38
- /** 获取深度行情 */
39
- async quoteDepth(symbol) {
40
- return this.execute('quote_depth', { symbol });
41
- }
42
- // === 期权行情方法 ===
43
- /** 获取期权到期日 */
44
- async optionExpiration(symbol) {
45
- return this.execute('option_expiration', { symbols: [symbol] });
46
- }
47
- /** 获取期权链 */
48
- async optionChain(symbol, expiry) {
49
- return this.execute('option_chain', { symbol, expiry });
50
- }
51
- /** 获取期权报价 */
52
- async optionBrief(identifiers) {
53
- return this.execute('option_brief', { identifiers });
54
- }
55
- /** 获取期权 K 线 */
56
- async optionKline(identifier, period) {
57
- return this.execute('option_kline', { identifier, period });
58
- }
59
- // === 期货行情方法 ===
60
- /** 获取期货交易所列表 */
61
- async futureExchange() {
62
- return this.execute('future_exchange', { sec_type: 'FUT' });
63
- }
64
- /** 获取期货合约列表 */
65
- async futureContracts(exchange) {
66
- return this.execute('future_contracts', { exchange });
67
- }
68
- /** 获取期货实时报价 */
69
- async futureRealTimeQuote(symbols) {
70
- return this.execute('future_real_time_quote', { symbols });
71
- }
72
- /** 获取期货 K 线 */
73
- async futureKline(symbol, period) {
74
- return this.execute('future_kline', { symbol, period });
75
- }
76
- // === 基本面和资金流向方法 ===
77
- /** 获取财务日报 */
78
- async financialDaily(symbol) {
79
- return this.execute('financial_daily', { symbol });
80
- }
81
- /** 获取财务报告 */
82
- async financialReport(symbol) {
83
- return this.execute('financial_report', { symbol });
84
- }
85
- /** 获取公司行动 */
86
- async corporateAction(symbol) {
87
- return this.execute('corporate_action', { symbol });
88
- }
89
- /** 获取资金流向 */
90
- async capitalFlow(symbol) {
91
- return this.execute('capital_flow', { symbol });
92
- }
93
- /** 获取资金分布 */
94
- async capitalDistribution(symbol) {
95
- return this.execute('capital_distribution', { symbol });
96
- }
97
- // === 选股器和行情权限方法 ===
98
- /** 选股器 */
99
- async marketScanner(params) {
100
- return this.execute('market_scanner', params);
101
- }
102
- /** 获取行情权限 */
49
+ async callIntoListOrObject(method, bizParams, version) {
50
+ const raw = await this.callInto(method, bizParams, version);
51
+ if (raw == null)
52
+ return [];
53
+ if (Array.isArray(raw))
54
+ return raw;
55
+ return [raw];
56
+ }
57
+ /** Unwrap server {"items":[...]} envelope. */
58
+ async callIntoItems(method, bizParams, version) {
59
+ const wrap = await this.callInto(method, bizParams, version);
60
+ return wrap?.items ?? [];
61
+ }
62
+ // === Basic market data ===
63
+ async getMarketState(market) {
64
+ return this.callInto('market_state', { market });
65
+ }
66
+ /** Real-time stock briefs. wire: quote_real_time */
67
+ async getBrief(req) {
68
+ return this.callInto('quote_real_time', req);
69
+ }
70
+ async getKline(symbol, period) {
71
+ return this.callInto('kline', { symbols: [symbol], period });
72
+ }
73
+ async getTimeline(symbols) {
74
+ return this.callInto('timeline', { symbols });
75
+ }
76
+ /** Tick-by-tick trades. wire: trade_tick */
77
+ async getTradeTick(req) {
78
+ return this.callInto('trade_tick', req);
79
+ }
80
+ /** Depth snapshot. wire: quote_depth */
81
+ async getQuoteDepth(req) {
82
+ return this.callInto('quote_depth', req);
83
+ }
84
+ // === Options ===
85
+ async getOptionExpiration(symbol) {
86
+ return this.callInto('option_expiration', { symbols: [symbol] });
87
+ }
88
+ /** Option chain; `expiry` is "YYYY-MM-DD". */
89
+ async getOptionChain(symbol, expiry) {
90
+ const d = new Date(expiry + 'T00:00:00Z');
91
+ const expiryMs = d.getTime();
92
+ if (Number.isNaN(expiryMs)) {
93
+ throw new Error(`invalid expiry date, expected YYYY-MM-DD: ${expiry}`);
94
+ }
95
+ return this.callInto('option_chain', { option_basic: [{ symbol, expiry: expiryMs }] }, '3.0');
96
+ }
97
+ async getOptionBrief(identifiers) {
98
+ const optionBasic = identifiers.map((id) => {
99
+ const p = parseOptionIdentifier(id);
100
+ return { symbol: p.symbol, expiry: p.expiryMs, right: p.right, strike: p.strike };
101
+ });
102
+ return this.callInto('option_brief', { option_basic: optionBasic }, '2.0');
103
+ }
104
+ async getOptionKline(identifier, period) {
105
+ const p = parseOptionIdentifier(identifier);
106
+ return this.callInto('option_kline', {
107
+ option_query: [{ symbol: p.symbol, expiry: p.expiryMs, right: p.right, strike: p.strike, period }],
108
+ }, '2.0');
109
+ }
110
+ // === Futures ===
111
+ async getFutureExchange() {
112
+ return this.callInto('future_exchange', { secType: 'FUT' });
113
+ }
114
+ async getFutureContracts(exchange) {
115
+ return this.callInto('future_contract_by_exchange_code', { exchangeCode: exchange });
116
+ }
117
+ /** Real-time futures quotes. wire: future_real_time_quote */
118
+ async getFutureRealTimeQuote(req) {
119
+ return this.callInto('future_real_time_quote', req);
120
+ }
121
+ /** Futures K-line; use -1 for unbounded beginTime / endTime. */
122
+ async getFutureKline(req) {
123
+ const body = {
124
+ ...req,
125
+ beginTime: req.beginTime ?? -1,
126
+ endTime: req.endTime ?? -1,
127
+ };
128
+ return this.callInto('future_kline', body);
129
+ }
130
+ // === Fundamentals ===
131
+ async getFinancialDaily(req) {
132
+ return this.callInto('financial_daily', req);
133
+ }
134
+ async getFinancialReport(req) {
135
+ return this.callInto('financial_report', req);
136
+ }
137
+ /**
138
+ * Corporate actions. Server returns {symbol: [...]}, this method flattens into a single list.
139
+ */
140
+ async getCorporateAction(req) {
141
+ const grouped = await this.callInto('corporate_action', req);
142
+ if (!grouped || typeof grouped !== 'object')
143
+ return [];
144
+ return Object.values(grouped).flat();
145
+ }
146
+ // === Capital flow ===
147
+ async getCapitalFlow(symbol, market, period) {
148
+ return this.callInto('capital_flow', { symbol, market, period });
149
+ }
150
+ async getCapitalDistribution(symbol, market) {
151
+ return this.callInto('capital_distribution', { symbol, market });
152
+ }
153
+ // === Scanner & permission ===
154
+ async marketScanner(req) {
155
+ return this.callInto('market_scanner', req);
156
+ }
103
157
  async grabQuotePermission() {
104
- return this.execute('grab_quote_permission');
158
+ return this.callInto('grab_quote_permission');
159
+ }
160
+ // ==========================================================================
161
+ // Batch 3: stock basics + time series
162
+ // ==========================================================================
163
+ /** All symbol codes (string list). wire: all_symbols */
164
+ async getSymbols(req) {
165
+ return this.callInto('all_symbols', req);
166
+ }
167
+ /** All symbols with names. wire: all_symbol_names */
168
+ async getSymbolNames(req) {
169
+ return this.callInto('all_symbol_names', req);
170
+ }
171
+ /** Trade meta (lot size / tick size). wire: quote_stock_trade */
172
+ async getTradeMetas(req) {
173
+ return this.callInto('quote_stock_trade', req);
174
+ }
175
+ /** Stock details. wire: stock_detail. Server returns {items:[...]}. */
176
+ async getStockDetails(req) {
177
+ return this.callIntoItems('stock_detail', req);
178
+ }
179
+ /** Delayed stock briefs. wire: quote_delay */
180
+ async getStockDelayBriefs(req) {
181
+ return this.callInto('quote_delay', req);
182
+ }
183
+ /** K-line bars (full request). wire: kline */
184
+ async getBars(req) {
185
+ return this.callInto('kline', req);
186
+ }
187
+ /**
188
+ * Client-side paginated K-line fetch — loops over getBars until TotalSize
189
+ * bars are collected. Items are returned oldest-first, matching
190
+ * Python/Go get_bars_by_page behaviour.
191
+ */
192
+ async getBarsByPage(req) {
193
+ const pageSize = req.pageSize && req.pageSize > 0 ? req.pageSize : 200;
194
+ const totalSize = req.totalSize && req.totalSize > 0 ? req.totalSize : 1000;
195
+ let beginTime = req.beginTime ?? -1;
196
+ let endTime = req.endTime ?? -1;
197
+ if (beginTime === 0)
198
+ beginTime = -1;
199
+ if (endTime === 0)
200
+ endTime = -1;
201
+ const acc = [];
202
+ while (acc.length < totalSize) {
203
+ const sub = {
204
+ symbols: req.symbol ? [req.symbol] : undefined,
205
+ period: req.period,
206
+ right: req.right,
207
+ beginTime,
208
+ endTime,
209
+ limit: pageSize,
210
+ tradeSession: req.tradeSession,
211
+ lang: req.lang,
212
+ };
213
+ const pageOut = await this.callInto('kline', sub);
214
+ if (!pageOut || pageOut.length === 0 || !pageOut[0].items || pageOut[0].items.length === 0) {
215
+ break;
216
+ }
217
+ const items = pageOut[0].items;
218
+ acc.push(...items);
219
+ if (items.length < pageSize)
220
+ break;
221
+ // next page endTime = oldest bar time - 1
222
+ let oldest = items[0].time;
223
+ for (const it of items) {
224
+ if (it.time < oldest)
225
+ oldest = it.time;
226
+ }
227
+ endTime = oldest - 1;
228
+ }
229
+ return acc;
230
+ }
231
+ /** Historical intraday timeline. wire: history_timeline */
232
+ async getTimelineHistory(req) {
233
+ return this.callInto('history_timeline', req);
234
+ }
235
+ /** Trade rank (top movers / volume). wire: trade_rank */
236
+ async getTradeRank(req) {
237
+ return this.callInto('trade_rank', req);
238
+ }
239
+ /** Short interest / shortable. wire: quote_shortable_stocks */
240
+ async getShortInterest(req) {
241
+ return this.callInto('quote_shortable_stocks', req);
242
+ }
243
+ /** Broker queue. wire: stock_broker */
244
+ async getStockBroker(req) {
245
+ return this.callInto('stock_broker', req);
246
+ }
247
+ /** Stock fundamentals (server returns grouped map). wire: stock_fundamental */
248
+ async getStockFundamental(req) {
249
+ const out = await this.callInto('stock_fundamental', req);
250
+ return out ?? {};
251
+ }
252
+ /** Stock industry classification (array). wire: stock_industry */
253
+ async getStockIndustry(req) {
254
+ return this.callInto('stock_industry', req);
255
+ }
256
+ /** Quote permission detail. wire: get_quote_permission */
257
+ async getQuotePermission(req) {
258
+ return this.callInto('get_quote_permission', req);
259
+ }
260
+ /** K-line quota usage. wire: kline_quota */
261
+ async getKlineQuota(req) {
262
+ return this.callInto('kline_quota', req);
263
+ }
264
+ // ==========================================================================
265
+ // Batch 4: option / future extensions
266
+ // ==========================================================================
267
+ /** Option K-line. wire: option_kline (v2.0) */
268
+ async getOptionBars(req) {
269
+ return this.callInto('option_kline', req, '2.0');
270
+ }
271
+ /** Option tick trades. wire: option_trade_tick */
272
+ async getOptionTradeTicks(req) {
273
+ return this.callInto('option_trade_tick', req);
274
+ }
275
+ /** Option intraday timeline. wire: option_timeline */
276
+ async getOptionTimeline(req) {
277
+ return this.callInto('option_timeline', req);
278
+ }
279
+ /** Option depth. wire: option_depth */
280
+ async getOptionDepth(req) {
281
+ return this.callInto('option_depth', req);
282
+ }
283
+ /** Available option symbols. wire: option_symbol */
284
+ async getOptionSymbols(req) {
285
+ return this.callInto('option_symbol', req);
286
+ }
287
+ /** Option analysis (volatility). wire: option_analysis */
288
+ async getOptionAnalysis(req) {
289
+ return this.callInto('option_analysis', req);
290
+ }
291
+ /** Single futures contract by code. wire: future_contract_by_contract_code */
292
+ async getFutureContract(req) {
293
+ return this.callIntoListOrObject('future_contract_by_contract_code', req);
294
+ }
295
+ /** All futures contracts. wire: future_contracts */
296
+ async getAllFutureContracts(req) {
297
+ return this.callInto('future_contracts', req);
298
+ }
299
+ /** Current main contract. wire: future_current_contract */
300
+ async getCurrentFutureContract(req) {
301
+ return this.callInto('future_current_contract', req);
302
+ }
303
+ /** Continuous main contracts. wire: future_continuous_contracts */
304
+ async getFutureContinuousContracts(req) {
305
+ return this.callIntoListOrObject('future_continuous_contracts', req);
306
+ }
307
+ /** Historical main contracts. wire: future_main_contract */
308
+ async getFutureHistoryMainContract(req) {
309
+ return this.callInto('future_main_contract', req);
310
+ }
311
+ /**
312
+ * Futures K-line (full request with index pagination). wire: future_kline
313
+ * begin_time / end_time default to -1 when unset (server requires them present).
314
+ */
315
+ async getFutureBars(req) {
316
+ const body = {
317
+ ...req,
318
+ beginTime: req.beginTime ?? -1,
319
+ endTime: req.endTime ?? -1,
320
+ };
321
+ return this.callInto('future_kline', body);
322
+ }
323
+ /** Client-side paginated futures K-line fetch. */
324
+ async getFutureBarsByPage(req) {
325
+ const pageSize = req.pageSize && req.pageSize > 0 ? req.pageSize : 200;
326
+ const totalSize = req.totalSize && req.totalSize > 0 ? req.totalSize : 1000;
327
+ let beginTime = req.beginTime ?? -1;
328
+ let endTime = req.endTime ?? -1;
329
+ if (beginTime === 0)
330
+ beginTime = -1;
331
+ if (endTime === 0)
332
+ endTime = -1;
333
+ const acc = [];
334
+ while (acc.length < totalSize) {
335
+ const sub = {
336
+ contractCode: req.contractCode,
337
+ period: req.period,
338
+ beginTime,
339
+ endTime,
340
+ limit: pageSize,
341
+ lang: req.lang,
342
+ };
343
+ const pageOut = await this.callInto('future_kline', sub);
344
+ if (!pageOut || pageOut.length === 0 || !pageOut[0].items || pageOut[0].items.length === 0) {
345
+ break;
346
+ }
347
+ const items = pageOut[0].items;
348
+ acc.push(...items);
349
+ if (items.length < pageSize)
350
+ break;
351
+ let oldest = items[0].time;
352
+ for (const it of items) {
353
+ if (it.time < oldest)
354
+ oldest = it.time;
355
+ }
356
+ endTime = oldest - 1;
357
+ }
358
+ return acc;
359
+ }
360
+ /** Futures tick trades. wire: future_tick (API v3.0) */
361
+ async getFutureTradeTicks(req) {
362
+ return this.callInto('future_tick', req, '3.0');
363
+ }
364
+ /** Futures depth. wire: future_depth */
365
+ async getFutureDepth(req) {
366
+ return this.callInto('future_depth', req);
367
+ }
368
+ /** Futures trading times (single-object response). wire: future_trading_date */
369
+ async getFutureTradingTimes(req) {
370
+ return this.callInto('future_trading_date', req);
371
+ }
372
+ // ==========================================================================
373
+ // Batch 5: fund / warrant / industry / corporate / financial / calendar
374
+ // ==========================================================================
375
+ /** Fund symbols. wire: fund_all_symbols */
376
+ async getFundSymbols(req) {
377
+ return this.callInto('fund_all_symbols', req);
378
+ }
379
+ /** Fund contracts. wire: fund_contracts */
380
+ async getFundContracts(req) {
381
+ return this.callInto('fund_contracts', req);
382
+ }
383
+ /** Fund real-time NAV. wire: fund_quote */
384
+ async getFundQuote(req) {
385
+ return this.callInto('fund_quote', req);
386
+ }
387
+ /** Fund historical NAV. wire: fund_history_quote */
388
+ async getFundHistoryQuote(req) {
389
+ return this.callInto('fund_history_quote', req);
390
+ }
391
+ /** Warrant briefs. wire: warrant_briefs */
392
+ async getWarrantBriefs(req) {
393
+ return this.callInto('warrant_briefs', req);
394
+ }
395
+ /** Warrant filter (paged). wire: warrant_filter */
396
+ async getWarrantFilter(req) {
397
+ return this.callInto('warrant_filter', req);
398
+ }
399
+ /** Industry list. wire: industry_list */
400
+ async getIndustryList(req) {
401
+ return this.callInto('industry_list', req);
402
+ }
403
+ /** Stocks inside an industry. wire: industry_stock_list */
404
+ async getIndustryStocks(req) {
405
+ return this.callInto('industry_stock_list', req);
406
+ }
407
+ /** Corporate split (flattened). wire: corporate_action (action_type=split) */
408
+ async getCorporateSplit(req) {
409
+ const body = { ...req, actionType: 'split' };
410
+ const grouped = await this.callInto('corporate_action', body);
411
+ if (!grouped || typeof grouped !== 'object')
412
+ return [];
413
+ return Object.values(grouped).flat();
414
+ }
415
+ /** Corporate dividend (flattened). wire: corporate_action (action_type=dividend) */
416
+ async getCorporateDividend(req) {
417
+ const body = { ...req, actionType: 'dividend' };
418
+ const grouped = await this.callInto('corporate_action', body);
419
+ if (!grouped || typeof grouped !== 'object')
420
+ return [];
421
+ return Object.values(grouped).flat();
422
+ }
423
+ /** Corporate earnings calendar (flattened). wire: corporate_action (action_type=earning) */
424
+ async getCorporateEarningsCalendar(req) {
425
+ const body = { ...req, actionType: 'earning' };
426
+ const grouped = await this.callInto('corporate_action', body);
427
+ if (!grouped || typeof grouped !== 'object')
428
+ return [];
429
+ return Object.values(grouped).flat();
430
+ }
431
+ /** Financial currency per symbol. wire: financial_currency */
432
+ async getFinancialCurrency(req) {
433
+ return this.callInto('financial_currency', req);
434
+ }
435
+ /** FX rates. wire: financial_exchange_rate */
436
+ async getFinancialExchangeRate(req) {
437
+ return this.callInto('financial_exchange_rate', req);
438
+ }
439
+ /** Trading calendar. wire: trading_calendar */
440
+ async getTradingCalendar(req) {
441
+ return this.callInto('trading_calendar', req);
442
+ }
443
+ /** Available market-scanner tags. wire: market_scanner_tags */
444
+ async getMarketScannerTags(req) {
445
+ return this.callInto('market_scanner_tags', req);
446
+ }
447
+ /** Overnight quote. wire: quote_overnight */
448
+ async getQuoteOvernight(req) {
449
+ return this.callInto('quote_overnight', req);
105
450
  }
106
451
  }
@@ -73,16 +73,16 @@ export function signWithRSA(privateKeyStr, content) {
73
73
  return sign.sign(key, 'base64');
74
74
  }
75
75
  /**
76
- * 使用 RSA 公钥验证 SHA1WithRSA 签名。
76
+ * Verify a SHA1WithRSA signature using an RSA public key.
77
77
  *
78
- * @param publicKey - 公钥对象
79
- * @param content - 原始内容
80
- * @param signature - Base64 编码的签名字符串
81
- * @returns 验签是否成功
78
+ * @param publicKeyBase64 - Base64-encoded public key (DER / PKCS#1 or SPKI)
79
+ * @param content - Original content that was signed
80
+ * @param signatureBase64 - Base64-encoded signature
81
+ * @returns Whether the signature is valid
82
82
  */
83
- export function verifyWithRSA(publicKey, content, signature) {
84
- const verify = createVerify('SHA1');
85
- verify.update(content);
86
- verify.end();
87
- return verify.verify(publicKey, signature, 'base64');
83
+ export function verifyWithRSA(publicKeyBase64, content, signatureBase64) {
84
+ const pem = `-----BEGIN PUBLIC KEY-----\n${publicKeyBase64}\n-----END PUBLIC KEY-----`;
85
+ const verifier = createVerify('SHA1');
86
+ verifier.update(content);
87
+ return verifier.verify(pem, signatureBase64, 'base64');
88
88
  }