@tigeropenapi/tigeropen 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +475 -104
- package/dist/cjs/client/api-request.js +16 -10
- package/dist/cjs/client/api-response.js +23 -3
- package/dist/cjs/client/case-convert.js +35 -0
- package/dist/cjs/client/http-client.js +46 -20
- package/dist/cjs/client/index.js +6 -2
- package/dist/cjs/config/client-config.js +130 -49
- package/dist/cjs/config/domain.js +21 -2
- package/dist/cjs/config/index.js +3 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/model/contract.js +1 -2
- package/dist/cjs/model/order-helpers.js +9 -9
- package/dist/cjs/model/order.js +5 -2
- package/dist/cjs/model/position.js +1 -2
- package/dist/cjs/model/quote.js +7 -0
- package/dist/cjs/model/trade.js +2 -0
- package/dist/cjs/push/index.js +6 -3
- package/dist/cjs/push/pb/AssetData.js +208 -0
- package/dist/cjs/push/pb/KlineData.js +184 -0
- package/dist/cjs/push/pb/OptionTopData.js +427 -0
- package/dist/cjs/push/pb/OrderStatusData.js +568 -0
- package/dist/cjs/push/pb/OrderTransactionData.js +256 -0
- package/dist/cjs/push/pb/PositionData.js +316 -0
- package/dist/cjs/push/pb/PushData.js +219 -0
- package/dist/cjs/push/pb/QuoteBBOData.js +160 -0
- package/dist/cjs/push/pb/QuoteBasicData.js +329 -0
- package/dist/cjs/push/pb/QuoteData.js +507 -0
- package/dist/cjs/push/pb/QuoteDepthData.js +220 -0
- package/dist/cjs/push/pb/Request.js +278 -0
- package/dist/cjs/push/pb/Response.js +97 -0
- package/dist/cjs/push/pb/SocketCommon.js +86 -0
- package/dist/cjs/push/pb/StockTopData.js +199 -0
- package/dist/cjs/push/pb/TickData.js +202 -0
- package/dist/cjs/push/pb/TradeTickData.js +308 -0
- package/dist/cjs/push/pb/index.js +49 -0
- package/dist/cjs/push/proto-message.js +129 -0
- package/dist/cjs/push/push-client.js +292 -164
- package/dist/cjs/push/push-message.js +4 -60
- package/dist/cjs/push/varint.js +76 -0
- package/dist/cjs/quote/index.js +3 -2
- package/dist/cjs/quote/quote-client.js +128 -94
- package/dist/cjs/signer/signer.js +10 -10
- package/dist/cjs/trade/trade-client.js +56 -62
- package/dist/esm/client/api-request.js +14 -8
- package/dist/esm/client/api-response.js +22 -3
- package/dist/esm/client/case-convert.js +31 -0
- package/dist/esm/client/http-client.js +47 -21
- package/dist/esm/client/index.js +3 -2
- package/dist/esm/config/client-config.js +131 -51
- package/dist/esm/config/domain.js +20 -2
- package/dist/esm/config/index.js +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/model/contract.js +1 -2
- package/dist/esm/model/order-helpers.js +9 -9
- package/dist/esm/model/order.js +5 -2
- package/dist/esm/model/position.js +1 -2
- package/dist/esm/model/quote.js +6 -0
- package/dist/esm/model/trade.js +1 -0
- package/dist/esm/push/index.js +4 -2
- package/dist/esm/push/pb/AssetData.js +205 -0
- package/dist/esm/push/pb/KlineData.js +181 -0
- package/dist/esm/push/pb/OptionTopData.js +424 -0
- package/dist/esm/push/pb/OrderStatusData.js +565 -0
- package/dist/esm/push/pb/OrderTransactionData.js +253 -0
- package/dist/esm/push/pb/PositionData.js +313 -0
- package/dist/esm/push/pb/PushData.js +216 -0
- package/dist/esm/push/pb/QuoteBBOData.js +157 -0
- package/dist/esm/push/pb/QuoteBasicData.js +326 -0
- package/dist/esm/push/pb/QuoteData.js +504 -0
- package/dist/esm/push/pb/QuoteDepthData.js +217 -0
- package/dist/esm/push/pb/Request.js +275 -0
- package/dist/esm/push/pb/Response.js +94 -0
- package/dist/esm/push/pb/SocketCommon.js +83 -0
- package/dist/esm/push/pb/StockTopData.js +196 -0
- package/dist/esm/push/pb/TickData.js +199 -0
- package/dist/esm/push/pb/TradeTickData.js +305 -0
- package/dist/esm/push/pb/index.js +25 -0
- package/dist/esm/push/proto-message.js +121 -0
- package/dist/esm/push/push-client.js +260 -165
- package/dist/esm/push/push-message.js +3 -56
- package/dist/esm/push/varint.js +72 -0
- package/dist/esm/quote/index.js +2 -2
- package/dist/esm/quote/quote-client.js +127 -94
- package/dist/esm/signer/signer.js +10 -10
- package/dist/esm/trade/trade-client.js +56 -62
- package/dist/types/client/api-request.d.ts +12 -11
- package/dist/types/client/api-response.d.ts +15 -7
- package/dist/types/client/case-convert.d.ts +16 -0
- package/dist/types/client/http-client.d.ts +26 -14
- package/dist/types/client/index.d.ts +3 -2
- package/dist/types/config/client-config.d.ts +29 -13
- package/dist/types/config/domain.d.ts +9 -0
- package/dist/types/config/index.d.ts +2 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/model/contract.d.ts +13 -29
- package/dist/types/model/order-helpers.d.ts +21 -20
- package/dist/types/model/order.d.ts +101 -55
- package/dist/types/model/position.d.ts +26 -24
- package/dist/types/model/quote.d.ts +311 -0
- package/dist/types/model/trade.d.ts +113 -0
- package/dist/types/push/callbacks.d.ts +32 -51
- package/dist/types/push/index.d.ts +5 -3
- package/dist/types/push/pb/AssetData.d.ts +47 -0
- package/dist/types/push/pb/KlineData.d.ts +43 -0
- package/dist/types/push/pb/OptionTopData.d.ts +76 -0
- package/dist/types/push/pb/OrderStatusData.d.ts +96 -0
- package/dist/types/push/pb/OrderTransactionData.d.ts +51 -0
- package/dist/types/push/pb/PositionData.d.ts +63 -0
- package/dist/types/push/pb/PushData.d.ts +46 -0
- package/dist/types/push/pb/QuoteBBOData.d.ts +35 -0
- package/dist/types/push/pb/QuoteBasicData.d.ts +66 -0
- package/dist/types/push/pb/QuoteData.d.ts +94 -0
- package/dist/types/push/pb/QuoteDepthData.d.ts +37 -0
- package/dist/types/push/pb/Request.d.ts +44 -0
- package/dist/types/push/pb/Response.d.ts +30 -0
- package/dist/types/push/pb/SocketCommon.d.ts +64 -0
- package/dist/types/push/pb/StockTopData.d.ts +37 -0
- package/dist/types/push/pb/TickData.d.ts +44 -0
- package/dist/types/push/pb/TradeTickData.d.ts +53 -0
- package/dist/types/push/pb/index.d.ts +39 -0
- package/dist/types/push/proto-message.d.ts +33 -0
- package/dist/types/push/push-client.d.ts +69 -68
- package/dist/types/push/push-message.d.ts +3 -147
- package/dist/types/push/varint.d.ts +23 -0
- package/dist/types/quote/index.d.ts +2 -2
- package/dist/types/quote/quote-client.d.ts +41 -47
- package/dist/types/signer/signer.d.ts +6 -6
- package/dist/types/trade/trade-client.d.ts +34 -38
- package/package.json +11 -6
|
@@ -1,45 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* 推送消息类型定义
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* 仅保留 SubjectType 枚举,用于订阅/退订 API。
|
|
6
|
+
* JSON 消息类型定义和序列化函数已移除,改用 Protobuf 协议。
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.SubjectType =
|
|
10
|
-
exports.createPushMessage = createPushMessage;
|
|
11
|
-
exports.serializeMessage = serializeMessage;
|
|
12
|
-
exports.deserializeMessage = deserializeMessage;
|
|
13
|
-
/** 推送消息类型 */
|
|
14
|
-
var MessageType;
|
|
15
|
-
(function (MessageType) {
|
|
16
|
-
// 连接相关
|
|
17
|
-
MessageType["Connect"] = "connect";
|
|
18
|
-
MessageType["Connected"] = "connected";
|
|
19
|
-
MessageType["Disconnect"] = "disconnect";
|
|
20
|
-
MessageType["Heartbeat"] = "heartbeat";
|
|
21
|
-
MessageType["Kickout"] = "kickout";
|
|
22
|
-
MessageType["Error"] = "error";
|
|
23
|
-
// 订阅相关
|
|
24
|
-
MessageType["Subscribe"] = "subscribe";
|
|
25
|
-
MessageType["Unsubscribe"] = "unsubscribe";
|
|
26
|
-
// 行情推送
|
|
27
|
-
MessageType["Quote"] = "quote";
|
|
28
|
-
MessageType["Tick"] = "tick";
|
|
29
|
-
MessageType["Depth"] = "depth";
|
|
30
|
-
MessageType["Option"] = "option";
|
|
31
|
-
MessageType["Future"] = "future";
|
|
32
|
-
MessageType["Kline"] = "kline";
|
|
33
|
-
MessageType["StockTop"] = "stock_top";
|
|
34
|
-
MessageType["OptionTop"] = "option_top";
|
|
35
|
-
MessageType["FullTick"] = "full_tick";
|
|
36
|
-
MessageType["QuoteBBO"] = "quote_bbo";
|
|
37
|
-
// 账户推送
|
|
38
|
-
MessageType["Asset"] = "asset";
|
|
39
|
-
MessageType["Position"] = "position";
|
|
40
|
-
MessageType["Order"] = "order";
|
|
41
|
-
MessageType["Transaction"] = "transaction";
|
|
42
|
-
})(MessageType || (exports.MessageType = MessageType = {}));
|
|
9
|
+
exports.SubjectType = void 0;
|
|
43
10
|
/** 订阅主题类型 */
|
|
44
11
|
var SubjectType;
|
|
45
12
|
(function (SubjectType) {
|
|
@@ -58,26 +25,3 @@ var SubjectType;
|
|
|
58
25
|
SubjectType["Order"] = "order";
|
|
59
26
|
SubjectType["Transaction"] = "transaction";
|
|
60
27
|
})(SubjectType || (exports.SubjectType = SubjectType = {}));
|
|
61
|
-
/**
|
|
62
|
-
* 创建推送消息
|
|
63
|
-
*/
|
|
64
|
-
function createPushMessage(type, subject, data) {
|
|
65
|
-
const msg = { type };
|
|
66
|
-
if (subject)
|
|
67
|
-
msg.subject = subject;
|
|
68
|
-
if (data !== undefined)
|
|
69
|
-
msg.data = data;
|
|
70
|
-
return msg;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* 序列化推送消息为 JSON 字符串
|
|
74
|
-
*/
|
|
75
|
-
function serializeMessage(msg) {
|
|
76
|
-
return JSON.stringify(msg);
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* 反序列化 JSON 字符串为推送消息
|
|
80
|
-
*/
|
|
81
|
-
function deserializeMessage(data) {
|
|
82
|
-
return JSON.parse(data);
|
|
83
|
-
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Varint32 帧编解码器
|
|
4
|
+
*
|
|
5
|
+
* 兼容 Netty 的 ProtobufVarint32FrameDecoder / ProtobufVarint32LengthFieldPrepender。
|
|
6
|
+
* 每个字节低 7 位存数据,最高位为延续标志(1=后续还有字节,0=最后一个字节),最大 5 字节。
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.encodeVarint32 = encodeVarint32;
|
|
10
|
+
exports.decodeVarint32 = decodeVarint32;
|
|
11
|
+
/**
|
|
12
|
+
* 在 protobuf 字节前添加 varint32 长度前缀
|
|
13
|
+
*
|
|
14
|
+
* @param data - 待编码的 protobuf 二进制数据
|
|
15
|
+
* @returns varint32 长度前缀 + 原始数据
|
|
16
|
+
*/
|
|
17
|
+
function encodeVarint32(data) {
|
|
18
|
+
const length = data.length;
|
|
19
|
+
const header = encodeVarint32Length(length);
|
|
20
|
+
const result = new Uint8Array(header.length + data.length);
|
|
21
|
+
result.set(header, 0);
|
|
22
|
+
result.set(data, header.length);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 将一个非负整数编码为 varint32 字节序列
|
|
27
|
+
*/
|
|
28
|
+
function encodeVarint32Length(value) {
|
|
29
|
+
const bytes = [];
|
|
30
|
+
while (value > 0x7f) {
|
|
31
|
+
bytes.push((value & 0x7f) | 0x80);
|
|
32
|
+
value >>>= 7;
|
|
33
|
+
}
|
|
34
|
+
bytes.push(value & 0x7f);
|
|
35
|
+
return new Uint8Array(bytes);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 从缓冲区解码一个 varint32 帧
|
|
39
|
+
*
|
|
40
|
+
* @param buffer - 包含 varint32 长度前缀 + protobuf 数据的缓冲区
|
|
41
|
+
* @returns 解码结果 `{ message, remaining }`,数据不足时返回 `null`
|
|
42
|
+
*/
|
|
43
|
+
function decodeVarint32(buffer) {
|
|
44
|
+
if (buffer.length === 0) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
// 读取 varint32 长度前缀
|
|
48
|
+
let value = 0;
|
|
49
|
+
let shift = 0;
|
|
50
|
+
let i = 0;
|
|
51
|
+
while (i < buffer.length) {
|
|
52
|
+
// varint32 最多 5 字节
|
|
53
|
+
if (i >= 5) {
|
|
54
|
+
throw new Error('varint32 overflow: more than 5 bytes');
|
|
55
|
+
}
|
|
56
|
+
const byte = buffer[i];
|
|
57
|
+
value |= (byte & 0x7f) << shift;
|
|
58
|
+
i++;
|
|
59
|
+
if ((byte & 0x80) === 0) {
|
|
60
|
+
// 最后一个字节,延续标志为 0
|
|
61
|
+
const messageLength = value >>> 0; // 确保无符号
|
|
62
|
+
const totalNeeded = i + messageLength;
|
|
63
|
+
if (buffer.length < totalNeeded) {
|
|
64
|
+
// 数据不足,等待更多数据
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
message: buffer.slice(i, i + messageLength),
|
|
69
|
+
remaining: buffer.slice(i + messageLength),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
shift += 7;
|
|
73
|
+
}
|
|
74
|
+
// 缓冲区中 varint 前缀不完整,等待更多数据
|
|
75
|
+
return null;
|
|
76
|
+
}
|
package/dist/cjs/quote/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.QuoteClient = void 0;
|
|
3
|
+
exports.parseOptionIdentifier = exports.QuoteClient = void 0;
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Quote module exports
|
|
6
6
|
*/
|
|
7
7
|
var quote_client_1 = require("./quote-client");
|
|
8
8
|
Object.defineProperty(exports, "QuoteClient", { enumerable: true, get: function () { return quote_client_1.QuoteClient; } });
|
|
9
|
+
Object.defineProperty(exports, "parseOptionIdentifier", { enumerable: true, get: function () { return quote_client_1.parseOptionIdentifier; } });
|
|
@@ -1,110 +1,144 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.QuoteClient = void 0;
|
|
4
|
+
exports.parseOptionIdentifier = parseOptionIdentifier;
|
|
4
5
|
const api_request_1 = require("../client/api-request");
|
|
6
|
+
const api_response_1 = require("../client/api-response");
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* Parse an OCC-style option identifier like "AAPL 260619C00150000"
|
|
9
|
+
* into its component parts.
|
|
7
10
|
*/
|
|
11
|
+
function parseOptionIdentifier(identifier) {
|
|
12
|
+
const trimmed = identifier.trim();
|
|
13
|
+
const spaceIdx = trimmed.indexOf(' ');
|
|
14
|
+
if (spaceIdx === -1) {
|
|
15
|
+
throw new Error(`invalid option identifier: ${identifier}`);
|
|
16
|
+
}
|
|
17
|
+
const symbol = trimmed.substring(0, spaceIdx);
|
|
18
|
+
const rest = trimmed.substring(spaceIdx + 1).trim();
|
|
19
|
+
if (rest.length < 15) {
|
|
20
|
+
throw new Error(`option code too short: ${rest}`);
|
|
21
|
+
}
|
|
22
|
+
const datePart = rest.substring(0, 6);
|
|
23
|
+
const rightChar = rest.substring(6, 7);
|
|
24
|
+
const strikePart = rest.substring(7);
|
|
25
|
+
const yy = parseInt(datePart.substring(0, 2), 10);
|
|
26
|
+
const mm = parseInt(datePart.substring(2, 4), 10);
|
|
27
|
+
const dd = parseInt(datePart.substring(4, 6), 10);
|
|
28
|
+
const expiryMs = Date.UTC(2000 + yy, mm - 1, dd);
|
|
29
|
+
const right = rightChar === 'C' ? 'CALL' : rightChar === 'P' ? 'PUT' : '';
|
|
30
|
+
if (!right)
|
|
31
|
+
throw new Error(`invalid right character: ${rightChar}`);
|
|
32
|
+
const strikeInt = parseInt(strikePart, 10);
|
|
33
|
+
if (Number.isNaN(strikeInt))
|
|
34
|
+
throw new Error(`invalid strike digits: ${strikePart}`);
|
|
35
|
+
const strike = strikeInt / 1000;
|
|
36
|
+
return { symbol, expiryMs, right, strike };
|
|
37
|
+
}
|
|
38
|
+
/** Market data client wrapping all quote-related APIs. */
|
|
8
39
|
class QuoteClient {
|
|
9
40
|
constructor(httpClient) {
|
|
10
41
|
this.httpClient = httpClient;
|
|
11
42
|
}
|
|
43
|
+
async callInto(method, bizParams, version) {
|
|
44
|
+
const request = (0, api_request_1.createApiRequest)(method, bizParams, version);
|
|
45
|
+
const response = await this.httpClient.executeRequest(request);
|
|
46
|
+
return (0, api_response_1.unmarshalData)(response.data);
|
|
47
|
+
}
|
|
48
|
+
// === Basic market data ===
|
|
49
|
+
async getMarketState(market) {
|
|
50
|
+
return this.callInto('market_state', { market });
|
|
51
|
+
}
|
|
52
|
+
async getBrief(symbols) {
|
|
53
|
+
return this.callInto('quote_real_time', { symbols });
|
|
54
|
+
}
|
|
55
|
+
async getKline(symbol, period) {
|
|
56
|
+
return this.callInto('kline', { symbols: [symbol], period });
|
|
57
|
+
}
|
|
58
|
+
async getTimeline(symbols) {
|
|
59
|
+
return this.callInto('timeline', { symbols });
|
|
60
|
+
}
|
|
61
|
+
async getTradeTick(symbols) {
|
|
62
|
+
return this.callInto('trade_tick', { symbols });
|
|
63
|
+
}
|
|
64
|
+
/** Depth snapshot. market is required (US / HK supported). */
|
|
65
|
+
async getQuoteDepth(symbol, market) {
|
|
66
|
+
return this.callInto('quote_depth', { symbols: [symbol], market });
|
|
67
|
+
}
|
|
68
|
+
// === Options ===
|
|
69
|
+
async getOptionExpiration(symbol) {
|
|
70
|
+
return this.callInto('option_expiration', { symbols: [symbol] });
|
|
71
|
+
}
|
|
72
|
+
/** Option chain; `expiry` is "YYYY-MM-DD". */
|
|
73
|
+
async getOptionChain(symbol, expiry) {
|
|
74
|
+
const d = new Date(expiry + 'T00:00:00Z');
|
|
75
|
+
const expiryMs = d.getTime();
|
|
76
|
+
if (Number.isNaN(expiryMs)) {
|
|
77
|
+
throw new Error(`invalid expiry date, expected YYYY-MM-DD: ${expiry}`);
|
|
78
|
+
}
|
|
79
|
+
return this.callInto('option_chain', { option_basic: [{ symbol, expiry: expiryMs }] }, '3.0');
|
|
80
|
+
}
|
|
81
|
+
async getOptionBrief(identifiers) {
|
|
82
|
+
const optionBasic = identifiers.map((id) => {
|
|
83
|
+
const p = parseOptionIdentifier(id);
|
|
84
|
+
return { symbol: p.symbol, expiry: p.expiryMs, right: p.right, strike: p.strike };
|
|
85
|
+
});
|
|
86
|
+
return this.callInto('option_brief', { option_basic: optionBasic }, '2.0');
|
|
87
|
+
}
|
|
88
|
+
async getOptionKline(identifier, period) {
|
|
89
|
+
const p = parseOptionIdentifier(identifier);
|
|
90
|
+
return this.callInto('option_kline', {
|
|
91
|
+
option_query: [{ symbol: p.symbol, expiry: p.expiryMs, right: p.right, strike: p.strike, period }],
|
|
92
|
+
}, '2.0');
|
|
93
|
+
}
|
|
94
|
+
// === Futures ===
|
|
95
|
+
async getFutureExchange() {
|
|
96
|
+
return this.callInto('future_exchange', { secType: 'FUT' });
|
|
97
|
+
}
|
|
98
|
+
async getFutureContracts(exchange) {
|
|
99
|
+
return this.callInto('future_contract_by_exchange_code', { exchangeCode: exchange });
|
|
100
|
+
}
|
|
101
|
+
async getFutureRealTimeQuote(contractCodes) {
|
|
102
|
+
return this.callInto('future_real_time_quote', { contractCodes });
|
|
103
|
+
}
|
|
104
|
+
/** Futures K-line; use -1 for unbounded beginTime / endTime. */
|
|
105
|
+
async getFutureKline(req) {
|
|
106
|
+
const body = {
|
|
107
|
+
...req,
|
|
108
|
+
beginTime: req.beginTime ?? -1,
|
|
109
|
+
endTime: req.endTime ?? -1,
|
|
110
|
+
};
|
|
111
|
+
return this.callInto('future_kline', body);
|
|
112
|
+
}
|
|
113
|
+
// === Fundamentals ===
|
|
114
|
+
async getFinancialDaily(req) {
|
|
115
|
+
return this.callInto('financial_daily', req);
|
|
116
|
+
}
|
|
117
|
+
async getFinancialReport(req) {
|
|
118
|
+
return this.callInto('financial_report', req);
|
|
119
|
+
}
|
|
12
120
|
/**
|
|
13
|
-
*
|
|
121
|
+
* Corporate actions. Server returns {symbol: [...]}, this method flattens into a single list.
|
|
14
122
|
*/
|
|
15
|
-
async
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
async
|
|
23
|
-
return this.
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
/** 获取分时数据 */
|
|
34
|
-
async timeline(symbols) {
|
|
35
|
-
return this.execute('timeline', { symbols });
|
|
36
|
-
}
|
|
37
|
-
/** 获取逐笔成交数据 */
|
|
38
|
-
async tradeTick(symbols) {
|
|
39
|
-
return this.execute('trade_tick', { symbols });
|
|
40
|
-
}
|
|
41
|
-
/** 获取深度行情 */
|
|
42
|
-
async quoteDepth(symbol) {
|
|
43
|
-
return this.execute('quote_depth', { symbol });
|
|
44
|
-
}
|
|
45
|
-
// === 期权行情方法 ===
|
|
46
|
-
/** 获取期权到期日 */
|
|
47
|
-
async optionExpiration(symbol) {
|
|
48
|
-
return this.execute('option_expiration', { symbols: [symbol] });
|
|
49
|
-
}
|
|
50
|
-
/** 获取期权链 */
|
|
51
|
-
async optionChain(symbol, expiry) {
|
|
52
|
-
return this.execute('option_chain', { symbol, expiry });
|
|
53
|
-
}
|
|
54
|
-
/** 获取期权报价 */
|
|
55
|
-
async optionBrief(identifiers) {
|
|
56
|
-
return this.execute('option_brief', { identifiers });
|
|
57
|
-
}
|
|
58
|
-
/** 获取期权 K 线 */
|
|
59
|
-
async optionKline(identifier, period) {
|
|
60
|
-
return this.execute('option_kline', { identifier, period });
|
|
61
|
-
}
|
|
62
|
-
// === 期货行情方法 ===
|
|
63
|
-
/** 获取期货交易所列表 */
|
|
64
|
-
async futureExchange() {
|
|
65
|
-
return this.execute('future_exchange', { sec_type: 'FUT' });
|
|
66
|
-
}
|
|
67
|
-
/** 获取期货合约列表 */
|
|
68
|
-
async futureContracts(exchange) {
|
|
69
|
-
return this.execute('future_contracts', { exchange });
|
|
70
|
-
}
|
|
71
|
-
/** 获取期货实时报价 */
|
|
72
|
-
async futureRealTimeQuote(symbols) {
|
|
73
|
-
return this.execute('future_real_time_quote', { symbols });
|
|
74
|
-
}
|
|
75
|
-
/** 获取期货 K 线 */
|
|
76
|
-
async futureKline(symbol, period) {
|
|
77
|
-
return this.execute('future_kline', { symbol, period });
|
|
78
|
-
}
|
|
79
|
-
// === 基本面和资金流向方法 ===
|
|
80
|
-
/** 获取财务日报 */
|
|
81
|
-
async financialDaily(symbol) {
|
|
82
|
-
return this.execute('financial_daily', { symbol });
|
|
83
|
-
}
|
|
84
|
-
/** 获取财务报告 */
|
|
85
|
-
async financialReport(symbol) {
|
|
86
|
-
return this.execute('financial_report', { symbol });
|
|
87
|
-
}
|
|
88
|
-
/** 获取公司行动 */
|
|
89
|
-
async corporateAction(symbol) {
|
|
90
|
-
return this.execute('corporate_action', { symbol });
|
|
91
|
-
}
|
|
92
|
-
/** 获取资金流向 */
|
|
93
|
-
async capitalFlow(symbol) {
|
|
94
|
-
return this.execute('capital_flow', { symbol });
|
|
95
|
-
}
|
|
96
|
-
/** 获取资金分布 */
|
|
97
|
-
async capitalDistribution(symbol) {
|
|
98
|
-
return this.execute('capital_distribution', { symbol });
|
|
99
|
-
}
|
|
100
|
-
// === 选股器和行情权限方法 ===
|
|
101
|
-
/** 选股器 */
|
|
102
|
-
async marketScanner(params) {
|
|
103
|
-
return this.execute('market_scanner', params);
|
|
104
|
-
}
|
|
105
|
-
/** 获取行情权限 */
|
|
123
|
+
async getCorporateAction(req) {
|
|
124
|
+
const grouped = await this.callInto('corporate_action', req);
|
|
125
|
+
if (!grouped || typeof grouped !== 'object')
|
|
126
|
+
return [];
|
|
127
|
+
return Object.values(grouped).flat();
|
|
128
|
+
}
|
|
129
|
+
// === Capital flow ===
|
|
130
|
+
async getCapitalFlow(symbol, market, period) {
|
|
131
|
+
return this.callInto('capital_flow', { symbol, market, period });
|
|
132
|
+
}
|
|
133
|
+
async getCapitalDistribution(symbol, market) {
|
|
134
|
+
return this.callInto('capital_distribution', { symbol, market });
|
|
135
|
+
}
|
|
136
|
+
// === Scanner & permission ===
|
|
137
|
+
async marketScanner(req) {
|
|
138
|
+
return this.callInto('market_scanner', req);
|
|
139
|
+
}
|
|
106
140
|
async grabQuotePermission() {
|
|
107
|
-
return this.
|
|
141
|
+
return this.callInto('grab_quote_permission');
|
|
108
142
|
}
|
|
109
143
|
}
|
|
110
144
|
exports.QuoteClient = QuoteClient;
|
|
@@ -78,16 +78,16 @@ function signWithRSA(privateKeyStr, content) {
|
|
|
78
78
|
return sign.sign(key, 'base64');
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
81
|
+
* Verify a SHA1WithRSA signature using an RSA public key.
|
|
82
82
|
*
|
|
83
|
-
* @param
|
|
84
|
-
* @param content -
|
|
85
|
-
* @param
|
|
86
|
-
* @returns
|
|
83
|
+
* @param publicKeyBase64 - Base64-encoded public key (DER / PKCS#1 or SPKI)
|
|
84
|
+
* @param content - Original content that was signed
|
|
85
|
+
* @param signatureBase64 - Base64-encoded signature
|
|
86
|
+
* @returns Whether the signature is valid
|
|
87
87
|
*/
|
|
88
|
-
function verifyWithRSA(
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return
|
|
88
|
+
function verifyWithRSA(publicKeyBase64, content, signatureBase64) {
|
|
89
|
+
const pem = `-----BEGIN PUBLIC KEY-----\n${publicKeyBase64}\n-----END PUBLIC KEY-----`;
|
|
90
|
+
const verifier = (0, crypto_1.createVerify)('SHA1');
|
|
91
|
+
verifier.update(content);
|
|
92
|
+
return verifier.verify(pem, signatureBase64, 'base64');
|
|
93
93
|
}
|
|
@@ -2,98 +2,92 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TradeClient = void 0;
|
|
4
4
|
const api_request_1 = require("../client/api-request");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*/
|
|
5
|
+
const api_response_1 = require("../client/api-response");
|
|
6
|
+
/** Trading client wrapping all trade-related APIs. */
|
|
8
7
|
class TradeClient {
|
|
9
8
|
constructor(httpClient, account) {
|
|
10
9
|
this.httpClient = httpClient;
|
|
11
10
|
this.account = account;
|
|
12
11
|
}
|
|
13
|
-
|
|
14
|
-
* 内部通用方法:构造请求、发送、返回 data 字段
|
|
15
|
-
*/
|
|
16
|
-
async execute(method, bizParams) {
|
|
12
|
+
async callInto(method, bizParams) {
|
|
17
13
|
const request = (0, api_request_1.createApiRequest)(method, bizParams);
|
|
18
14
|
const response = await this.httpClient.executeRequest(request);
|
|
19
|
-
return response.data;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
return (0, api_response_1.unmarshalData)(response.data);
|
|
16
|
+
}
|
|
17
|
+
/** Strip `{items: [...]}` envelope used by most trade read endpoints. */
|
|
18
|
+
async callIntoItems(method, bizParams) {
|
|
19
|
+
const wrap = await this.callInto(method, bizParams);
|
|
20
|
+
if (Array.isArray(wrap))
|
|
21
|
+
return wrap;
|
|
22
|
+
return wrap?.items ?? [];
|
|
23
|
+
}
|
|
24
|
+
// === Contracts ===
|
|
25
|
+
async getContract(symbol, secType) {
|
|
26
|
+
return this.callIntoItems('contract', {
|
|
25
27
|
account: this.account, symbol, secType,
|
|
26
28
|
});
|
|
27
29
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return this.execute('contracts', {
|
|
30
|
+
async getContracts(symbols, secType) {
|
|
31
|
+
return this.callIntoItems('contracts', {
|
|
31
32
|
account: this.account, symbols, secType,
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Derivative contracts (OPT / WAR / IOPT only).
|
|
37
|
+
* `symbol` is the underlying (e.g. "AAPL"); `expiry` is "YYYYMMDD".
|
|
38
|
+
*/
|
|
39
|
+
async getQuoteContract(symbol, secType, expiry) {
|
|
40
|
+
return this.callIntoItems('quote_contract', {
|
|
41
|
+
account: this.account, symbols: [symbol], secType, expiry,
|
|
38
42
|
});
|
|
39
43
|
}
|
|
40
|
-
// ===
|
|
41
|
-
/** 下单 */
|
|
44
|
+
// === Order operations ===
|
|
42
45
|
async placeOrder(order) {
|
|
43
|
-
|
|
44
|
-
return this.execute('place_order', params);
|
|
46
|
+
return this.callInto('place_order', { ...order, account: this.account });
|
|
45
47
|
}
|
|
46
|
-
/** 预览订单 */
|
|
47
48
|
async previewOrder(order) {
|
|
48
|
-
|
|
49
|
-
return this.execute('preview_order', params);
|
|
49
|
+
return this.callInto('preview_order', { ...order, account: this.account });
|
|
50
50
|
}
|
|
51
|
-
/** 修改订单 */
|
|
52
51
|
async modifyOrder(id, order) {
|
|
53
|
-
|
|
54
|
-
return this.execute('modify_order', params);
|
|
52
|
+
return this.callInto('modify_order', { ...order, account: this.account, id });
|
|
55
53
|
}
|
|
56
|
-
/** 取消订单 */
|
|
57
54
|
async cancelOrder(id) {
|
|
58
|
-
return this.
|
|
59
|
-
account: this.account, id,
|
|
60
|
-
});
|
|
55
|
+
return this.callInto('cancel_order', { account: this.account, id });
|
|
61
56
|
}
|
|
62
|
-
// ===
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return this.execute('orders', { account: this.account });
|
|
57
|
+
// === Order queries ===
|
|
58
|
+
async getOrders() {
|
|
59
|
+
return this.callIntoItems('orders', { account: this.account });
|
|
66
60
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return this.execute('active_orders', { account: this.account });
|
|
61
|
+
async getActiveOrders() {
|
|
62
|
+
return this.callIntoItems('active_orders', { account: this.account });
|
|
70
63
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return this.execute('inactive_orders', { account: this.account });
|
|
64
|
+
async getInactiveOrders() {
|
|
65
|
+
return this.callIntoItems('inactive_orders', { account: this.account });
|
|
74
66
|
}
|
|
75
|
-
/**
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Filled orders in a time range (ms timestamps required by the server).
|
|
69
|
+
* Use `Date.now() - 30*24*3600*1000` for "last 30 days".
|
|
70
|
+
*/
|
|
71
|
+
async getFilledOrders(startDateMs, endDateMs) {
|
|
72
|
+
return this.callIntoItems('filled_orders', {
|
|
73
|
+
account: this.account, startDate: startDateMs, endDate: endDateMs,
|
|
74
|
+
});
|
|
78
75
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
/** Transactions for a specific order; `symbol` and `secType` are required. */
|
|
77
|
+
async getOrderTransactions(id, symbol, secType) {
|
|
78
|
+
return this.callIntoItems('order_transactions', {
|
|
79
|
+
account: this.account, orderId: id, symbol, secType,
|
|
80
|
+
});
|
|
83
81
|
}
|
|
84
|
-
|
|
85
|
-
async
|
|
86
|
-
return this.
|
|
82
|
+
// === Positions & assets ===
|
|
83
|
+
async getPositions() {
|
|
84
|
+
return this.callIntoItems('positions', { account: this.account });
|
|
87
85
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return this.execute('prime_assets', { account: this.account });
|
|
86
|
+
async getAssets() {
|
|
87
|
+
return this.callIntoItems('assets', { account: this.account });
|
|
91
88
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return this.execute('order_transactions', {
|
|
95
|
-
account: this.account, id,
|
|
96
|
-
});
|
|
89
|
+
async getPrimeAssets() {
|
|
90
|
+
return this.callInto('prime_assets', { account: this.account });
|
|
97
91
|
}
|
|
98
92
|
}
|
|
99
93
|
exports.TradeClient = TradeClient;
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* API
|
|
2
|
+
* API request builder.
|
|
3
|
+
*
|
|
4
|
+
* Requests use camelCase parameters in TypeScript (idiomatic), but the
|
|
5
|
+
* server wire format is snake_case, so we convert keys before serializing.
|
|
3
6
|
*/
|
|
7
|
+
import { keysToSnakeCase } from './case-convert';
|
|
4
8
|
/**
|
|
5
|
-
*
|
|
9
|
+
* Create an API request, serializing business parameters to JSON as bizContent.
|
|
10
|
+
* camelCase keys are automatically converted to snake_case to match the server.
|
|
6
11
|
*
|
|
7
|
-
* @param method - API
|
|
8
|
-
* @param bizParams -
|
|
9
|
-
* @
|
|
12
|
+
* @param method - API method name
|
|
13
|
+
* @param bizParams - Business parameters (object, string, or null); objects are converted recursively
|
|
14
|
+
* @param version - Optional API version override
|
|
15
|
+
* @returns ApiRequest object
|
|
10
16
|
*/
|
|
11
|
-
export function createApiRequest(method, bizParams) {
|
|
17
|
+
export function createApiRequest(method, bizParams, version) {
|
|
12
18
|
let bizContent;
|
|
13
19
|
if (typeof bizParams === 'string') {
|
|
14
20
|
bizContent = bizParams;
|
|
@@ -17,7 +23,7 @@ export function createApiRequest(method, bizParams) {
|
|
|
17
23
|
bizContent = '{}';
|
|
18
24
|
}
|
|
19
25
|
else {
|
|
20
|
-
bizContent = JSON.stringify(bizParams);
|
|
26
|
+
bizContent = JSON.stringify(keysToSnakeCase(bizParams));
|
|
21
27
|
}
|
|
22
|
-
return { method, bizContent };
|
|
28
|
+
return { method, bizContent, version };
|
|
23
29
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* API
|
|
2
|
+
* API response parsing.
|
|
3
3
|
*/
|
|
4
4
|
import { TigerError } from './errors';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Parse the raw HTTP response body.
|
|
7
|
+
* Throws TigerError when code != 0.
|
|
8
8
|
*/
|
|
9
9
|
export function parseApiResponse(body) {
|
|
10
10
|
const resp = JSON.parse(body);
|
|
@@ -13,3 +13,22 @@ export function parseApiResponse(body) {
|
|
|
13
13
|
}
|
|
14
14
|
return resp;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Decode an ApiResponse.data payload into a typed value.
|
|
18
|
+
* Handles the server's occasional double-encoded JSON (where `data` is a
|
|
19
|
+
* JSON string that itself wraps JSON), seen on some trade endpoints.
|
|
20
|
+
*/
|
|
21
|
+
export function unmarshalData(data) {
|
|
22
|
+
if (data == null)
|
|
23
|
+
return undefined;
|
|
24
|
+
if (typeof data === 'string') {
|
|
25
|
+
// Attempt to parse JSON string (double-encoded case)
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(data);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return data;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return data;
|
|
34
|
+
}
|