@tigeropenapi/tigeropen 0.5.3 → 0.5.5

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.
@@ -0,0 +1,165 @@
1
+ const PART_CODE_NAME_MAP = {
2
+ a: 'NYSE American, LLC (NYSE American)',
3
+ b: 'NASDAQ OMX BX, Inc. (NASDAQ OMX BX)',
4
+ c: 'NYSE National, Inc. (NYSE National)',
5
+ d: 'FINRA Alternative Display Facility (ADF)',
6
+ h: 'MIAX Pearl Exchange, LLC (MIAX)',
7
+ i: 'International Securities Exchange, LLC (ISE)',
8
+ j: 'Cboe EDGA Exchange, Inc. (Cboe EDGA)',
9
+ k: 'Cboe EDGX Exchange, Inc. (Cboe EDGX)',
10
+ l: 'Long-Term Stock Exchange, Inc. (LTSE)',
11
+ m: 'NYSE Chicago, Inc. (NYSE Chicago)',
12
+ n: 'New York Stock Exchange, LLC (NYSE)',
13
+ p: 'NYSE Arca, Inc. (NYSE Arca)',
14
+ s: 'Consolidated Tape System (CTS)',
15
+ t: 'NASDAQ Stock Market, LLC (NASDAQ)',
16
+ u: 'Members Exchange, LLC (MEMX)',
17
+ v: "Investors' Exchange, LLC. (IEX)",
18
+ w: 'CBOE Stock Exchange, Inc. (CBSX)',
19
+ x: 'NASDAQ OMX PSX, Inc. (NASDAQ OMX PSX)',
20
+ y: 'Cboe BYX Exchange, Inc. (Cboe BYX)',
21
+ z: 'Cboe BZX Exchange, Inc. (Cboe BZX)',
22
+ };
23
+ const PART_CODE_SHORT_NAME_MAP = {
24
+ a: 'AMEX',
25
+ b: 'BX',
26
+ c: 'NSX',
27
+ d: 'ADF',
28
+ h: 'MIAX',
29
+ i: 'ISE',
30
+ j: 'EDGA',
31
+ k: 'EDGX',
32
+ l: 'LTSE',
33
+ m: 'CHO',
34
+ n: 'NYSE',
35
+ p: 'ARCA',
36
+ s: 'CTS',
37
+ t: 'NSDQ',
38
+ u: 'MEMX',
39
+ v: 'IEX',
40
+ w: 'CBSX',
41
+ x: 'PSX',
42
+ y: 'BYX',
43
+ z: 'BZX',
44
+ };
45
+ const US_TRADE_COND = {
46
+ ' ': 'US_REGULAR_SALE',
47
+ B: 'US_BUNCHED_TRADE',
48
+ C: 'US_CASH_TRADE',
49
+ F: 'US_INTERMARKET_SWEEP',
50
+ G: 'US_BUNCHED_SOLD_TRADE',
51
+ H: 'US_PRICE_VARIATION_TRADE',
52
+ I: 'US_ODD_LOT_TRADE',
53
+ K: 'US_RULE_127_OR_155_TRADE',
54
+ L: 'US_SOLD_LAST',
55
+ M: 'US_MARKET_CENTER_CLOSE_PRICE',
56
+ N: 'US_NEXT_DAY_TRADE',
57
+ O: 'US_MARKET_CENTER_OPENING_TRADE',
58
+ P: 'US_PRIOR_REFERENCE_PRICE',
59
+ Q: 'US_MARKET_CENTER_OPEN_PRICE',
60
+ R: 'US_SELLER',
61
+ T: 'US_FORM_T',
62
+ U: 'US_EXTENDED_TRADING_HOURS',
63
+ V: 'US_CONTINGENT_TRADE',
64
+ W: 'US_AVERAGE_PRICE_TRADE',
65
+ X: 'US_CROSS_TRADE',
66
+ Z: 'US_SOLD_OUT_OF_SEQUENCE',
67
+ '0': 'US_ODD_LOST_CROSS_TRADE',
68
+ '4': 'US_DERIVATIVELY_PRICED',
69
+ '5': 'US_MARKET_CENTER_RE_OPENING_TRADE',
70
+ '6': 'US_MARKET_CENTER_CLOSING_TRADE',
71
+ '7': 'US_QUALIFIED_CONTINGENT_TRADE',
72
+ '9': 'US_CONSOLIDATED_LAST_PRICE_PER_LISTING_PACKET',
73
+ };
74
+ const HK_TRADE_COND = {
75
+ ' ': 'HK_AUTOMATCH_NORMAL',
76
+ D: 'HK_ODD_LOT_TRADE',
77
+ U: 'HK_AUCTION_TRADE',
78
+ '*': 'HK_OVERSEAS_TRADE',
79
+ P: 'HK_LATE_TRADE_OFF_EXCHG',
80
+ M: 'HK_NON_DIRECT_OFF_EXCHG_TRADE',
81
+ X: 'HK_DIRECT_OFF_EXCHG_TRADE',
82
+ Y: 'HK_AUTOMATIC_INTERNALIZED',
83
+ };
84
+ /** Returns the full exchange name for a partCode letter, or the raw code if unknown. */
85
+ export function getPartNameByCode(code) {
86
+ if (!code)
87
+ return code;
88
+ return PART_CODE_NAME_MAP[code] ?? code;
89
+ }
90
+ /** Returns the short exchange name for a partCode letter, or the raw code if unknown. */
91
+ export function getPartShortNameByCode(code) {
92
+ if (!code)
93
+ return code;
94
+ return PART_CODE_SHORT_NAME_MAP[code] ?? code;
95
+ }
96
+ /** Resolves a raw cond character to a readable string. */
97
+ export function getTradeCondByCode(isUs, ch) {
98
+ const map = isUs ? US_TRADE_COND : HK_TRADE_COND;
99
+ return map[ch] ?? ch;
100
+ }
101
+ const US_SYMBOL_RE = /^[A-Z]+(\.[A-Z0-9]+)?$/;
102
+ /** Reports whether symbol is a US stock (uppercase letters, optional dot suffix). */
103
+ export function isUsStockSymbol(symbol) {
104
+ return US_SYMBOL_RE.test(symbol);
105
+ }
106
+ function isUsSymbol(symbol) {
107
+ return US_SYMBOL_RE.test(symbol);
108
+ }
109
+ function getTradeCond(isUs, ch) {
110
+ const map = isUs ? US_TRADE_COND : HK_TRADE_COND;
111
+ return map[ch] ?? ch;
112
+ }
113
+ /** Decodes a TradeTickData pb message into a PushTradeTick with resolved partCode/partName. */
114
+ export function convertTradeTick(src) {
115
+ if (src.secType === 'FUT')
116
+ return convertFutureTick(src);
117
+ return convertStockTick(src);
118
+ }
119
+ function convertStockTick(src) {
120
+ const isUs = isUsSymbol(src.symbol);
121
+ const denominator = Math.pow(10, src.priceOffset);
122
+ const ticks = [];
123
+ let currentTime = 0;
124
+ for (let i = 0; i < src.time.length; i++) {
125
+ currentTime += src.time[i];
126
+ const condCh = src.cond.length > i ? src.cond[i] : ' ';
127
+ const rawCode = i < src.partCode.length ? src.partCode[i] : '';
128
+ ticks.push({
129
+ sn: src.sn + i,
130
+ time: currentTime,
131
+ price: (src.priceBase + src.price[i]) / denominator,
132
+ volume: src.volume[i],
133
+ tickType: src.type.length > i ? src.type[i] : '',
134
+ cond: getTradeCond(isUs, condCh),
135
+ partCode: getPartShortNameByCode(rawCode),
136
+ partName: getPartNameByCode(rawCode),
137
+ });
138
+ }
139
+ return { symbol: src.symbol, secType: src.secType, quoteLevel: src.quoteLevel, timestamp: src.timestamp, ticks };
140
+ }
141
+ function convertFutureTick(src) {
142
+ const denominator = Math.pow(10, src.priceOffset);
143
+ const ticks = [];
144
+ let currentTime = 0;
145
+ let startSn = src.sn;
146
+ for (let i = 0; i < src.time.length; i++) {
147
+ currentTime += src.time[i];
148
+ const curPrice = (src.priceBase + src.price[i]) / denominator;
149
+ const mv = src.mergedVols[i];
150
+ for (let j = 0; j < mv.vol.length; j++) {
151
+ ticks.push({
152
+ sn: startSn * 10 + j,
153
+ time: currentTime,
154
+ price: curPrice,
155
+ volume: mv.vol[j],
156
+ tickType: '',
157
+ cond: '',
158
+ partCode: '',
159
+ partName: '',
160
+ });
161
+ }
162
+ startSn++;
163
+ }
164
+ return { symbol: src.symbol, secType: src.secType, quoteLevel: '', timestamp: src.timestamp, ticks };
165
+ }
@@ -8,6 +8,8 @@
8
8
  import { HttpClient } from '../client/http-client.js';
9
9
  import { createApiRequest } from '../client/api-request.js';
10
10
  import { unmarshalData } from '../client/api-response.js';
11
+ import * as tokenMethods from '../client/token-methods.js';
12
+ import { getTradeCondByCode, isUsStockSymbol } from '../push/tick-util.js';
11
13
  /**
12
14
  * resolveOptionTimezone returns the timezone string to use for expiry conversion.
13
15
  * Explicit tz takes precedence; otherwise infer from symbol (.HK suffix → Asia/Hong_Kong, else America/New_York).
@@ -90,6 +92,25 @@ export class QuoteClient {
90
92
  static fromConfig(config) {
91
93
  return new QuoteClient(new HttpClient(config, undefined, { useQuoteServerUrl: true }));
92
94
  }
95
+ // ── Token management ──────────────────────────────────────────────────────
96
+ /** Call the `user_token_refresh` API and return the new token. Read-only. */
97
+ async queryToken() {
98
+ return tokenMethods.queryToken(this.httpClient);
99
+ }
100
+ /** Refresh the token and update the in-memory config token. */
101
+ async refreshToken(tokenManager) {
102
+ return tokenMethods.refreshToken(this.httpClient, tokenManager);
103
+ }
104
+ /**
105
+ * Start background token auto-refresh. Returns a TokenManager to stop with `tm.stopAutoRefresh()`.
106
+ *
107
+ * @param refreshDurationSecs - Refresh threshold in seconds (minimum 30).
108
+ * @param checkIntervalMs - How often to check, in milliseconds (default 300 000 / 5 min).
109
+ * @param tokenWriter - Optional callback invoked after each successful refresh.
110
+ */
111
+ startTokenAutoRefresh(refreshDurationSecs, checkIntervalMs, tokenWriter) {
112
+ return tokenMethods.startTokenAutoRefresh(this.httpClient, refreshDurationSecs, checkIntervalMs, tokenWriter);
113
+ }
93
114
  async callInto(method, bizParams, version) {
94
115
  const request = createApiRequest(method, bizParams, version);
95
116
  const response = await this.httpClient.executeRequest(request);
@@ -128,12 +149,22 @@ export class QuoteClient {
128
149
  async getKline(req) {
129
150
  return this.callInto('kline', req);
130
151
  }
131
- async getTimeline(symbols) {
132
- return this.callInto('timeline', { symbols });
152
+ async getTimeline(symbolsOrRequest) {
153
+ const req = Array.isArray(symbolsOrRequest) ? { symbols: symbolsOrRequest } : symbolsOrRequest;
154
+ return this.callInto('timeline', req, req.secType === 'CC' ? '3.0' : undefined);
133
155
  }
134
156
  /** Tick-by-tick trades. wire: trade_tick */
135
157
  async getTradeTick(req) {
136
- return this.callInto('trade_tick', req);
158
+ const out = await this.callInto('trade_tick', req);
159
+ for (const tick of out) {
160
+ const isUs = isUsStockSymbol(tick.symbol);
161
+ for (const item of tick.items) {
162
+ if (item.cond && item.cond.length > 0) {
163
+ item.cond = getTradeCondByCode(isUs, item.cond[0]);
164
+ }
165
+ }
166
+ }
167
+ return out;
137
168
  }
138
169
  /** Depth snapshot. wire: quote_depth */
139
170
  async getQuoteDepth(req) {
@@ -299,6 +330,7 @@ export class QuoteClient {
299
330
  while (acc.length < totalSize) {
300
331
  const sub = {
301
332
  symbols: req.symbol ? [req.symbol] : undefined,
333
+ secType: req.secType,
302
334
  period: req.period,
303
335
  right: req.right,
304
336
  beginTime,
@@ -349,7 +381,7 @@ export class QuoteClient {
349
381
  async getStockIndustry(req) {
350
382
  return this.callInto('stock_industry', req);
351
383
  }
352
- /** Quote permission detail. wire: get_quote_permission */
384
+ /** Market data permission entries. wire: get_quote_permission */
353
385
  async getQuotePermission(req) {
354
386
  return this.callInto('get_quote_permission', req);
355
387
  }
@@ -360,9 +392,16 @@ export class QuoteClient {
360
392
  // ==========================================================================
361
393
  // Batch 4: option / future extensions
362
394
  // ==========================================================================
363
- /** Option tick trades. wire: option_trade_tick */
395
+ /** Option tick trades. wire: option_trade_tick
396
+ *
397
+ * Server expects `biz_content` as a top-level JSON array (matches Java's
398
+ * `BatchApiModel` and Python's `MultipleContractParams.to_openapi_dict`).
399
+ * We unwrap the request here so the array is emitted directly instead of
400
+ * `{"contracts": [...]}`. Sending it as an object triggers
401
+ * `biz param error(failed to parse parameters in 'biz_content')`.
402
+ */
364
403
  async getOptionTradeTicks(req) {
365
- return this.callInto('option_trade_tick', req);
404
+ return this.callInto('option_trade_tick', req.contracts ?? []);
366
405
  }
367
406
  /** Option intraday timeline. wire: option_timeline */
368
407
  async getOptionTimeline(req) {
@@ -401,10 +440,16 @@ export class QuoteClient {
401
440
  return this.callInto('future_main_contract', req);
402
441
  }
403
442
  /** Futures K-line. wire: future_kline
404
- * beginTime / endTime default to -1 when unset (server requires them present). */
443
+ * beginTime / endTime default to -1 when unset (server requires them present).
444
+ * Server expects `contract_codes` (plural) — normalize singular `contractCode`
445
+ * to the plural form so callers can pass either shape. */
405
446
  async getFutureKline(req) {
447
+ const contractCodes = req.contractCodes
448
+ ?? (req.contractCode ? [req.contractCode] : undefined);
449
+ const { contractCode: _drop, ...rest } = req;
406
450
  const body = {
407
- ...req,
451
+ ...rest,
452
+ ...(contractCodes ? { contractCodes } : {}),
408
453
  beginTime: req.beginTime ?? -1,
409
454
  endTime: req.endTime ?? -1,
410
455
  };
@@ -422,8 +467,9 @@ export class QuoteClient {
422
467
  endTime = -1;
423
468
  const acc = [];
424
469
  while (acc.length < totalSize) {
470
+ // Server rejects singular `contract_code` — send the plural form.
425
471
  const sub = {
426
- contractCode: req.contractCode,
472
+ contractCodes: req.contractCode ? [req.contractCode] : undefined,
427
473
  period: req.period,
428
474
  beginTime,
429
475
  endTime,
@@ -502,9 +548,30 @@ export class QuoteClient {
502
548
  async getWarrantFilter(req) {
503
549
  return this.callInto('warrant_filter', req);
504
550
  }
505
- /** Industry list. wire: industry_list */
506
- async getIndustryList(req) {
507
- return this.callInto('industry_list', req);
551
+ /** Industry list. wire: industry_list
552
+ *
553
+ * `industryLevel` is required by the server — omitting it returns
554
+ * `industry level error, all supported is: [GSECTOR, GGROUP, GIND, GSUBIND]`.
555
+ * Defaults to `GGROUP` when unset, matching Python SDK's
556
+ * `IndustryLevel.GGROUP` default.
557
+ *
558
+ * Wire fields differ from other endpoints (see `IndustryItem`): server sends
559
+ * `nameCN` / `nameEN` / `industryLevel`. This method hydrates the
560
+ * backwards-compat `name` (from `nameEN || nameCN`) and mirrors
561
+ * `industryLevel` to `level` so existing callers keep working.
562
+ */
563
+ async getIndustryList(req = {}) {
564
+ const payload = { industryLevel: 'GGROUP', ...req };
565
+ const items = await this.callInto('industry_list', payload);
566
+ if (!Array.isArray(items))
567
+ return [];
568
+ for (const it of items) {
569
+ if (it.name === undefined)
570
+ it.name = it.nameEN || it.nameCN;
571
+ if (it.level === undefined)
572
+ it.level = it.industryLevel;
573
+ }
574
+ return items;
508
575
  }
509
576
  /** Stocks inside an industry. wire: industry_stock_list */
510
577
  async getIndustryStocks(req) {
@@ -10,6 +10,7 @@
10
10
  import { HttpClient } from '../client/http-client.js';
11
11
  import { createApiRequest } from '../client/api-request.js';
12
12
  import { unmarshalData } from '../client/api-response.js';
13
+ import * as tokenMethods from '../client/token-methods.js';
13
14
  import { normalizeOrderStatus } from '../model/order-status.js';
14
15
  /** Normalize `Order.status` field in-place (handles int → string). */
15
16
  function normalizeOrderInPlace(o) {
@@ -41,6 +42,31 @@ export class TradeClient {
41
42
  static fromConfig(config, account, secretKey) {
42
43
  return new TradeClient(new HttpClient(config), account, secretKey);
43
44
  }
45
+ // ── Token management ──────────────────────────────────────────────────────
46
+ /** Call the `user_token_refresh` API and return the new token. Read-only. */
47
+ async queryToken() {
48
+ return tokenMethods.queryToken(this.httpClient);
49
+ }
50
+ /**
51
+ * Refresh the token: call the API, update the in-memory config token, and
52
+ * optionally persist via the provided TokenManager (file + writer callback).
53
+ *
54
+ * @param tokenManager - optional TokenManager for file persistence and writer callback
55
+ */
56
+ async refreshToken(tokenManager) {
57
+ return tokenMethods.refreshToken(this.httpClient, tokenManager);
58
+ }
59
+ /**
60
+ * Start background token auto-refresh. Returns a TokenManager that can be
61
+ * used to stop the background task via `tm.stopAutoRefresh()`.
62
+ *
63
+ * @param refreshDurationSecs - Refresh threshold in seconds (minimum 30).
64
+ * @param checkIntervalMs - How often to check, in milliseconds (default 300 000 / 5 min).
65
+ * @param tokenWriter - Optional callback invoked after each successful refresh.
66
+ */
67
+ startTokenAutoRefresh(refreshDurationSecs, checkIntervalMs, tokenWriter) {
68
+ return tokenMethods.startTokenAutoRefresh(this.httpClient, refreshDurationSecs, checkIntervalMs, tokenWriter);
69
+ }
44
70
  async callInto(method, bizParams) {
45
71
  // Inject secretKey into every request when available (institution accounts require it).
46
72
  // Individual methods that already set secretKey will not be overwritten (|| not &&).
@@ -83,14 +109,54 @@ export class TradeClient {
83
109
  });
84
110
  }
85
111
  // === Order operations ===
112
+ /**
113
+ * Prepare an order request for the wire.
114
+ *
115
+ * The gateway expects `algo_params` as a `[{tag, value}, ...]` array
116
+ * (matching the Python SDK's AlgoParams.to_dict serialization), not the
117
+ * plain object shape that reads naturally in TypeScript. This helper
118
+ * normalizes the object form into the array form on outbound payloads
119
+ * so callers can pass the natural object and TWAP/VWAP orders work end
120
+ * to end without wire-format workarounds.
121
+ *
122
+ * Fields with undefined/null values are dropped; empty algoParams
123
+ * becomes an empty array rather than being stripped, matching the
124
+ * Python SDK behavior when the user passes an empty AlgoParams().
125
+ */
126
+ marshalOrderForWire(order) {
127
+ const { algoParams, ...rest } = order;
128
+ const withAccount = { ...rest, account: this.account };
129
+ if (algoParams === undefined)
130
+ return withAccount;
131
+ // Already a tag/value array (advanced callers who want raw control)
132
+ if (Array.isArray(algoParams)) {
133
+ withAccount.algoParams = algoParams;
134
+ return withAccount;
135
+ }
136
+ // Object shape → tag/value array.
137
+ // Keys are converted to snake_case explicitly here (e.g. `startTime` →
138
+ // `start_time`) so they land correctly in the `tag` string that the
139
+ // gateway reads. `keysToSnakeCase` only rewrites object *keys*, not
140
+ // string *values*, so `tag` would be left camelCase if we didn't do
141
+ // this conversion ourselves.
142
+ const tagValues = [];
143
+ for (const [key, value] of Object.entries(algoParams)) {
144
+ if (value === undefined || value === null)
145
+ continue;
146
+ const snakeKey = key.replace(/[A-Z]/g, (c) => '_' + c.toLowerCase());
147
+ tagValues.push({ tag: snakeKey, value });
148
+ }
149
+ withAccount.algoParams = tagValues;
150
+ return withAccount;
151
+ }
86
152
  async placeOrder(order) {
87
- return this.callInto('place_order', { ...order, account: this.account });
153
+ return this.callInto('place_order', this.marshalOrderForWire(order));
88
154
  }
89
155
  async previewOrder(order) {
90
- return this.callInto('preview_order', { ...order, account: this.account });
156
+ return this.callInto('preview_order', this.marshalOrderForWire(order));
91
157
  }
92
158
  async modifyOrder(id, order) {
93
- return this.callInto('modify_order', { ...order, account: this.account, id });
159
+ return this.callInto('modify_order', { ...this.marshalOrderForWire(order), id });
94
160
  }
95
161
  async cancelOrder(id, secretKey) {
96
162
  const params = { account: this.account, id };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Shared token management methods for TradeClient and QuoteClient.
3
+ * Both clients delegate to the underlying HttpClient; this module
4
+ * centralises the JSDoc so each client stays in sync automatically.
5
+ */
6
+ import type { HttpClient } from './http-client';
7
+ import type { TokenManager } from '../config/token-manager';
8
+ /**
9
+ * Call the `user_token_refresh` API and return the new token string.
10
+ * Read-only: does NOT update the stored token.
11
+ * Use `refreshToken()` to also update the in-memory config and optionally persist.
12
+ */
13
+ export declare function queryToken(httpClient: HttpClient): Promise<string>;
14
+ /**
15
+ * Refresh the token: call the API, update the in-memory config token, and
16
+ * optionally persist via the provided TokenManager (file + writer callback).
17
+ *
18
+ * @param httpClient - The underlying HTTP client
19
+ * @param tokenManager - optional TokenManager for file persistence and writer callback
20
+ */
21
+ export declare function refreshToken(httpClient: HttpClient, tokenManager?: TokenManager | null): Promise<void>;
22
+ /**
23
+ * Start background token auto-refresh. Returns a TokenManager that can be
24
+ * used to stop the background task via `tm.stopAutoRefresh()`.
25
+ *
26
+ * @param httpClient - The underlying HTTP client
27
+ * @param refreshDurationSecs - Refresh threshold in seconds (minimum 30).
28
+ * When the token age exceeds this value the refresh is triggered.
29
+ * @param checkIntervalMs - How often to check whether a refresh is needed,
30
+ * in milliseconds. Defaults to 300 000 ms (5 minutes).
31
+ * @param tokenWriter - Optional callback invoked with the new token string
32
+ * after each successful refresh.
33
+ */
34
+ export declare function startTokenAutoRefresh(httpClient: HttpClient, refreshDurationSecs: number, checkIntervalMs?: number, tokenWriter?: (token: string) => void): TokenManager;
@@ -35,5 +35,5 @@ export type { Position } from './model/position';
35
35
  export type { Asset, AssetSegment, PrimeAsset, PreviewResult, PlaceOrderResult, OrderIdResult, Transaction, ManagedAccount, AnalyticsAsset, AggregateAssets, EstimateTradableQuantity, ForexOrderResult, SegmentFund, SegmentFundAvailableItem, SegmentFundHistoryItem, FundDetails, FundingHistoryItem, PositionTransferRecord, PositionTransferDetail, PositionTransferExternalRecord, OptionExerciseCheckResult, OptionExercisePositionPageResult, OptionExerciseRecordPageResult, } from './model/trade';
36
36
  export type { OrdersRequest, GetOrderRequest, OrderTransactionsRequest, PositionsRequest, AssetsRequest, ManagedAccountsRequest, DerivativeContractsRequest, AnalyticsAssetRequest, AggregateAssetsRequest, EstimateTradableQuantityRequest, ForexOrderRequest, SegmentFundRequest, FundDetailsRequest, FundingHistoryRequest, PositionTransferRequest, PositionTransferRecordsRequest, PositionTransferDetailRequest, PositionTransferExternalRecordsRequest, OptionExerciseCheckRequest, OptionExercisePositionRequest, OptionExerciseSubmitRequest, OptionExerciseRecordsRequest, OptionExerciseCancelRequest, } from './model/trade-requests';
37
37
  export type { MarketState, Brief, Kline, KlineItem, Timeline, TimelineItem, TradeTick, TradeTickItem, Depth, DepthLevel, OptionExpiration, OptionChain, OptionChainRow, OptionSymbol, OptionChainFilter, OptionChainFilterGreeks, Range, FutureExchange, FutureContractInfo, FutureQuote, FutureKline, FutureKlineItem, FutureDepth, FutureTradeTickItem, FutureTradingTime, FinancialDailyItem, FinancialReportItem, CorporateAction, CorporateSymbolChange, CorporateDelisting, CorporateIPO, CapitalFlow, CapitalFlowItem, CapitalDistribution, ScannerResult, ScannerResultItem, QuotePermission, SymbolName, TradeMeta, StockDetail, StockBroker, StockBrokerItem, ShortInterest, StockIndustry, IndustryItem, IndustryStock, WarrantBrief, WarrantFilterResult, FundContractInfo, FundQuote, FundHistoryQuote, QuoteOvernight, KlineQuota, MarketScannerTag, MarketScannerTags, OptionAnalysis, OptionLeg, OptionVolatilityPoint, ExchangeRate, FinancialCurrency, BrokerDetail, TradingCalendarItem, FutureMainContractHistory, } from './model/quote';
38
- export type { BriefRequest, DepthQuoteRequest, TradeTickRequest, KlineRequest, KlineByPageRequest, FutureBriefRequest, FutureKlineRequest, FutureKlineByPageRequest, FutureTradeTicksRequest, FutureDepthRequest, FutureContractSingleRequest, FutureContinuousContractsRequest, FutureHistoryMainContractRequest, FutureTradingTimesRequest, AllFutureContractsRequest, OptionTradeTicksRequest, OptionTimelineRequest, OptionDepthRequest, OptionSymbolsRequest, OptionAnalysisRequest, OptionQueryItem, ShortInterestRequest, StockBrokerRequest, StockDetailsRequest, StockFundamentalRequest, StockIndustryRequest, StockDelayBriefsRequest, SymbolsRequest, TradeMetasRequest, TradeRankRequest, TimelineHistoryRequest, TradingCalendarRequest, KlineQuotaRequest, QuotePermissionRequest, QuoteOvernightRequest, IndustryListRequest, IndustryStocksRequest, FundSymbolsRequest, FundContractsRequest, FundQuoteRequest, FundHistoryQuoteRequest, WarrantBriefsRequest, WarrantFilterRequest, MarketScannerTagsRequest, FinancialCurrencyRequest, FinancialExchangeRateRequest, } from './model/quote-requests';
38
+ export type { BriefRequest, DepthQuoteRequest, TradeTickRequest, KlineRequest, KlineByPageRequest, TimelineRequest, FutureBriefRequest, FutureKlineRequest, FutureKlineByPageRequest, FutureTradeTicksRequest, FutureDepthRequest, FutureContractSingleRequest, FutureContinuousContractsRequest, FutureHistoryMainContractRequest, FutureTradingTimesRequest, AllFutureContractsRequest, OptionTradeTicksRequest, OptionTimelineRequest, OptionDepthRequest, OptionSymbolsRequest, OptionAnalysisRequest, OptionQueryItem, ShortInterestRequest, StockBrokerRequest, StockDetailsRequest, StockFundamentalRequest, StockIndustryRequest, StockDelayBriefsRequest, SymbolsRequest, TradeMetasRequest, TradeRankRequest, TimelineHistoryRequest, TradingCalendarRequest, KlineQuotaRequest, QuotePermissionRequest, QuoteOvernightRequest, IndustryListRequest, IndustryStocksRequest, FundSymbolsRequest, FundContractsRequest, FundQuoteRequest, FundHistoryQuoteRequest, WarrantBriefsRequest, WarrantFilterRequest, MarketScannerTagsRequest, FinancialCurrencyRequest, FinancialExchangeRateRequest, } from './model/quote-requests';
39
39
  export { OrderStatus, SecurityType, OrderType, TimeInForce, Market, Currency, QuoteRight, SegmentType, OrderSortBy, CorporateActionType, IndustryLevel, SortDirection, OptionAnalysisPeriod, FinancialReportPeriod, Language, License, BarPeriod, orderStatusCode, } from './model/enums';
@@ -2,7 +2,7 @@
2
2
  * Order construction helpers.
3
3
  * All helpers return an `OrderRequest` with sensible defaults.
4
4
  */
5
- import type { OrderRequest, OrderLegRequest, AlgoParamsRequest } from './order';
5
+ import type { OrderRequest, OrderLegRequest, AlgoParamsRequest, ContractLegRequest } from './order';
6
6
  import { PriceType } from './enums';
7
7
  /** Market order */
8
8
  export declare function marketOrder(account: string, symbol: string, secType: string, action: string, quantity: number): OrderRequest;
@@ -21,14 +21,54 @@ export declare function auctionMarketOrder(account: string, symbol: string, secT
21
21
  /** Algo order (TWAP / VWAP) */
22
22
  export declare function algoOrder(account: string, symbol: string, secType: string, action: string, quantity: number, limitPrice: number, algoType: string, params: AlgoParamsRequest): OrderRequest;
23
23
  /**
24
- * Iceberg order (basic) — only displaySize required.
25
- */
26
- export declare function icebergOrder(account: string, symbol: string, secType: string, action: string, quantity: number, limitPrice: number, displaySize: number): OrderRequest;
27
- /**
28
- * Iceberg order (full params).
29
- * Pass `priceType` as empty string to use server default (LIMIT_PRICE).
24
+ * Iceberg order. `displaySize` is required; all other parameters are optional.
25
+ * Pass `priceType` as empty string to use the server default (LIMIT_PRICE).
30
26
  * Pass `startTime` / `endTime` as 0 to omit the time window.
31
27
  */
32
- export declare function icebergOrderFull(account: string, symbol: string, secType: string, action: string, quantity: number, limitPrice: number, displaySize: number, minDisplaySize?: number, checkIntervals?: number, priceType?: PriceType | string, startTime?: number, endTime?: number): OrderRequest;
28
+ export declare function icebergOrder(account: string, symbol: string, secType: string, action: string, quantity: number, limitPrice: number, displaySize: number, minDisplaySize?: number, checkIntervals?: number, priceType?: PriceType | string, startTime?: number, endTime?: number): OrderRequest;
33
29
  /** Attached profit / loss leg */
34
30
  export declare function orderLeg(legType: string, price: number, timeInForce: string): OrderLegRequest;
31
+ /**
32
+ * Market order by cash amount (instead of quantity).
33
+ * Server uses `isQuantityByAmount=true` + `amount` field.
34
+ */
35
+ export declare function marketOrderByAmount(account: string, symbol: string, secType: string, action: string, amount: number): OrderRequest;
36
+ /**
37
+ * Limit order by cash amount (instead of quantity).
38
+ */
39
+ export declare function limitOrderByAmount(account: string, symbol: string, secType: string, action: string, amount: number, limitPrice: number): OrderRequest;
40
+ /**
41
+ * Trailing stop order using a fixed price offset (auxPrice) instead of a percentage.
42
+ * Use `trailOrder()` for percentage-based trailing stops.
43
+ */
44
+ export declare function trailOrderByPrice(account: string, symbol: string, secType: string, action: string, quantity: number, auxPrice: number): OrderRequest;
45
+ /**
46
+ * Limit order with attached profit/loss legs (bracket order).
47
+ * At most 2 legs are supported.
48
+ *
49
+ * @param orderLegs - Array of `OrderLegRequest` (use `orderLeg()` helper)
50
+ */
51
+ export declare function limitOrderWithLegs(account: string, symbol: string, secType: string, action: string, quantity: number, limitPrice: number, orderLegs: OrderLegRequest[]): OrderRequest;
52
+ /**
53
+ * Multi-leg (combo/MLEG) order for options combos.
54
+ *
55
+ * @param contractLegs - Array of `ContractLegRequest` (use `contractLeg()` helper)
56
+ * @param comboType - e.g. `'MLEG'`
57
+ */
58
+ export declare function comboOrder(account: string, action: string, quantity: number, orderType: string, contractLegs: ContractLegRequest[], comboType?: string, limitPrice?: number, auxPrice?: number, trailingPercent?: number): OrderRequest;
59
+ /**
60
+ * OCA (One-Cancels-All) order.
61
+ * Server expects `orderType: 'OCA'` and an `ocaOrders` list.
62
+ *
63
+ * @param ocaOrders - The contained orders (use any order helper to build each)
64
+ */
65
+ export declare function ocaOrder(account: string, symbol: string, secType: string, action: string, quantity: number, ocaOrders: OrderRequest[]): OrderRequest;
66
+ /**
67
+ * Build a single leg for a multi-leg (MLEG / combo) order.
68
+ *
69
+ * @param symbol - Underlying symbol
70
+ * @param secType - Security type (e.g. `'OPT'`)
71
+ * @param action - `'BUY'` or `'SELL'`
72
+ * @param ratio - Number of contracts for this leg
73
+ */
74
+ export declare function contractLeg(symbol: string, secType: string, action: string, ratio: number, expiry?: string, strike?: string, right?: string): ContractLegRequest;
@@ -12,11 +12,28 @@ export interface OrderLeg {
12
12
  timeInForce?: string;
13
13
  quantity?: number;
14
14
  }
15
- /** Algo order parameters — response side */
15
+ /**
16
+ * Algo order parameters — response side.
17
+ *
18
+ * The response shape flattens the [{tag, value}, ...] wire form into an
19
+ * object, and the server historically emits `startTime` / `endTime` as
20
+ * epoch-ms numbers (matching what the request side sends). Some legacy
21
+ * paths still return the raw string; accept both.
22
+ *
23
+ * Note: `algoStrategy` on the response side is server-echoed; on the
24
+ * request side it lives on `OrderRequest`, not `AlgoParamsRequest`.
25
+ */
16
26
  export interface AlgoParams {
17
27
  algoStrategy?: string;
18
- startTime?: string;
19
- endTime?: string;
28
+ /** Epoch-ms; server may echo as string on legacy paths */
29
+ startTime?: number | string;
30
+ /** Epoch-ms; server may echo as string on legacy paths */
31
+ endTime?: number | string;
32
+ /** Whether to minimize trade count (VWAP) */
33
+ noTakeLiq?: boolean;
34
+ /** Whether to allow completion after end_time (TWAP / VWAP) */
35
+ allowPastEndTime?: boolean;
36
+ /** Participation rate 0.01–0.5 (VWAP only) */
20
37
  participationRate?: number;
21
38
  }
22
39
  /** Order response model (returned by order query methods). */
@@ -135,10 +152,18 @@ export interface OrderRequest {
135
152
  checkIntervals?: number;
136
153
  /** 冰山单:价格类型(LIMIT_PRICE / ASK_PRICE / BID_PRICE / LATEST_PRICE) */
137
154
  priceType?: string;
138
- /** 冰山单:生效开始时间(epoch ms) */
139
- startTime?: number;
140
- /** 冰山单:生效结束时间(epoch ms) */
141
- endTime?: number;
155
+ /**
156
+ * 冰山单:生效开始时间(epoch ms)。
157
+ * Wire note: the gateway accepts both `number` (epoch ms) and `string`
158
+ * (epoch ms as string) for ICEBERG orders; `number | string` keeps
159
+ * TypeScript callers who pass `String(now)` from hitting a compile error.
160
+ */
161
+ startTime?: number | string;
162
+ /**
163
+ * 冰山单:生效结束时间(epoch ms)。
164
+ * Same dual-type note as `startTime` above.
165
+ */
166
+ endTime?: number | string;
142
167
  /** GTD 到期时间(epoch ms) */
143
168
  expireTime?: number;
144
169
  /** 盘后委托价格 */
@@ -149,7 +174,12 @@ export interface OrderRequest {
149
174
  segType?: string;
150
175
  /** 按金额下单:委托金额 */
151
176
  amount?: number;
152
- /** 是否按金额下单 */
177
+ /** 按金额下单:现金金额(wire: cash_amount,与 amount 二选一) */
178
+ cashAmount?: number;
179
+ /**
180
+ * @deprecated 服务端不再需要此字段,by-amount 订单直接设置 `cashAmount`。
181
+ * 保留仅为向前兼容,新代码勿使用。
182
+ */
153
183
  isQuantityByAmount?: boolean;
154
184
  /** 账户分配列表(机构账户) */
155
185
  allocAccounts?: string[];
@@ -173,6 +203,19 @@ export interface OrderRequest {
173
203
  ocaOrders?: OrderRequest[];
174
204
  /** 多腿期权各腿(MLEG) */
175
205
  contractLegs?: ContractLegRequest[];
206
+ /** 组合单类型(如 MLEG) */
207
+ comboType?: string;
208
+ /**
209
+ * Algo strategy name for TWAP / VWAP orders (e.g. `'TWAP'`, `'VWAP'`).
210
+ * Lives on `OrderRequest`, not inside `algoParams` — the Python SDK
211
+ * places it at the top-level order object, and the gateway expects
212
+ * `algo_strategy` as a sibling of `algo_params`.
213
+ *
214
+ * Note: `AlgoParamsRequest` intentionally omits this field (see its
215
+ * doc-comment). Pass `algoStrategy` here and `algoParams` as the
216
+ * companion object.
217
+ */
218
+ algoStrategy?: string;
176
219
  }
177
220
  /** Single leg of a multi-leg option order (MLEG) */
178
221
  export interface ContractLegRequest {
@@ -191,10 +234,25 @@ export interface OrderLegRequest {
191
234
  timeInForce?: string;
192
235
  quantity?: number;
193
236
  }
194
- /** Algo parameters for request side */
237
+ /**
238
+ * Algo parameters for request side (TWAP / VWAP).
239
+ *
240
+ * Fields match the Python SDK's AlgoParams. On the wire, the SDK marshals
241
+ * this object into the `[{tag, value}, ...]` array shape the gateway
242
+ * expects — callers should just pass the natural object.
243
+ *
244
+ * `algoStrategy` is intentionally not here: it lives on the parent
245
+ * `OrderRequest`, not inside `algoParams`.
246
+ */
195
247
  export interface AlgoParamsRequest {
196
- algoStrategy?: string;
197
- startTime?: string;
198
- endTime?: string;
248
+ /** Epoch-ms start time (TWAP / VWAP only) */
249
+ startTime?: number;
250
+ /** Epoch-ms end time (TWAP / VWAP only) */
251
+ endTime?: number;
252
+ /** Try to minimize trade count (VWAP only) */
253
+ noTakeLiq?: boolean;
254
+ /** Allow completing after end_time (TWAP / VWAP only) */
255
+ allowPastEndTime?: boolean;
256
+ /** Participation rate 0.01–0.5 (VWAP only) */
199
257
  participationRate?: number;
200
258
  }