@tigeropenapi/tigeropen 0.5.0 → 0.5.4
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/client/token-methods.js +42 -0
- package/dist/cjs/config/client-config.js +59 -11
- 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/model/order-helpers.js +126 -21
- package/dist/cjs/quote/quote-client.js +112 -21
- package/dist/cjs/trade/trade-client.js +74 -16
- package/dist/esm/client/api-response.js +17 -15
- package/dist/esm/client/token-methods.js +37 -0
- package/dist/esm/config/client-config.js +59 -12
- 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/model/order-helpers.js +119 -20
- package/dist/esm/quote/quote-client.js +79 -21
- package/dist/esm/trade/trade-client.js +41 -16
- package/dist/types/client/api-response.d.ts +6 -5
- package/dist/types/client/token-methods.d.ts +34 -0
- 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-helpers.d.ts +48 -8
- package/dist/types/model/order.d.ts +52 -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 +31 -8
- package/dist/types/trade/trade-client.d.ts +19 -3
- package/package.json +1 -1
|
@@ -7,29 +7,33 @@ exports.unmarshalData = unmarshalData;
|
|
|
7
7
|
*/
|
|
8
8
|
const errors_1 = require("./errors");
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Replaces bare int64 values (≥17 digits, not part of a float) with quoted
|
|
11
|
+
* strings so they survive JSON.parse without precision loss.
|
|
12
|
+
* 17+ digits are guaranteed to exceed Number.MAX_SAFE_INTEGER (≈9.007e15),
|
|
13
|
+
* so 16-digit microsecond timestamps remain as numbers.
|
|
13
14
|
*/
|
|
14
15
|
function patchLargeIntegers(text) {
|
|
15
|
-
// Mask all existing JSON string values so their content isn't touched.
|
|
16
16
|
const strings = [];
|
|
17
17
|
const masked = text.replace(/"(?:[^"\\]|\\.)*"/g, (match) => {
|
|
18
18
|
strings.push(match);
|
|
19
19
|
return '\x01' + (strings.length - 1) + '\x01';
|
|
20
20
|
});
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
//
|
|
21
|
+
// Match bare integers preceded by a JSON structural character or line start,
|
|
22
|
+
// not followed by decimal point or exponent (avoids matching float components).
|
|
23
|
+
// The `m` flag makes `^` match line-start for multi-line JSON.
|
|
24
|
+
const patched = masked.replace(/([:,\[{]|^)\s*(-?\d{17,})(?![.\deE])/gm, (full, prefix, num) => {
|
|
25
|
+
return prefix + '"' + num + '"';
|
|
26
|
+
});
|
|
24
27
|
return patched.replace(/\x01(\d+)\x01/g, (_, i) => strings[parseInt(i, 10)]);
|
|
25
28
|
}
|
|
26
29
|
/**
|
|
27
|
-
* Parse the raw HTTP response body.
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
+
* Parse the raw HTTP response body. Throws TigerError when code != 0.
|
|
31
|
+
*
|
|
32
|
+
* patchLargeIntegers is applied before JSON.parse to preserve int64 order IDs
|
|
33
|
+
* (e.g. 28868646234578944) as strings rather than losing precision.
|
|
30
34
|
*/
|
|
31
35
|
function parseApiResponse(body) {
|
|
32
|
-
const resp = JSON.parse(body);
|
|
36
|
+
const resp = JSON.parse(patchLargeIntegers(body));
|
|
33
37
|
if (resp.code !== 0) {
|
|
34
38
|
throw new errors_1.TigerError(resp.code, resp.message);
|
|
35
39
|
}
|
|
@@ -37,15 +41,13 @@ function parseApiResponse(body) {
|
|
|
37
41
|
}
|
|
38
42
|
/**
|
|
39
43
|
* Decode an ApiResponse.data payload into a typed value.
|
|
40
|
-
* Handles
|
|
41
|
-
*
|
|
44
|
+
* Handles double-encoded JSON (where `data` is a JSON string wrapping JSON),
|
|
45
|
+
* seen on some trade endpoints.
|
|
42
46
|
*/
|
|
43
47
|
function unmarshalData(data) {
|
|
44
48
|
if (data == null)
|
|
45
49
|
return undefined;
|
|
46
50
|
if (typeof data === 'string') {
|
|
47
|
-
// Attempt to parse JSON string (double-encoded case).
|
|
48
|
-
// Patch large integers before parsing so int64 IDs survive as strings.
|
|
49
51
|
try {
|
|
50
52
|
return JSON.parse(patchLargeIntegers(data));
|
|
51
53
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.queryToken = queryToken;
|
|
4
|
+
exports.refreshToken = refreshToken;
|
|
5
|
+
exports.startTokenAutoRefresh = startTokenAutoRefresh;
|
|
6
|
+
/**
|
|
7
|
+
* Call the `user_token_refresh` API and return the new token string.
|
|
8
|
+
* Read-only: does NOT update the stored token.
|
|
9
|
+
* Use `refreshToken()` to also update the in-memory config and optionally persist.
|
|
10
|
+
*/
|
|
11
|
+
async function queryToken(httpClient) {
|
|
12
|
+
return httpClient.queryToken();
|
|
13
|
+
}
|
|
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
|
+
async function refreshToken(httpClient, tokenManager) {
|
|
22
|
+
return httpClient.refreshToken(tokenManager);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Start background token auto-refresh. Returns a TokenManager that can be
|
|
26
|
+
* used to stop the background task via `tm.stopAutoRefresh()`.
|
|
27
|
+
*
|
|
28
|
+
* @param httpClient - The underlying HTTP client
|
|
29
|
+
* @param refreshDurationSecs - Refresh threshold in seconds (minimum 30).
|
|
30
|
+
* When the token age exceeds this value the refresh is triggered.
|
|
31
|
+
* @param checkIntervalMs - How often to check whether a refresh is needed,
|
|
32
|
+
* in milliseconds. Defaults to 300 000 ms (5 minutes).
|
|
33
|
+
* @param tokenWriter - Optional callback invoked with the new token string
|
|
34
|
+
* after each successful refresh.
|
|
35
|
+
*/
|
|
36
|
+
function startTokenAutoRefresh(httpClient, refreshDurationSecs, checkIntervalMs, tokenWriter) {
|
|
37
|
+
return httpClient.startTokenAutoRefresh(null, {
|
|
38
|
+
refreshDuration: refreshDurationSecs,
|
|
39
|
+
refreshInterval: checkIntervalMs,
|
|
40
|
+
tokenWriter,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SANDBOX_TIGER_PUBLIC_KEY = void 0;
|
|
3
4
|
exports.loadPropertiesFile = loadPropertiesFile;
|
|
4
5
|
exports.createClientConfig = createClientConfig;
|
|
5
6
|
/**
|
|
@@ -26,6 +27,10 @@ const DEFAULT_TIMEOUT = 15;
|
|
|
26
27
|
const DEFAULT_SERVER_URL = 'https://openapi.tigerfintech.com/gateway';
|
|
27
28
|
/** Tiger public key for response signature verification (Base64-encoded) */
|
|
28
29
|
const TIGER_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNF3G8SoEcCZh2rshUbayDgLLrj6rKgzNMxDL2HSnKcB0+GPOsndqSv+a4IBu9+I3fyBp5hkyMMG2+AXugd9pMpy6VxJxlNjhX1MYbNTZJUT4nudki4uh+LMOkIBHOceGNXjgB+cXqmlUnjlqha/HgboeHSnSgpM3dKSJQlIOsDwIDAQAB';
|
|
30
|
+
/** Sandbox / QA tiger public key for response signature verification */
|
|
31
|
+
exports.SANDBOX_TIGER_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbm21i11hgAENGd3/f280PSe4g9YGkS3TEXBYMidihTvHHf' +
|
|
32
|
+
'+tJ0PYD0o3PruI0hl3qhEjHTAxb75T5YD3SGK4IBhHn/Rk6mhqlGgI+bBrBVYaXixmHfRo75RpUUuWACyeqQk' +
|
|
33
|
+
'ZckgR0McxuW9xRMIa2cXZOoL1E4SL4lXKGhKoWbwIDAQAB';
|
|
29
34
|
/** Environment variable names */
|
|
30
35
|
const ENV_TIGER_ID = 'TIGEROPEN_TIGER_ID';
|
|
31
36
|
const ENV_PRIVATE_KEY = 'TIGEROPEN_PRIVATE_KEY';
|
|
@@ -33,6 +38,9 @@ const ENV_ACCOUNT = 'TIGEROPEN_ACCOUNT';
|
|
|
33
38
|
const ENV_SECRET_KEY = 'TIGEROPEN_SECRET_KEY';
|
|
34
39
|
const ENV_TOKEN = 'TIGEROPEN_TOKEN';
|
|
35
40
|
const ENV_TOKEN_FILE = 'TIGEROPEN_TOKEN_FILE';
|
|
41
|
+
const ENV_TIGER_PUBLIC_KEY = 'TIGEROPEN_TIGER_PUBLIC_KEY';
|
|
42
|
+
const ENV_SERVER_URL = 'TIGEROPEN_SERVER_URL';
|
|
43
|
+
const ENV_QUOTE_SERVER_URL = 'TIGEROPEN_QUOTE_SERVER_URL';
|
|
36
44
|
/**
|
|
37
45
|
* Load and parse a Java-style properties file.
|
|
38
46
|
*
|
|
@@ -105,23 +113,32 @@ function createClientConfig(options) {
|
|
|
105
113
|
const opts = options ?? {};
|
|
106
114
|
// Load properties: explicit path > auto-discovery
|
|
107
115
|
let fileProps = {};
|
|
116
|
+
let configFileDir;
|
|
108
117
|
if (opts.propertiesFilePath) {
|
|
109
118
|
// Support both directory path and full file path
|
|
110
119
|
let filePath = opts.propertiesFilePath;
|
|
111
120
|
if ((0, fs_1.existsSync)(filePath) && (0, fs_1.statSync)(filePath).isDirectory()) {
|
|
121
|
+
configFileDir = filePath;
|
|
112
122
|
filePath = (0, path_1.join)(filePath, CONFIG_FILE_NAME);
|
|
113
123
|
}
|
|
114
124
|
else if (!(0, fs_1.existsSync)(filePath) && !filePath.endsWith('.properties')) {
|
|
115
125
|
// Path doesn't exist as-is; try treating it as a directory
|
|
116
126
|
const asDir = (0, path_1.join)(filePath, CONFIG_FILE_NAME);
|
|
117
|
-
if ((0, fs_1.existsSync)(asDir))
|
|
127
|
+
if ((0, fs_1.existsSync)(asDir)) {
|
|
128
|
+
configFileDir = filePath;
|
|
118
129
|
filePath = asDir;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// It's a file path: derive directory from it
|
|
134
|
+
configFileDir = (0, path_1.dirname)(filePath);
|
|
119
135
|
}
|
|
120
136
|
fileProps = loadPropertiesFile(filePath);
|
|
121
137
|
}
|
|
122
138
|
else {
|
|
123
139
|
const discovered = discoverConfigFile();
|
|
124
140
|
if (discovered) {
|
|
141
|
+
configFileDir = (0, path_1.dirname)(discovered);
|
|
125
142
|
fileProps = loadPropertiesFile(discovered);
|
|
126
143
|
}
|
|
127
144
|
}
|
|
@@ -134,12 +151,15 @@ function createClientConfig(options) {
|
|
|
134
151
|
const license = opts.license || fileProps['license'];
|
|
135
152
|
const language = opts.language || fileProps['language'] || DEFAULT_LANGUAGE;
|
|
136
153
|
const timezone = opts.timezone || fileProps['timezone'];
|
|
154
|
+
// tiger_public_key from properties file (e.g. for QA/sandbox environments)
|
|
155
|
+
let tigerPublicKey = opts.tigerPublicKey || fileProps['tiger_public_key'] || TIGER_PUBLIC_KEY;
|
|
137
156
|
// Environment variables override everything
|
|
138
157
|
const envTigerId = process.env[ENV_TIGER_ID];
|
|
139
158
|
const envPrivateKey = process.env[ENV_PRIVATE_KEY];
|
|
140
159
|
const envAccount = process.env[ENV_ACCOUNT];
|
|
141
160
|
const envSecretKey = process.env[ENV_SECRET_KEY];
|
|
142
161
|
const envToken = process.env[ENV_TOKEN];
|
|
162
|
+
const envTigerPublicKey = process.env[ENV_TIGER_PUBLIC_KEY];
|
|
143
163
|
if (envTigerId) {
|
|
144
164
|
tigerId = envTigerId;
|
|
145
165
|
}
|
|
@@ -155,6 +175,9 @@ function createClientConfig(options) {
|
|
|
155
175
|
if (envToken) {
|
|
156
176
|
token = envToken;
|
|
157
177
|
}
|
|
178
|
+
if (envTigerPublicKey) {
|
|
179
|
+
tigerPublicKey = envTigerPublicKey;
|
|
180
|
+
}
|
|
158
181
|
// Token loading priority: env TIGEROPEN_TOKEN > tokenLoader > token file (TIGEROPEN_TOKEN_FILE or default)
|
|
159
182
|
if (!token) {
|
|
160
183
|
if (opts.tokenLoader) {
|
|
@@ -175,8 +198,9 @@ function createClientConfig(options) {
|
|
|
175
198
|
}
|
|
176
199
|
}
|
|
177
200
|
else {
|
|
178
|
-
// Load from token file: TIGEROPEN_TOKEN_FILE env var > default
|
|
179
|
-
const tokenFilePath = process.env[ENV_TOKEN_FILE]
|
|
201
|
+
// Load from token file: TIGEROPEN_TOKEN_FILE env var > config dir > default
|
|
202
|
+
const tokenFilePath = process.env[ENV_TOKEN_FILE]
|
|
203
|
+
|| (configFileDir ? (0, path_1.join)(configFileDir, 'tiger_openapi_token.properties') : 'tiger_openapi_token.properties');
|
|
180
204
|
const tm = new token_manager_1.TokenManager({ filePath: tokenFilePath });
|
|
181
205
|
try {
|
|
182
206
|
token = tm.loadTokenSync();
|
|
@@ -193,29 +217,53 @@ function createClientConfig(options) {
|
|
|
193
217
|
if (!privateKey) {
|
|
194
218
|
throw new Error(`privateKey is required. Set it via options.privateKey, a config file, or the ${ENV_PRIVATE_KEY} environment variable.`);
|
|
195
219
|
}
|
|
196
|
-
// Resolve server URL: explicit > dynamic domain > default
|
|
220
|
+
// Resolve server URL: env var > explicit opts > file > dynamic domain > default
|
|
197
221
|
const enableDynamicDomain = opts.enableDynamicDomain ?? true;
|
|
198
222
|
let serverUrl;
|
|
199
223
|
let quoteServerUrl;
|
|
200
224
|
// Query dynamic domains once (may spawn a child process); reuse for both URLs.
|
|
201
225
|
let domainConf = {};
|
|
202
|
-
|
|
226
|
+
const envServerUrl = process.env[ENV_SERVER_URL];
|
|
227
|
+
const envQuoteServerUrl = process.env[ENV_QUOTE_SERVER_URL];
|
|
228
|
+
const needServerUrl = !envServerUrl && !opts.serverUrl && !fileProps['server_url'];
|
|
229
|
+
const needQuoteServerUrl = !envQuoteServerUrl && !opts.quoteServerUrl && !fileProps['quote_server_url'];
|
|
230
|
+
if (enableDynamicDomain && (needServerUrl || needQuoteServerUrl)) {
|
|
203
231
|
domainConf = (0, domain_1.queryDomains)(license);
|
|
204
232
|
}
|
|
205
|
-
if (
|
|
233
|
+
if (envServerUrl) {
|
|
234
|
+
serverUrl = envServerUrl;
|
|
235
|
+
}
|
|
236
|
+
else if (opts.serverUrl) {
|
|
206
237
|
serverUrl = opts.serverUrl;
|
|
207
238
|
}
|
|
239
|
+
else if (fileProps['server_url']) {
|
|
240
|
+
serverUrl = fileProps['server_url'];
|
|
241
|
+
}
|
|
208
242
|
else {
|
|
209
243
|
const dynamicUrl = (0, domain_1.resolveDynamicServerUrl)(domainConf, license);
|
|
210
244
|
serverUrl = dynamicUrl || DEFAULT_SERVER_URL;
|
|
211
245
|
}
|
|
212
|
-
// Resolve quote server URL: explicit > dynamic domain > serverUrl fallback
|
|
213
|
-
if (
|
|
246
|
+
// Resolve quote server URL: env var > explicit opts > file > dynamic domain > serverUrl fallback
|
|
247
|
+
if (envQuoteServerUrl) {
|
|
248
|
+
quoteServerUrl = envQuoteServerUrl;
|
|
249
|
+
}
|
|
250
|
+
else if (opts.quoteServerUrl) {
|
|
214
251
|
quoteServerUrl = opts.quoteServerUrl;
|
|
215
252
|
}
|
|
253
|
+
else if (fileProps['quote_server_url']) {
|
|
254
|
+
quoteServerUrl = fileProps['quote_server_url'];
|
|
255
|
+
}
|
|
216
256
|
else {
|
|
217
|
-
|
|
218
|
-
|
|
257
|
+
// Only use dynamic domain if serverUrl itself came from dynamic resolution (not pinned by env/opts/file).
|
|
258
|
+
// When serverUrl is pinned, prefer it as the quote fallback to avoid mixing environments.
|
|
259
|
+
const serverUrlPinned = !!(envServerUrl || opts.serverUrl || fileProps['server_url']);
|
|
260
|
+
if (!serverUrlPinned) {
|
|
261
|
+
const dynamicQuoteUrl = (0, domain_1.resolveDynamicQuoteServerUrl)(domainConf, license);
|
|
262
|
+
quoteServerUrl = dynamicQuoteUrl || serverUrl;
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
quoteServerUrl = serverUrl;
|
|
266
|
+
}
|
|
219
267
|
}
|
|
220
268
|
return {
|
|
221
269
|
tigerId,
|
|
@@ -234,7 +282,7 @@ function createClientConfig(options) {
|
|
|
234
282
|
serverUrl,
|
|
235
283
|
quoteServerUrl,
|
|
236
284
|
deviceId: detectDeviceId(),
|
|
237
|
-
tigerPublicKey
|
|
285
|
+
tigerPublicKey,
|
|
238
286
|
};
|
|
239
287
|
}
|
|
240
288
|
/**
|
|
@@ -70,34 +70,34 @@ function parsePropertiesString(content) {
|
|
|
70
70
|
let continuation = false;
|
|
71
71
|
for (const rawLine of lines) {
|
|
72
72
|
if (continuation) {
|
|
73
|
-
// 续行:去除前导空格后拼接
|
|
74
73
|
const trimmedLeft = rawLine.replace(/^[ \t]+/, '');
|
|
75
|
-
if (trimmedLeft.
|
|
74
|
+
if (trimmedLeft === '' || trimmedLeft.startsWith('#') || trimmedLeft.startsWith('!')) {
|
|
75
|
+
continuation = false;
|
|
76
|
+
}
|
|
77
|
+
else if (endsWithContinuation(trimmedLeft)) {
|
|
76
78
|
currentLine += trimmedLeft.slice(0, -1);
|
|
77
79
|
continue;
|
|
78
80
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
else {
|
|
82
|
+
currentLine += trimmedLeft;
|
|
83
|
+
continuation = false;
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
else {
|
|
83
87
|
const trimmed = rawLine.trim();
|
|
84
|
-
// 跳过空行
|
|
85
88
|
if (trimmed === '') {
|
|
86
89
|
continue;
|
|
87
90
|
}
|
|
88
|
-
// 跳过注释行
|
|
89
91
|
if (trimmed.startsWith('#') || trimmed.startsWith('!')) {
|
|
90
92
|
continue;
|
|
91
93
|
}
|
|
92
|
-
|
|
93
|
-
if (trimmed.endsWith('\\')) {
|
|
94
|
+
if (endsWithContinuation(trimmed)) {
|
|
94
95
|
currentLine = trimmed.slice(0, -1);
|
|
95
96
|
continuation = true;
|
|
96
97
|
continue;
|
|
97
98
|
}
|
|
98
99
|
currentLine = trimmed;
|
|
99
100
|
}
|
|
100
|
-
// 解析键值对
|
|
101
101
|
const result = parseKeyValue(currentLine);
|
|
102
102
|
if (result) {
|
|
103
103
|
props[result[0]] = result[1];
|
|
@@ -113,6 +113,16 @@ function parsePropertiesString(content) {
|
|
|
113
113
|
}
|
|
114
114
|
return props;
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* 判断一行是否以续行标记结尾(奇数个末尾反斜杠)。
|
|
118
|
+
*/
|
|
119
|
+
function endsWithContinuation(line) {
|
|
120
|
+
let count = 0;
|
|
121
|
+
for (let i = line.length - 1; i >= 0 && line[i] === '\\'; i--) {
|
|
122
|
+
count++;
|
|
123
|
+
}
|
|
124
|
+
return count % 2 === 1;
|
|
125
|
+
}
|
|
116
126
|
/**
|
|
117
127
|
* 解析单行键值对,支持 = 和 : 分隔符。
|
|
118
128
|
* 值中可以包含 = 或 :,只按第一个分隔符拆分。
|
package/dist/cjs/config/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveDynamicQuoteServerUrl = exports.resolveDynamicServerUrl = exports.queryDomains = exports.TokenManager = exports.loadPropertiesFile = exports.createClientConfig = exports.parsePropertiesString = exports.parsePropertiesFile = void 0;
|
|
3
|
+
exports.resolveDynamicQuoteServerUrl = exports.resolveDynamicServerUrl = exports.queryDomains = exports.TokenManager = exports.SANDBOX_TIGER_PUBLIC_KEY = exports.loadPropertiesFile = exports.createClientConfig = exports.parsePropertiesString = exports.parsePropertiesFile = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* 配置层导出
|
|
6
6
|
*/
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "parsePropertiesString", { enumerable: true, get:
|
|
|
10
10
|
var client_config_1 = require("./client-config");
|
|
11
11
|
Object.defineProperty(exports, "createClientConfig", { enumerable: true, get: function () { return client_config_1.createClientConfig; } });
|
|
12
12
|
Object.defineProperty(exports, "loadPropertiesFile", { enumerable: true, get: function () { return client_config_1.loadPropertiesFile; } });
|
|
13
|
+
Object.defineProperty(exports, "SANDBOX_TIGER_PUBLIC_KEY", { enumerable: true, get: function () { return client_config_1.SANDBOX_TIGER_PUBLIC_KEY; } });
|
|
13
14
|
var token_manager_1 = require("./token-manager");
|
|
14
15
|
Object.defineProperty(exports, "TokenManager", { enumerable: true, get: function () { return token_manager_1.TokenManager; } });
|
|
15
16
|
var domain_1 = require("./domain");
|
package/dist/cjs/index.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* @packageDocumentation
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.orderStatusCode = exports.BarPeriod = exports.License = exports.Language = exports.FinancialReportPeriod = exports.OptionAnalysisPeriod = exports.SortDirection = exports.IndustryLevel = exports.CorporateActionType = exports.OrderSortBy = exports.SegmentType = exports.QuoteRight = exports.Currency = exports.Market = exports.TimeInForce = exports.OrderType = exports.SecurityType = exports.OrderStatus = exports.normalizeOrderStatus = exports.stopLimitOrder = exports.stopOrder = exports.limitOrder = exports.marketOrder = exports.SubjectType = exports.ConnectionState = exports.PushClient = exports.TradeClient = exports.parseOptionIdentifier = exports.QuoteClient = exports.classifyErrorCode = exports.TigerError = exports.HttpClient = exports.TokenManager = exports.loadPropertiesFile = exports.createClientConfig = exports.VERSION = void 0;
|
|
19
|
+
exports.orderStatusCode = exports.BarPeriod = exports.License = exports.Language = exports.FinancialReportPeriod = exports.OptionAnalysisPeriod = exports.SortDirection = exports.IndustryLevel = exports.CorporateActionType = exports.OrderSortBy = exports.SegmentType = exports.QuoteRight = exports.Currency = exports.Market = exports.TimeInForce = exports.OrderType = exports.SecurityType = exports.OrderStatus = exports.normalizeOrderStatus = exports.stopLimitOrder = exports.stopOrder = exports.limitOrder = exports.marketOrder = exports.SubjectType = exports.ConnectionState = exports.PushClient = exports.TradeClient = exports.parseOptionIdentifier = exports.QuoteClient = exports.classifyErrorCode = exports.TigerError = exports.HttpClient = exports.TokenManager = exports.SANDBOX_TIGER_PUBLIC_KEY = exports.loadPropertiesFile = exports.createClientConfig = exports.VERSION = void 0;
|
|
20
20
|
/** SDK 版本号 */
|
|
21
21
|
var version_1 = require("./version");
|
|
22
22
|
Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return version_1.SDK_VERSION; } });
|
|
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () {
|
|
|
24
24
|
var config_1 = require("./config");
|
|
25
25
|
Object.defineProperty(exports, "createClientConfig", { enumerable: true, get: function () { return config_1.createClientConfig; } });
|
|
26
26
|
Object.defineProperty(exports, "loadPropertiesFile", { enumerable: true, get: function () { return config_1.loadPropertiesFile; } });
|
|
27
|
+
Object.defineProperty(exports, "SANDBOX_TIGER_PUBLIC_KEY", { enumerable: true, get: function () { return config_1.SANDBOX_TIGER_PUBLIC_KEY; } });
|
|
27
28
|
var config_2 = require("./config");
|
|
28
29
|
Object.defineProperty(exports, "TokenManager", { enumerable: true, get: function () { return config_2.TokenManager; } });
|
|
29
30
|
// Transport
|
package/dist/cjs/model/enums.js
CHANGED
|
@@ -150,6 +150,7 @@ var TimeInForce;
|
|
|
150
150
|
(function (TimeInForce) {
|
|
151
151
|
TimeInForce["DAY"] = "DAY";
|
|
152
152
|
TimeInForce["GTC"] = "GTC";
|
|
153
|
+
TimeInForce["GTD"] = "GTD";
|
|
153
154
|
TimeInForce["OPG"] = "OPG";
|
|
154
155
|
})(TimeInForce || (exports.TimeInForce = TimeInForce = {}));
|
|
155
156
|
/** 订单排序字段 */
|
|
@@ -172,6 +173,9 @@ var CorporateActionType;
|
|
|
172
173
|
CorporateActionType["Split"] = "split";
|
|
173
174
|
CorporateActionType["Dividend"] = "dividend";
|
|
174
175
|
CorporateActionType["Earning"] = "earning";
|
|
176
|
+
CorporateActionType["SymbolChange"] = "symbol_change";
|
|
177
|
+
CorporateActionType["Delisting"] = "delisting";
|
|
178
|
+
CorporateActionType["IPO"] = "ipo";
|
|
175
179
|
})(CorporateActionType || (exports.CorporateActionType = CorporateActionType = {}));
|
|
176
180
|
/** 行业级别 (1~4 级) */
|
|
177
181
|
var IndustryLevel;
|
|
@@ -9,8 +9,14 @@ exports.auctionLimitOrder = auctionLimitOrder;
|
|
|
9
9
|
exports.auctionMarketOrder = auctionMarketOrder;
|
|
10
10
|
exports.algoOrder = algoOrder;
|
|
11
11
|
exports.icebergOrder = icebergOrder;
|
|
12
|
-
exports.icebergOrderFull = icebergOrderFull;
|
|
13
12
|
exports.orderLeg = orderLeg;
|
|
13
|
+
exports.marketOrderByAmount = marketOrderByAmount;
|
|
14
|
+
exports.limitOrderByAmount = limitOrderByAmount;
|
|
15
|
+
exports.trailOrderByPrice = trailOrderByPrice;
|
|
16
|
+
exports.limitOrderWithLegs = limitOrderWithLegs;
|
|
17
|
+
exports.comboOrder = comboOrder;
|
|
18
|
+
exports.ocaOrder = ocaOrder;
|
|
19
|
+
exports.contractLeg = contractLeg;
|
|
14
20
|
const enums_1 = require("./enums");
|
|
15
21
|
/** Market order */
|
|
16
22
|
function marketOrder(account, symbol, secType, action, quantity) {
|
|
@@ -101,26 +107,11 @@ function algoOrder(account, symbol, secType, action, quantity, limitPrice, algoT
|
|
|
101
107
|
};
|
|
102
108
|
}
|
|
103
109
|
/**
|
|
104
|
-
* Iceberg order
|
|
105
|
-
|
|
106
|
-
function icebergOrder(account, symbol, secType, action, quantity, limitPrice, displaySize) {
|
|
107
|
-
return {
|
|
108
|
-
account, symbol, secType, action,
|
|
109
|
-
orderType: enums_1.OrderType.ICEBERG,
|
|
110
|
-
totalQuantity: quantity,
|
|
111
|
-
limitPrice,
|
|
112
|
-
timeInForce: enums_1.TimeInForce.DAY,
|
|
113
|
-
outsideRth: false,
|
|
114
|
-
displaySize,
|
|
115
|
-
priceType: enums_1.PriceType.LIMIT_PRICE,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Iceberg order (full params).
|
|
120
|
-
* Pass `priceType` as empty string to use server default (LIMIT_PRICE).
|
|
110
|
+
* Iceberg order. `displaySize` is required; all other parameters are optional.
|
|
111
|
+
* Pass `priceType` as empty string to use the server default (LIMIT_PRICE).
|
|
121
112
|
* Pass `startTime` / `endTime` as 0 to omit the time window.
|
|
122
113
|
*/
|
|
123
|
-
function
|
|
114
|
+
function icebergOrder(account, symbol, secType, action, quantity, limitPrice, displaySize, minDisplaySize, checkIntervals, priceType, startTime, endTime) {
|
|
124
115
|
const req = {
|
|
125
116
|
account, symbol, secType, action,
|
|
126
117
|
orderType: enums_1.OrderType.ICEBERG,
|
|
@@ -129,13 +120,12 @@ function icebergOrderFull(account, symbol, secType, action, quantity, limitPrice
|
|
|
129
120
|
timeInForce: enums_1.TimeInForce.DAY,
|
|
130
121
|
outsideRth: false,
|
|
131
122
|
displaySize,
|
|
123
|
+
priceType: priceType || enums_1.PriceType.LIMIT_PRICE,
|
|
132
124
|
};
|
|
133
125
|
if (minDisplaySize !== undefined && minDisplaySize > 0)
|
|
134
126
|
req.minDisplaySize = minDisplaySize;
|
|
135
127
|
if (checkIntervals !== undefined && checkIntervals > 0)
|
|
136
128
|
req.checkIntervals = checkIntervals;
|
|
137
|
-
if (priceType)
|
|
138
|
-
req.priceType = priceType;
|
|
139
129
|
if (startTime && startTime > 0)
|
|
140
130
|
req.startTime = startTime;
|
|
141
131
|
if (endTime && endTime > 0)
|
|
@@ -146,3 +136,118 @@ function icebergOrderFull(account, symbol, secType, action, quantity, limitPrice
|
|
|
146
136
|
function orderLeg(legType, price, timeInForce) {
|
|
147
137
|
return { legType, price, timeInForce };
|
|
148
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Market order by cash amount (instead of quantity).
|
|
141
|
+
* Server uses `isQuantityByAmount=true` + `amount` field.
|
|
142
|
+
*/
|
|
143
|
+
function marketOrderByAmount(account, symbol, secType, action, amount) {
|
|
144
|
+
return {
|
|
145
|
+
account, symbol, secType, action,
|
|
146
|
+
orderType: enums_1.OrderType.MKT,
|
|
147
|
+
totalQuantity: 0,
|
|
148
|
+
cashAmount: amount,
|
|
149
|
+
timeInForce: enums_1.TimeInForce.DAY,
|
|
150
|
+
outsideRth: false,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Limit order by cash amount (instead of quantity).
|
|
155
|
+
*/
|
|
156
|
+
function limitOrderByAmount(account, symbol, secType, action, amount, limitPrice) {
|
|
157
|
+
return {
|
|
158
|
+
account, symbol, secType, action,
|
|
159
|
+
orderType: enums_1.OrderType.LMT,
|
|
160
|
+
totalQuantity: 0,
|
|
161
|
+
cashAmount: amount,
|
|
162
|
+
limitPrice,
|
|
163
|
+
timeInForce: enums_1.TimeInForce.DAY,
|
|
164
|
+
outsideRth: false,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Trailing stop order using a fixed price offset (auxPrice) instead of a percentage.
|
|
169
|
+
* Use `trailOrder()` for percentage-based trailing stops.
|
|
170
|
+
*/
|
|
171
|
+
function trailOrderByPrice(account, symbol, secType, action, quantity, auxPrice) {
|
|
172
|
+
return {
|
|
173
|
+
account, symbol, secType, action,
|
|
174
|
+
orderType: enums_1.OrderType.TRAIL,
|
|
175
|
+
totalQuantity: quantity,
|
|
176
|
+
auxPrice,
|
|
177
|
+
timeInForce: enums_1.TimeInForce.DAY,
|
|
178
|
+
outsideRth: false,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Limit order with attached profit/loss legs (bracket order).
|
|
183
|
+
* At most 2 legs are supported.
|
|
184
|
+
*
|
|
185
|
+
* @param orderLegs - Array of `OrderLegRequest` (use `orderLeg()` helper)
|
|
186
|
+
*/
|
|
187
|
+
function limitOrderWithLegs(account, symbol, secType, action, quantity, limitPrice, orderLegs) {
|
|
188
|
+
if (orderLegs.length === 0) {
|
|
189
|
+
throw new Error('At least 1 order leg is required for a bracket order');
|
|
190
|
+
}
|
|
191
|
+
if (orderLegs.length > 2) {
|
|
192
|
+
throw new Error('At most 2 order legs are supported');
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
account, symbol, secType, action,
|
|
196
|
+
orderType: enums_1.OrderType.LMT,
|
|
197
|
+
totalQuantity: quantity,
|
|
198
|
+
limitPrice,
|
|
199
|
+
orderLegs,
|
|
200
|
+
timeInForce: enums_1.TimeInForce.DAY,
|
|
201
|
+
outsideRth: false,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Multi-leg (combo/MLEG) order for options combos.
|
|
206
|
+
*
|
|
207
|
+
* @param contractLegs - Array of `ContractLegRequest` (use `contractLeg()` helper)
|
|
208
|
+
* @param comboType - e.g. `'MLEG'`
|
|
209
|
+
*/
|
|
210
|
+
function comboOrder(account, action, quantity, orderType, contractLegs, comboType = 'MLEG', limitPrice, auxPrice, trailingPercent) {
|
|
211
|
+
return {
|
|
212
|
+
account,
|
|
213
|
+
symbol: '', // not used for combo orders
|
|
214
|
+
secType: 'MLEG',
|
|
215
|
+
action,
|
|
216
|
+
orderType,
|
|
217
|
+
totalQuantity: quantity,
|
|
218
|
+
limitPrice,
|
|
219
|
+
auxPrice,
|
|
220
|
+
trailingPercent,
|
|
221
|
+
contractLegs,
|
|
222
|
+
comboType,
|
|
223
|
+
timeInForce: enums_1.TimeInForce.DAY,
|
|
224
|
+
outsideRth: false,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* OCA (One-Cancels-All) order.
|
|
229
|
+
* Server expects `orderType: 'OCA'` and an `ocaOrders` list.
|
|
230
|
+
*
|
|
231
|
+
* @param ocaOrders - The contained orders (use any order helper to build each)
|
|
232
|
+
*/
|
|
233
|
+
function ocaOrder(account, symbol, secType, action, quantity, ocaOrders) {
|
|
234
|
+
return {
|
|
235
|
+
account, symbol, secType, action,
|
|
236
|
+
orderType: enums_1.OrderType.OCA,
|
|
237
|
+
totalQuantity: quantity,
|
|
238
|
+
ocaOrders,
|
|
239
|
+
timeInForce: enums_1.TimeInForce.DAY,
|
|
240
|
+
outsideRth: false,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Build a single leg for a multi-leg (MLEG / combo) order.
|
|
245
|
+
*
|
|
246
|
+
* @param symbol - Underlying symbol
|
|
247
|
+
* @param secType - Security type (e.g. `'OPT'`)
|
|
248
|
+
* @param action - `'BUY'` or `'SELL'`
|
|
249
|
+
* @param ratio - Number of contracts for this leg
|
|
250
|
+
*/
|
|
251
|
+
function contractLeg(symbol, secType, action, ratio, expiry, strike, right) {
|
|
252
|
+
return { symbol, secType, action, ratio, expiry, strike, right };
|
|
253
|
+
}
|