@tigeropenapi/tigeropen 0.5.0 → 0.5.3
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/dist/cjs/client/api-response.js +17 -15
- package/dist/cjs/config/client-config.js +46 -8
- package/dist/cjs/config/config-parser.js +19 -9
- package/dist/cjs/config/index.js +2 -1
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/model/enums.js +4 -0
- package/dist/cjs/quote/quote-client.js +59 -21
- package/dist/cjs/trade/trade-client.js +15 -16
- package/dist/esm/client/api-response.js +17 -15
- package/dist/esm/config/client-config.js +45 -8
- package/dist/esm/config/config-parser.js +19 -9
- package/dist/esm/config/index.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/model/enums.js +4 -0
- package/dist/esm/quote/quote-client.js +59 -21
- package/dist/esm/trade/trade-client.js +15 -16
- package/dist/types/client/api-response.d.ts +6 -5
- package/dist/types/config/client-config.d.ts +2 -0
- package/dist/types/config/index.d.ts +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/model/enums.d.ts +5 -1
- package/dist/types/model/order.d.ts +45 -1
- package/dist/types/model/quote.d.ts +56 -0
- package/dist/types/model/trade-requests.d.ts +41 -0
- package/dist/types/quote/quote-client.d.ts +18 -8
- package/dist/types/trade/trade-client.d.ts +0 -3
- package/package.json +1 -1
|
@@ -22,6 +22,10 @@ const DEFAULT_TIMEOUT = 15;
|
|
|
22
22
|
const DEFAULT_SERVER_URL = 'https://openapi.tigerfintech.com/gateway';
|
|
23
23
|
/** Tiger public key for response signature verification (Base64-encoded) */
|
|
24
24
|
const TIGER_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNF3G8SoEcCZh2rshUbayDgLLrj6rKgzNMxDL2HSnKcB0+GPOsndqSv+a4IBu9+I3fyBp5hkyMMG2+AXugd9pMpy6VxJxlNjhX1MYbNTZJUT4nudki4uh+LMOkIBHOceGNXjgB+cXqmlUnjlqha/HgboeHSnSgpM3dKSJQlIOsDwIDAQAB';
|
|
25
|
+
/** Sandbox / QA tiger public key for response signature verification */
|
|
26
|
+
export const SANDBOX_TIGER_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbm21i11hgAENGd3/f280PSe4g9YGkS3TEXBYMidihTvHHf' +
|
|
27
|
+
'+tJ0PYD0o3PruI0hl3qhEjHTAxb75T5YD3SGK4IBhHn/Rk6mhqlGgI+bBrBVYaXixmHfRo75RpUUuWACyeqQk' +
|
|
28
|
+
'ZckgR0McxuW9xRMIa2cXZOoL1E4SL4lXKGhKoWbwIDAQAB';
|
|
25
29
|
/** Environment variable names */
|
|
26
30
|
const ENV_TIGER_ID = 'TIGEROPEN_TIGER_ID';
|
|
27
31
|
const ENV_PRIVATE_KEY = 'TIGEROPEN_PRIVATE_KEY';
|
|
@@ -29,6 +33,9 @@ const ENV_ACCOUNT = 'TIGEROPEN_ACCOUNT';
|
|
|
29
33
|
const ENV_SECRET_KEY = 'TIGEROPEN_SECRET_KEY';
|
|
30
34
|
const ENV_TOKEN = 'TIGEROPEN_TOKEN';
|
|
31
35
|
const ENV_TOKEN_FILE = 'TIGEROPEN_TOKEN_FILE';
|
|
36
|
+
const ENV_TIGER_PUBLIC_KEY = 'TIGEROPEN_TIGER_PUBLIC_KEY';
|
|
37
|
+
const ENV_SERVER_URL = 'TIGEROPEN_SERVER_URL';
|
|
38
|
+
const ENV_QUOTE_SERVER_URL = 'TIGEROPEN_QUOTE_SERVER_URL';
|
|
32
39
|
/**
|
|
33
40
|
* Load and parse a Java-style properties file.
|
|
34
41
|
*
|
|
@@ -130,12 +137,15 @@ export function createClientConfig(options) {
|
|
|
130
137
|
const license = opts.license || fileProps['license'];
|
|
131
138
|
const language = opts.language || fileProps['language'] || DEFAULT_LANGUAGE;
|
|
132
139
|
const timezone = opts.timezone || fileProps['timezone'];
|
|
140
|
+
// tiger_public_key from properties file (e.g. for QA/sandbox environments)
|
|
141
|
+
let tigerPublicKey = opts.tigerPublicKey || fileProps['tiger_public_key'] || TIGER_PUBLIC_KEY;
|
|
133
142
|
// Environment variables override everything
|
|
134
143
|
const envTigerId = process.env[ENV_TIGER_ID];
|
|
135
144
|
const envPrivateKey = process.env[ENV_PRIVATE_KEY];
|
|
136
145
|
const envAccount = process.env[ENV_ACCOUNT];
|
|
137
146
|
const envSecretKey = process.env[ENV_SECRET_KEY];
|
|
138
147
|
const envToken = process.env[ENV_TOKEN];
|
|
148
|
+
const envTigerPublicKey = process.env[ENV_TIGER_PUBLIC_KEY];
|
|
139
149
|
if (envTigerId) {
|
|
140
150
|
tigerId = envTigerId;
|
|
141
151
|
}
|
|
@@ -151,6 +161,9 @@ export function createClientConfig(options) {
|
|
|
151
161
|
if (envToken) {
|
|
152
162
|
token = envToken;
|
|
153
163
|
}
|
|
164
|
+
if (envTigerPublicKey) {
|
|
165
|
+
tigerPublicKey = envTigerPublicKey;
|
|
166
|
+
}
|
|
154
167
|
// Token loading priority: env TIGEROPEN_TOKEN > tokenLoader > token file (TIGEROPEN_TOKEN_FILE or default)
|
|
155
168
|
if (!token) {
|
|
156
169
|
if (opts.tokenLoader) {
|
|
@@ -189,29 +202,53 @@ export function createClientConfig(options) {
|
|
|
189
202
|
if (!privateKey) {
|
|
190
203
|
throw new Error(`privateKey is required. Set it via options.privateKey, a config file, or the ${ENV_PRIVATE_KEY} environment variable.`);
|
|
191
204
|
}
|
|
192
|
-
// Resolve server URL: explicit > dynamic domain > default
|
|
205
|
+
// Resolve server URL: env var > explicit opts > file > dynamic domain > default
|
|
193
206
|
const enableDynamicDomain = opts.enableDynamicDomain ?? true;
|
|
194
207
|
let serverUrl;
|
|
195
208
|
let quoteServerUrl;
|
|
196
209
|
// Query dynamic domains once (may spawn a child process); reuse for both URLs.
|
|
197
210
|
let domainConf = {};
|
|
198
|
-
|
|
211
|
+
const envServerUrl = process.env[ENV_SERVER_URL];
|
|
212
|
+
const envQuoteServerUrl = process.env[ENV_QUOTE_SERVER_URL];
|
|
213
|
+
const needServerUrl = !envServerUrl && !opts.serverUrl && !fileProps['server_url'];
|
|
214
|
+
const needQuoteServerUrl = !envQuoteServerUrl && !opts.quoteServerUrl && !fileProps['quote_server_url'];
|
|
215
|
+
if (enableDynamicDomain && (needServerUrl || needQuoteServerUrl)) {
|
|
199
216
|
domainConf = queryDomains(license);
|
|
200
217
|
}
|
|
201
|
-
if (
|
|
218
|
+
if (envServerUrl) {
|
|
219
|
+
serverUrl = envServerUrl;
|
|
220
|
+
}
|
|
221
|
+
else if (opts.serverUrl) {
|
|
202
222
|
serverUrl = opts.serverUrl;
|
|
203
223
|
}
|
|
224
|
+
else if (fileProps['server_url']) {
|
|
225
|
+
serverUrl = fileProps['server_url'];
|
|
226
|
+
}
|
|
204
227
|
else {
|
|
205
228
|
const dynamicUrl = resolveDynamicServerUrl(domainConf, license);
|
|
206
229
|
serverUrl = dynamicUrl || DEFAULT_SERVER_URL;
|
|
207
230
|
}
|
|
208
|
-
// Resolve quote server URL: explicit > dynamic domain > serverUrl fallback
|
|
209
|
-
if (
|
|
231
|
+
// Resolve quote server URL: env var > explicit opts > file > dynamic domain > serverUrl fallback
|
|
232
|
+
if (envQuoteServerUrl) {
|
|
233
|
+
quoteServerUrl = envQuoteServerUrl;
|
|
234
|
+
}
|
|
235
|
+
else if (opts.quoteServerUrl) {
|
|
210
236
|
quoteServerUrl = opts.quoteServerUrl;
|
|
211
237
|
}
|
|
238
|
+
else if (fileProps['quote_server_url']) {
|
|
239
|
+
quoteServerUrl = fileProps['quote_server_url'];
|
|
240
|
+
}
|
|
212
241
|
else {
|
|
213
|
-
|
|
214
|
-
|
|
242
|
+
// Only use dynamic domain if serverUrl itself came from dynamic resolution (not pinned by env/opts/file).
|
|
243
|
+
// When serverUrl is pinned, prefer it as the quote fallback to avoid mixing environments.
|
|
244
|
+
const serverUrlPinned = !!(envServerUrl || opts.serverUrl || fileProps['server_url']);
|
|
245
|
+
if (!serverUrlPinned) {
|
|
246
|
+
const dynamicQuoteUrl = resolveDynamicQuoteServerUrl(domainConf, license);
|
|
247
|
+
quoteServerUrl = dynamicQuoteUrl || serverUrl;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
quoteServerUrl = serverUrl;
|
|
251
|
+
}
|
|
215
252
|
}
|
|
216
253
|
return {
|
|
217
254
|
tigerId,
|
|
@@ -230,7 +267,7 @@ export function createClientConfig(options) {
|
|
|
230
267
|
serverUrl,
|
|
231
268
|
quoteServerUrl,
|
|
232
269
|
deviceId: detectDeviceId(),
|
|
233
|
-
tigerPublicKey
|
|
270
|
+
tigerPublicKey,
|
|
234
271
|
};
|
|
235
272
|
}
|
|
236
273
|
/**
|
|
@@ -33,34 +33,34 @@ export function parsePropertiesString(content) {
|
|
|
33
33
|
let continuation = false;
|
|
34
34
|
for (const rawLine of lines) {
|
|
35
35
|
if (continuation) {
|
|
36
|
-
// 续行:去除前导空格后拼接
|
|
37
36
|
const trimmedLeft = rawLine.replace(/^[ \t]+/, '');
|
|
38
|
-
if (trimmedLeft.
|
|
37
|
+
if (trimmedLeft === '' || trimmedLeft.startsWith('#') || trimmedLeft.startsWith('!')) {
|
|
38
|
+
continuation = false;
|
|
39
|
+
}
|
|
40
|
+
else if (endsWithContinuation(trimmedLeft)) {
|
|
39
41
|
currentLine += trimmedLeft.slice(0, -1);
|
|
40
42
|
continue;
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
else {
|
|
45
|
+
currentLine += trimmedLeft;
|
|
46
|
+
continuation = false;
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
else {
|
|
46
50
|
const trimmed = rawLine.trim();
|
|
47
|
-
// 跳过空行
|
|
48
51
|
if (trimmed === '') {
|
|
49
52
|
continue;
|
|
50
53
|
}
|
|
51
|
-
// 跳过注释行
|
|
52
54
|
if (trimmed.startsWith('#') || trimmed.startsWith('!')) {
|
|
53
55
|
continue;
|
|
54
56
|
}
|
|
55
|
-
|
|
56
|
-
if (trimmed.endsWith('\\')) {
|
|
57
|
+
if (endsWithContinuation(trimmed)) {
|
|
57
58
|
currentLine = trimmed.slice(0, -1);
|
|
58
59
|
continuation = true;
|
|
59
60
|
continue;
|
|
60
61
|
}
|
|
61
62
|
currentLine = trimmed;
|
|
62
63
|
}
|
|
63
|
-
// 解析键值对
|
|
64
64
|
const result = parseKeyValue(currentLine);
|
|
65
65
|
if (result) {
|
|
66
66
|
props[result[0]] = result[1];
|
|
@@ -76,6 +76,16 @@ export function parsePropertiesString(content) {
|
|
|
76
76
|
}
|
|
77
77
|
return props;
|
|
78
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* 判断一行是否以续行标记结尾(奇数个末尾反斜杠)。
|
|
81
|
+
*/
|
|
82
|
+
function endsWithContinuation(line) {
|
|
83
|
+
let count = 0;
|
|
84
|
+
for (let i = line.length - 1; i >= 0 && line[i] === '\\'; i--) {
|
|
85
|
+
count++;
|
|
86
|
+
}
|
|
87
|
+
return count % 2 === 1;
|
|
88
|
+
}
|
|
79
89
|
/**
|
|
80
90
|
* 解析单行键值对,支持 = 和 : 分隔符。
|
|
81
91
|
* 值中可以包含 = 或 :,只按第一个分隔符拆分。
|
package/dist/esm/config/index.js
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* 配置层导出
|
|
3
3
|
*/
|
|
4
4
|
export { parsePropertiesFile, parsePropertiesString } from './config-parser.js';
|
|
5
|
-
export { createClientConfig, loadPropertiesFile } from './client-config.js';
|
|
5
|
+
export { createClientConfig, loadPropertiesFile, SANDBOX_TIGER_PUBLIC_KEY } from './client-config.js';
|
|
6
6
|
export { TokenManager } from './token-manager.js';
|
|
7
7
|
export { queryDomains, resolveDynamicServerUrl, resolveDynamicQuoteServerUrl } from './domain.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
/** SDK 版本号 */
|
|
18
18
|
export { SDK_VERSION as VERSION } from './version.js';
|
|
19
19
|
// Config
|
|
20
|
-
export { createClientConfig, loadPropertiesFile } from './config/index.js';
|
|
20
|
+
export { createClientConfig, loadPropertiesFile, SANDBOX_TIGER_PUBLIC_KEY } from './config/index.js';
|
|
21
21
|
export { TokenManager } from './config/index.js';
|
|
22
22
|
// Transport
|
|
23
23
|
export { HttpClient } from './client/index.js';
|
package/dist/esm/model/enums.js
CHANGED
|
@@ -146,6 +146,7 @@ export var TimeInForce;
|
|
|
146
146
|
(function (TimeInForce) {
|
|
147
147
|
TimeInForce["DAY"] = "DAY";
|
|
148
148
|
TimeInForce["GTC"] = "GTC";
|
|
149
|
+
TimeInForce["GTD"] = "GTD";
|
|
149
150
|
TimeInForce["OPG"] = "OPG";
|
|
150
151
|
})(TimeInForce || (TimeInForce = {}));
|
|
151
152
|
/** 订单排序字段 */
|
|
@@ -168,6 +169,9 @@ export var CorporateActionType;
|
|
|
168
169
|
CorporateActionType["Split"] = "split";
|
|
169
170
|
CorporateActionType["Dividend"] = "dividend";
|
|
170
171
|
CorporateActionType["Earning"] = "earning";
|
|
172
|
+
CorporateActionType["SymbolChange"] = "symbol_change";
|
|
173
|
+
CorporateActionType["Delisting"] = "delisting";
|
|
174
|
+
CorporateActionType["IPO"] = "ipo";
|
|
171
175
|
})(CorporateActionType || (CorporateActionType = {}));
|
|
172
176
|
/** 行业级别 (1~4 级) */
|
|
173
177
|
export var IndustryLevel;
|
|
@@ -151,8 +151,10 @@ export class QuoteClient {
|
|
|
151
151
|
*
|
|
152
152
|
* @param timezone - Optional IANA timezone for expiry conversion (e.g. 'America/New_York').
|
|
153
153
|
* If omitted, defaults to America/New_York for US symbols and Asia/Hong_Kong for .HK symbols.
|
|
154
|
+
* @param returnGreekValue - Whether to return Greeks (delta/gamma/theta/vega/rho).
|
|
155
|
+
* @param optionFilter - Optional filter for in-the-money status, IV range, open interest range, Greeks ranges.
|
|
154
156
|
*/
|
|
155
|
-
async getOptionChain(items, timezone) {
|
|
157
|
+
async getOptionChain(items, timezone, returnGreekValue, optionFilter) {
|
|
156
158
|
const optionBasic = items.map(([symbol, expiry]) => {
|
|
157
159
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(expiry)) {
|
|
158
160
|
throw new Error(`invalid expiry date, expected YYYY-MM-DD: ${expiry}`);
|
|
@@ -161,37 +163,27 @@ export class QuoteClient {
|
|
|
161
163
|
const expiryMs = localMidnightMs(expiry, tz);
|
|
162
164
|
return { symbol, expiry: expiryMs };
|
|
163
165
|
});
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
* If omitted, defaults to America/New_York for US symbols and Asia/Hong_Kong for .HK symbols.
|
|
171
|
-
*/
|
|
172
|
-
async getOptionQuote(identifiers, timezone) {
|
|
173
|
-
const optionBasic = identifiers.map((id) => {
|
|
174
|
-
const p = parseOptionIdentifier(id, timezone);
|
|
175
|
-
return { symbol: p.symbol, expiry: p.expiryMs, right: p.right, strike: p.strike };
|
|
176
|
-
});
|
|
177
|
-
return this.callInto('option_brief', { option_basic: optionBasic }, '2.0');
|
|
178
|
-
}
|
|
179
|
-
/** @deprecated Use getOptionQuote instead. */
|
|
180
|
-
async getOptionBrief(identifiers) {
|
|
181
|
-
return this.getOptionQuote(identifiers);
|
|
166
|
+
const body = { option_basic: optionBasic };
|
|
167
|
+
if (returnGreekValue !== undefined)
|
|
168
|
+
body['return_greek_value'] = returnGreekValue;
|
|
169
|
+
if (optionFilter !== undefined)
|
|
170
|
+
body['option_filter'] = optionFilter;
|
|
171
|
+
return this.callInto('option_chain', body, '3.0');
|
|
182
172
|
}
|
|
183
173
|
/**
|
|
184
174
|
* Option K-line by OCC-style identifier.
|
|
185
175
|
*
|
|
186
176
|
* @param timezone - Optional IANA timezone for expiry conversion (e.g. 'America/New_York').
|
|
187
177
|
* If omitted, defaults to America/New_York for US symbols and Asia/Hong_Kong for .HK symbols.
|
|
178
|
+
* @param limit - Maximum number of bars to return.
|
|
179
|
+
* @param sortDir - Sort direction ('asc' or 'desc').
|
|
188
180
|
*/
|
|
189
|
-
async getOptionKline(identifiers, period, beginTime = -1, endTime = -1, timezone) {
|
|
181
|
+
async getOptionKline(identifiers, period, beginTime = -1, endTime = -1, timezone, limit, sortDir) {
|
|
190
182
|
const resolvedBegin = beginTime === 0 ? -1 : beginTime;
|
|
191
183
|
const resolvedEnd = endTime === 0 ? -1 : endTime;
|
|
192
184
|
const optionQuery = identifiers.map((id) => {
|
|
193
185
|
const p = parseOptionIdentifier(id, timezone);
|
|
194
|
-
|
|
186
|
+
const entry = {
|
|
195
187
|
symbol: p.symbol,
|
|
196
188
|
expiry: p.expiryMs,
|
|
197
189
|
right: p.right,
|
|
@@ -200,9 +192,31 @@ export class QuoteClient {
|
|
|
200
192
|
begin_time: resolvedBegin,
|
|
201
193
|
end_time: resolvedEnd,
|
|
202
194
|
};
|
|
195
|
+
if (limit !== undefined && limit > 0)
|
|
196
|
+
entry['limit'] = limit;
|
|
197
|
+
if (sortDir !== undefined && sortDir !== '')
|
|
198
|
+
entry['sort_dir'] = sortDir;
|
|
199
|
+
return entry;
|
|
203
200
|
});
|
|
204
201
|
return this.callInto('option_kline', { option_query: optionQuery }, '2.0');
|
|
205
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Real-time option quotes by OCC-style identifier.
|
|
205
|
+
*
|
|
206
|
+
* @param timezone - Optional IANA timezone for expiry conversion (e.g. 'America/New_York').
|
|
207
|
+
* If omitted, defaults to America/New_York for US symbols and Asia/Hong_Kong for .HK symbols.
|
|
208
|
+
*/
|
|
209
|
+
async getOptionQuote(identifiers, timezone) {
|
|
210
|
+
const optionBasic = identifiers.map((id) => {
|
|
211
|
+
const p = parseOptionIdentifier(id, timezone);
|
|
212
|
+
return { symbol: p.symbol, expiry: p.expiryMs, right: p.right, strike: p.strike };
|
|
213
|
+
});
|
|
214
|
+
return this.callInto('option_brief', { option_basic: optionBasic }, '2.0');
|
|
215
|
+
}
|
|
216
|
+
/** @deprecated Use getOptionQuote instead. */
|
|
217
|
+
async getOptionBrief(identifiers) {
|
|
218
|
+
return this.getOptionQuote(identifiers);
|
|
219
|
+
}
|
|
206
220
|
// === Futures ===
|
|
207
221
|
async getFutureExchange() {
|
|
208
222
|
return this.callInto('future_exchange', { secType: 'FUT' });
|
|
@@ -520,6 +534,30 @@ export class QuoteClient {
|
|
|
520
534
|
return [];
|
|
521
535
|
return Object.values(grouped).flat();
|
|
522
536
|
}
|
|
537
|
+
/** Corporate symbol change (flattened). wire: corporate_action (action_type=symbol_change) */
|
|
538
|
+
async getCorporateSymbolChange(req) {
|
|
539
|
+
const body = { ...req, actionType: 'symbol_change' };
|
|
540
|
+
const grouped = await this.callInto('corporate_action', body);
|
|
541
|
+
if (!grouped || typeof grouped !== 'object')
|
|
542
|
+
return [];
|
|
543
|
+
return Object.values(grouped).flat();
|
|
544
|
+
}
|
|
545
|
+
/** Corporate delisting (flattened). wire: corporate_action (action_type=delisting) */
|
|
546
|
+
async getCorporateDelisting(req) {
|
|
547
|
+
const body = { ...req, actionType: 'delisting' };
|
|
548
|
+
const grouped = await this.callInto('corporate_action', body);
|
|
549
|
+
if (!grouped || typeof grouped !== 'object')
|
|
550
|
+
return [];
|
|
551
|
+
return Object.values(grouped).flat();
|
|
552
|
+
}
|
|
553
|
+
/** Corporate IPO (flattened). wire: corporate_action (action_type=ipo) */
|
|
554
|
+
async getCorporateIPO(req) {
|
|
555
|
+
const body = { ...req, actionType: 'ipo' };
|
|
556
|
+
const grouped = await this.callInto('corporate_action', body);
|
|
557
|
+
if (!grouped || typeof grouped !== 'object')
|
|
558
|
+
return [];
|
|
559
|
+
return Object.values(grouped).flat();
|
|
560
|
+
}
|
|
523
561
|
/** Financial currency per symbol. wire: financial_currency */
|
|
524
562
|
async getFinancialCurrency(req) {
|
|
525
563
|
return this.callInto('financial_currency', req);
|
|
@@ -42,7 +42,16 @@ export class TradeClient {
|
|
|
42
42
|
return new TradeClient(new HttpClient(config), account, secretKey);
|
|
43
43
|
}
|
|
44
44
|
async callInto(method, bizParams) {
|
|
45
|
-
|
|
45
|
+
// Inject secretKey into every request when available (institution accounts require it).
|
|
46
|
+
// Individual methods that already set secretKey will not be overwritten (|| not &&).
|
|
47
|
+
let params = bizParams;
|
|
48
|
+
if (this.secretKey && params !== null && typeof params === 'object' && !Array.isArray(params)) {
|
|
49
|
+
const p = params;
|
|
50
|
+
if (p['secretKey'] == null && p['secret_key'] == null) {
|
|
51
|
+
params = { ...p, secretKey: this.secretKey };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const request = createApiRequest(method, params);
|
|
46
55
|
const response = await this.httpClient.executeRequest(request);
|
|
47
56
|
return unmarshalData(response.data);
|
|
48
57
|
}
|
|
@@ -75,25 +84,18 @@ export class TradeClient {
|
|
|
75
84
|
}
|
|
76
85
|
// === Order operations ===
|
|
77
86
|
async placeOrder(order) {
|
|
78
|
-
|
|
79
|
-
if (!params.secretKey && this.secretKey)
|
|
80
|
-
params.secretKey = this.secretKey;
|
|
81
|
-
return this.callInto('place_order', params);
|
|
87
|
+
return this.callInto('place_order', { ...order, account: this.account });
|
|
82
88
|
}
|
|
83
89
|
async previewOrder(order) {
|
|
84
90
|
return this.callInto('preview_order', { ...order, account: this.account });
|
|
85
91
|
}
|
|
86
92
|
async modifyOrder(id, order) {
|
|
87
|
-
|
|
88
|
-
if (!params.secretKey && this.secretKey)
|
|
89
|
-
params.secretKey = this.secretKey;
|
|
90
|
-
return this.callInto('modify_order', params);
|
|
93
|
+
return this.callInto('modify_order', { ...order, account: this.account, id });
|
|
91
94
|
}
|
|
92
95
|
async cancelOrder(id, secretKey) {
|
|
93
|
-
const sk = secretKey ?? this.secretKey;
|
|
94
96
|
const params = { account: this.account, id };
|
|
95
|
-
if (
|
|
96
|
-
params.secretKey =
|
|
97
|
+
if (secretKey !== undefined)
|
|
98
|
+
params.secretKey = secretKey; // per-call override takes precedence; undefined means use config default
|
|
97
99
|
return this.callInto('cancel_order', params);
|
|
98
100
|
}
|
|
99
101
|
// === Order queries (BREAKING v0.4.0) ===
|
|
@@ -131,14 +133,11 @@ export class TradeClient {
|
|
|
131
133
|
}
|
|
132
134
|
/**
|
|
133
135
|
* Get a single order by ID (v0.4.0 new).
|
|
134
|
-
* Wire method: `orders` with id/order_id param; server returns a single Order object
|
|
135
|
-
* (not `{items:[]}` envelope).
|
|
136
|
-
*
|
|
137
136
|
* Returns `undefined` if no match.
|
|
138
137
|
*/
|
|
139
138
|
async getOrder(req) {
|
|
140
139
|
const merged = withAccount(req, this.account);
|
|
141
|
-
const out = await this.callInto('
|
|
140
|
+
const out = await this.callInto('order_no', merged);
|
|
142
141
|
if (!out || (!out.id && !out.orderId))
|
|
143
142
|
return undefined;
|
|
144
143
|
normalizeOrderInPlace(out);
|
|
@@ -12,14 +12,15 @@ export interface ApiResponse {
|
|
|
12
12
|
sign?: string;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* Parse the raw HTTP response body.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Parse the raw HTTP response body. Throws TigerError when code != 0.
|
|
16
|
+
*
|
|
17
|
+
* patchLargeIntegers is applied before JSON.parse to preserve int64 order IDs
|
|
18
|
+
* (e.g. 28868646234578944) as strings rather than losing precision.
|
|
18
19
|
*/
|
|
19
20
|
export declare function parseApiResponse(body: string): ApiResponse;
|
|
20
21
|
/**
|
|
21
22
|
* Decode an ApiResponse.data payload into a typed value.
|
|
22
|
-
* Handles
|
|
23
|
-
*
|
|
23
|
+
* Handles double-encoded JSON (where `data` is a JSON string wrapping JSON),
|
|
24
|
+
* seen on some trade endpoints.
|
|
24
25
|
*/
|
|
25
26
|
export declare function unmarshalData<T>(data: unknown): T | undefined;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 配置层导出
|
|
3
3
|
*/
|
|
4
4
|
export { parsePropertiesFile, parsePropertiesString } from './config-parser';
|
|
5
|
-
export { createClientConfig, loadPropertiesFile } from './client-config';
|
|
5
|
+
export { createClientConfig, loadPropertiesFile, SANDBOX_TIGER_PUBLIC_KEY } from './client-config';
|
|
6
6
|
export type { ClientConfig, ClientConfigOptions } from './client-config';
|
|
7
7
|
export { TokenManager } from './token-manager';
|
|
8
8
|
export type { TokenManagerOptions, RefreshFn } from './token-manager';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
/** SDK 版本号 */
|
|
18
18
|
export { SDK_VERSION as VERSION } from './version';
|
|
19
|
-
export { createClientConfig, loadPropertiesFile } from './config';
|
|
19
|
+
export { createClientConfig, loadPropertiesFile, SANDBOX_TIGER_PUBLIC_KEY } from './config';
|
|
20
20
|
export type { ClientConfig, ClientConfigOptions } from './config';
|
|
21
21
|
export { TokenManager } from './config';
|
|
22
22
|
export type { TokenManagerOptions, RefreshFn } from './config';
|
|
@@ -27,13 +27,13 @@ export { QuoteClient, parseOptionIdentifier } from './quote';
|
|
|
27
27
|
export { TradeClient } from './trade';
|
|
28
28
|
export { PushClient, ConnectionState, SubjectType } from './push';
|
|
29
29
|
export type { PushClientOptions } from './push';
|
|
30
|
-
export type { Order, OrderRequest } from './model/order';
|
|
30
|
+
export type { Order, OrderRequest, ContractLegRequest } from './model/order';
|
|
31
31
|
export { marketOrder, limitOrder, stopOrder, stopLimitOrder } from './model/order-helpers';
|
|
32
32
|
export { normalizeOrderStatus } from './model/order-status';
|
|
33
33
|
export type { Contract } from './model/contract';
|
|
34
34
|
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
|
-
export type { MarketState, Brief, Kline, KlineItem, Timeline, TimelineItem, TradeTick, TradeTickItem, Depth, DepthLevel, OptionExpiration, OptionChain, OptionChainRow, OptionSymbol, FutureExchange, FutureContractInfo, FutureQuote, FutureKline, FutureKlineItem, FutureDepth, FutureTradeTickItem, FutureTradingTime, FinancialDailyItem, FinancialReportItem, CorporateAction, 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';
|
|
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
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';
|
|
39
39
|
export { OrderStatus, SecurityType, OrderType, TimeInForce, Market, Currency, QuoteRight, SegmentType, OrderSortBy, CorporateActionType, IndustryLevel, SortDirection, OptionAnalysisPeriod, FinancialReportPeriod, Language, License, BarPeriod, orderStatusCode, } from './model/enums';
|
|
@@ -115,6 +115,7 @@ export declare enum License {
|
|
|
115
115
|
export declare enum TimeInForce {
|
|
116
116
|
DAY = "DAY",
|
|
117
117
|
GTC = "GTC",
|
|
118
|
+
GTD = "GTD",
|
|
118
119
|
OPG = "OPG"
|
|
119
120
|
}
|
|
120
121
|
/** 订单排序字段 */
|
|
@@ -133,7 +134,10 @@ export declare enum SegmentType {
|
|
|
133
134
|
export declare enum CorporateActionType {
|
|
134
135
|
Split = "split",
|
|
135
136
|
Dividend = "dividend",
|
|
136
|
-
Earning = "earning"
|
|
137
|
+
Earning = "earning",
|
|
138
|
+
SymbolChange = "symbol_change",
|
|
139
|
+
Delisting = "delisting",
|
|
140
|
+
IPO = "ipo"
|
|
137
141
|
}
|
|
138
142
|
/** 行业级别 (1~4 级) */
|
|
139
143
|
export declare enum IndustryLevel {
|
|
@@ -139,8 +139,52 @@ export interface OrderRequest {
|
|
|
139
139
|
startTime?: number;
|
|
140
140
|
/** 冰山单:生效结束时间(epoch ms) */
|
|
141
141
|
endTime?: number;
|
|
142
|
+
/** GTD 到期时间(epoch ms) */
|
|
143
|
+
expireTime?: number;
|
|
144
|
+
/** 盘后委托价格 */
|
|
145
|
+
afterHoursPrice?: number;
|
|
146
|
+
/** 批次号 */
|
|
147
|
+
batchNo?: number;
|
|
148
|
+
/** 资金类型(CASH / MARGIN) */
|
|
149
|
+
segType?: string;
|
|
150
|
+
/** 按金额下单:委托金额 */
|
|
151
|
+
amount?: number;
|
|
152
|
+
/** 是否按金额下单 */
|
|
153
|
+
isQuantityByAmount?: boolean;
|
|
154
|
+
/** 账户分配列表(机构账户) */
|
|
155
|
+
allocAccounts?: string[];
|
|
156
|
+
/** 各账户分配份额(与 allocAccounts 一一对应) */
|
|
157
|
+
allocShares?: number[];
|
|
158
|
+
/** 下单来源 */
|
|
159
|
+
source?: string;
|
|
160
|
+
/** 下单渠道 */
|
|
161
|
+
channel?: string;
|
|
162
|
+
/** 虚拟订单类型 */
|
|
163
|
+
virtualOrderType?: string;
|
|
164
|
+
/** 虚拟订单 ID */
|
|
165
|
+
virtualId?: string;
|
|
166
|
+
/** 止盈订单 ID(bracket 关联) */
|
|
167
|
+
profitTakerOrderId?: number;
|
|
168
|
+
/** 止损订单 ID(bracket 关联) */
|
|
169
|
+
stopLossOrderId?: number;
|
|
170
|
+
/** 本地流水号 */
|
|
171
|
+
localNo?: string;
|
|
172
|
+
/** OCA 订单组(One-Cancels-All) */
|
|
173
|
+
ocaOrders?: OrderRequest[];
|
|
174
|
+
/** 多腿期权各腿(MLEG) */
|
|
175
|
+
contractLegs?: ContractLegRequest[];
|
|
176
|
+
}
|
|
177
|
+
/** Single leg of a multi-leg option order (MLEG) */
|
|
178
|
+
export interface ContractLegRequest {
|
|
179
|
+
symbol?: string;
|
|
180
|
+
secType?: string;
|
|
181
|
+
expiry?: string;
|
|
182
|
+
strike?: string;
|
|
183
|
+
right?: string;
|
|
184
|
+
action?: string;
|
|
185
|
+
ratio?: number;
|
|
142
186
|
}
|
|
143
|
-
/** Attached leg for request side */
|
|
187
|
+
/** Attached profit/loss leg for order request side */
|
|
144
188
|
export interface OrderLegRequest {
|
|
145
189
|
legType: string;
|
|
146
190
|
price?: number;
|
|
@@ -121,6 +121,26 @@ export interface OptionChainRow {
|
|
|
121
121
|
put?: OptionLeg;
|
|
122
122
|
call?: OptionLeg;
|
|
123
123
|
}
|
|
124
|
+
/** Range filter, serialized as { min, max } — corresponds to Java Range<T> */
|
|
125
|
+
export interface Range {
|
|
126
|
+
min?: number;
|
|
127
|
+
max?: number;
|
|
128
|
+
}
|
|
129
|
+
/** Greeks range filters for option_chain (corresponds to Java OptionChainFilterModel.Greeks) */
|
|
130
|
+
export interface OptionChainFilterGreeks {
|
|
131
|
+
delta?: Range;
|
|
132
|
+
gamma?: Range;
|
|
133
|
+
vega?: Range;
|
|
134
|
+
theta?: Range;
|
|
135
|
+
rho?: Range;
|
|
136
|
+
}
|
|
137
|
+
/** Option chain filter (corresponds to Java OptionChainFilterModel) */
|
|
138
|
+
export interface OptionChainFilter {
|
|
139
|
+
inTheMoney?: boolean;
|
|
140
|
+
impliedVolatility?: Range;
|
|
141
|
+
openInterest?: Range;
|
|
142
|
+
greeks?: OptionChainFilterGreeks;
|
|
143
|
+
}
|
|
124
144
|
export interface OptionChain {
|
|
125
145
|
symbol: string;
|
|
126
146
|
expiry: number;
|
|
@@ -217,6 +237,42 @@ export interface CorporateAction {
|
|
|
217
237
|
fromFactor?: number;
|
|
218
238
|
toFactor?: number;
|
|
219
239
|
}
|
|
240
|
+
export interface CorporateSymbolChange {
|
|
241
|
+
symbol: string;
|
|
242
|
+
market?: string;
|
|
243
|
+
exchange?: string;
|
|
244
|
+
executeDate?: string;
|
|
245
|
+
actionType?: string;
|
|
246
|
+
oldSymbol?: string;
|
|
247
|
+
/** newSymbol is the ticker after the rename; same as symbol. */
|
|
248
|
+
newSymbol?: string;
|
|
249
|
+
}
|
|
250
|
+
export interface CorporateDelisting {
|
|
251
|
+
symbol: string;
|
|
252
|
+
market?: string;
|
|
253
|
+
exchange?: string;
|
|
254
|
+
executeDate?: string;
|
|
255
|
+
actionType?: string;
|
|
256
|
+
announcedDate?: string;
|
|
257
|
+
reason?: string;
|
|
258
|
+
}
|
|
259
|
+
export interface CorporateIPO {
|
|
260
|
+
symbol: string;
|
|
261
|
+
market?: string;
|
|
262
|
+
exchange?: string;
|
|
263
|
+
executeDate?: string;
|
|
264
|
+
actionType?: string;
|
|
265
|
+
ipoName?: string;
|
|
266
|
+
listingDate?: string;
|
|
267
|
+
listingPrice?: number;
|
|
268
|
+
sharesOutstanding?: number;
|
|
269
|
+
sharesFloat?: number;
|
|
270
|
+
offerAmount?: number;
|
|
271
|
+
priceRange?: string;
|
|
272
|
+
currency?: string;
|
|
273
|
+
minPurchaseQuantity?: number;
|
|
274
|
+
leverageRatio?: number;
|
|
275
|
+
}
|
|
220
276
|
export interface CapitalFlowItem {
|
|
221
277
|
time: string;
|
|
222
278
|
timestamp: number;
|