@yuants/vendor-okx 0.17.2 → 0.17.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/ohlc.js +2 -1
- package/dist/ohlc.js.map +1 -1
- package/dist/websocket.js +15 -2
- package/dist/websocket.js.map +1 -1
- package/lib/ohlc.js +3 -2
- package/lib/ohlc.js.map +1 -1
- package/lib/websocket.d.ts +3 -3
- package/lib/websocket.d.ts.map +1 -1
- package/lib/websocket.js +16 -2
- package/lib/websocket.js.map +1 -1
- package/package.json +1 -1
- package/temp/image-tag +1 -1
- package/temp/package-deps.json +5 -5
package/dist/ohlc.js
CHANGED
@@ -15,7 +15,7 @@ import { Terminal } from '@yuants/protocol';
|
|
15
15
|
import { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';
|
16
16
|
import { firstValueFrom, Observable, timer } from 'rxjs';
|
17
17
|
import { client } from './api';
|
18
|
-
import {
|
18
|
+
import { OKXWsClient } from './websocket';
|
19
19
|
import { writeToSQL } from '@yuants/sql';
|
20
20
|
// 时间粒度,默认值1m
|
21
21
|
// 如 [1m/3m/5m/15m/30m/1H/2H/4H]
|
@@ -130,6 +130,7 @@ Terminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (ser
|
|
130
130
|
console.info(formatTime(Date.now()), `subscribe`, series_id);
|
131
131
|
return new Observable((subscriber) => {
|
132
132
|
console.info(formatTime(Date.now()), `subscribe`, candleType, instId);
|
133
|
+
const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');
|
133
134
|
okxBusinessWsClient.subscribe(candleType, instId, async (data) => {
|
134
135
|
const created_at = Number(data[0]);
|
135
136
|
const closed_at = created_at + offset;
|
package/dist/ohlc.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":"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","sourcesContent":["import { IOHLC } from '@yuants/data-ohlc';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { Terminal } from '@yuants/protocol';\nimport { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, Observable, of, timer } from 'rxjs';\nimport { client } from './api';\nimport { okxBusinessWsClient } from './websocket';\nimport { buildInsertManyIntoTableSQL, requestSQL, writeToSQL } from '@yuants/sql';\n\n// 时间粒度,默认值1m\n// 如 [1m/3m/5m/15m/30m/1H/2H/4H]\n// 香港时间开盘价k线:[6H/12H/1D/1W/1M]\n// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/1Wutc/1Mutc]\n\nconst DURATION_TO_OKX_BAR_TYPE: Record<string, string> = {\n PT1M: '1m',\n PT3M: '3m',\n PT5M: '5m',\n PT15M: '15m',\n PT30M: '30m',\n\n PT1H: '1H',\n PT2H: '2H',\n PT4H: '4H',\n PT6H: '6H',\n PT12H: '12H',\n\n P1D: '1D',\n P1W: '1W',\n P1M: '1M',\n};\n\nconst DURATION_TO_OKX_CANDLE_TYPE: Record<string, string> = {\n PT1M: 'mark-price-candle1m',\n PT3M: 'mark-price-candle3m',\n PT5M: 'mark-price-candle5m',\n PT15M: 'mark-price-candle15m',\n PT30M: 'mark-price-candle30m',\n\n PT1H: 'mark-price-candle1H',\n PT2H: 'mark-price-candle2H',\n PT4H: 'mark-price-candle4H',\n PT6H: 'mark-price-candle6H',\n PT12H: 'mark-price-candle12H',\n\n P1D: 'mark-price-candle1D',\n P1W: 'mark-price-candle1W',\n P1M: 'mark-price-candle1M',\n};\n\ncreateSeriesProvider<IOHLC>(Terminal.fromNodeEnv(), {\n tableName: 'ohlc',\n series_id_prefix_parts: ['OKX'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, ended_at }) {\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const [instType, instId] = decodePath(product_id);\n if (!instId) {\n throw `invalid product_id: ${product_id}`;\n }\n\n const bar = DURATION_TO_OKX_BAR_TYPE[duration];\n if (!bar) {\n throw `unsupported duration: ${duration}`;\n }\n\n let currentStartTime = ended_at;\n\n while (true) {\n // 向前翻页,时间降序,不含 after 时间点\n const res = await client.getHistoryCandles({\n instId,\n bar,\n after: `${currentStartTime}`,\n limit: '100',\n });\n if (res.code !== '0') {\n throw `API failed: ${res.code} ${res.msg}`;\n }\n if (res.data.length === 0) break;\n currentStartTime = +res.data[res.data.length - 1][0];\n const data = res.data.map(\n (x): IOHLC => ({\n series_id,\n datasource_id,\n product_id,\n duration,\n created_at: formatTime(+x[0]),\n closed_at: formatTime(+x[0] + offset),\n open: x[1],\n high: x[2],\n low: x[3],\n close: x[4],\n volume: x[5],\n open_interest: '0',\n }),\n );\n yield data;\n await firstValueFrom(timer(1000));\n }\n },\n});\n\nTerminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (series_id) => {\n // const [] = decodePath(args)\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const [, instId] = decodePath(product_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const candleType = DURATION_TO_OKX_CANDLE_TYPE[duration];\n console.info(formatTime(Date.now()), `subscribe`, series_id);\n return new Observable<IOHLC>((subscriber) => {\n console.info(formatTime(Date.now()), `subscribe`, candleType, instId);\n okxBusinessWsClient.subscribe(candleType, instId, async (data: string[]) => {\n const created_at = Number(data[0]);\n const closed_at = created_at + offset;\n const open = data[1];\n const high = data[2];\n const low = data[3];\n const close = data[4];\n if (isNaN(closed_at)) {\n return;\n }\n console.info(formatTime(Date.now()), `insertData`, data);\n const cancelData: IOHLC = {\n closed_at: formatTime(closed_at),\n created_at: formatTime(created_at),\n open,\n high,\n low,\n close,\n series_id,\n datasource_id,\n duration,\n product_id,\n volume: '0',\n open_interest: '0',\n };\n subscriber.next(cancelData);\n });\n return () => {\n okxBusinessWsClient.unsubscribe(candleType, instId);\n };\n }).pipe(\n writeToSQL({\n tableName: 'ohlc',\n conflictKeys: ['created_at', 'series_id'],\n writeInterval: 1000,\n terminal: Terminal.fromNodeEnv(),\n keyFn: (x) => encodePath(x.created_at, x.series_id),\n }),\n );\n});\n"]}
|
1
|
+
{"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":"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","sourcesContent":["import { IOHLC } from '@yuants/data-ohlc';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { Terminal } from '@yuants/protocol';\nimport { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, Observable, of, timer } from 'rxjs';\nimport { client } from './api';\nimport { OKXWsClient } from './websocket';\nimport { writeToSQL } from '@yuants/sql';\n\n// 时间粒度,默认值1m\n// 如 [1m/3m/5m/15m/30m/1H/2H/4H]\n// 香港时间开盘价k线:[6H/12H/1D/1W/1M]\n// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/1Wutc/1Mutc]\n\nconst DURATION_TO_OKX_BAR_TYPE: Record<string, string> = {\n PT1M: '1m',\n PT3M: '3m',\n PT5M: '5m',\n PT15M: '15m',\n PT30M: '30m',\n\n PT1H: '1H',\n PT2H: '2H',\n PT4H: '4H',\n PT6H: '6H',\n PT12H: '12H',\n\n P1D: '1D',\n P1W: '1W',\n P1M: '1M',\n};\n\nconst DURATION_TO_OKX_CANDLE_TYPE: Record<string, string> = {\n PT1M: 'mark-price-candle1m',\n PT3M: 'mark-price-candle3m',\n PT5M: 'mark-price-candle5m',\n PT15M: 'mark-price-candle15m',\n PT30M: 'mark-price-candle30m',\n\n PT1H: 'mark-price-candle1H',\n PT2H: 'mark-price-candle2H',\n PT4H: 'mark-price-candle4H',\n PT6H: 'mark-price-candle6H',\n PT12H: 'mark-price-candle12H',\n\n P1D: 'mark-price-candle1D',\n P1W: 'mark-price-candle1W',\n P1M: 'mark-price-candle1M',\n};\n\ncreateSeriesProvider<IOHLC>(Terminal.fromNodeEnv(), {\n tableName: 'ohlc',\n series_id_prefix_parts: ['OKX'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, ended_at }) {\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const [instType, instId] = decodePath(product_id);\n if (!instId) {\n throw `invalid product_id: ${product_id}`;\n }\n\n const bar = DURATION_TO_OKX_BAR_TYPE[duration];\n if (!bar) {\n throw `unsupported duration: ${duration}`;\n }\n\n let currentStartTime = ended_at;\n\n while (true) {\n // 向前翻页,时间降序,不含 after 时间点\n const res = await client.getHistoryCandles({\n instId,\n bar,\n after: `${currentStartTime}`,\n limit: '100',\n });\n if (res.code !== '0') {\n throw `API failed: ${res.code} ${res.msg}`;\n }\n if (res.data.length === 0) break;\n currentStartTime = +res.data[res.data.length - 1][0];\n const data = res.data.map(\n (x): IOHLC => ({\n series_id,\n datasource_id,\n product_id,\n duration,\n created_at: formatTime(+x[0]),\n closed_at: formatTime(+x[0] + offset),\n open: x[1],\n high: x[2],\n low: x[3],\n close: x[4],\n volume: x[5],\n open_interest: '0',\n }),\n );\n yield data;\n await firstValueFrom(timer(1000));\n }\n },\n});\n\nTerminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (series_id) => {\n // const [] = decodePath(args)\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const [, instId] = decodePath(product_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const candleType = DURATION_TO_OKX_CANDLE_TYPE[duration];\n console.info(formatTime(Date.now()), `subscribe`, series_id);\n return new Observable<IOHLC>((subscriber) => {\n console.info(formatTime(Date.now()), `subscribe`, candleType, instId);\n const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');\n okxBusinessWsClient.subscribe(candleType, instId, async (data: string[]) => {\n const created_at = Number(data[0]);\n const closed_at = created_at + offset;\n const open = data[1];\n const high = data[2];\n const low = data[3];\n const close = data[4];\n if (isNaN(closed_at)) {\n return;\n }\n console.info(formatTime(Date.now()), `insertData`, data);\n const cancelData: IOHLC = {\n closed_at: formatTime(closed_at),\n created_at: formatTime(created_at),\n open,\n high,\n low,\n close,\n series_id,\n datasource_id,\n duration,\n product_id,\n volume: '0',\n open_interest: '0',\n };\n subscriber.next(cancelData);\n });\n return () => {\n okxBusinessWsClient.unsubscribe(candleType, instId);\n };\n }).pipe(\n writeToSQL({\n tableName: 'ohlc',\n conflictKeys: ['created_at', 'series_id'],\n writeInterval: 1000,\n terminal: Terminal.fromNodeEnv(),\n keyFn: (x) => encodePath(x.created_at, x.series_id),\n }),\n );\n});\n"]}
|
package/dist/websocket.js
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
import { encodePath, formatTime } from '@yuants/utils';
|
2
|
+
import { interval, tap } from 'rxjs';
|
2
3
|
// import WebSocket from 'ws';
|
3
|
-
class OKXWsClient {
|
4
|
+
export class OKXWsClient {
|
4
5
|
constructor(url) {
|
5
6
|
this.connected = false;
|
6
7
|
// this.instId = instId;
|
7
8
|
this.ws = new WebSocket(url);
|
8
9
|
this.pendingSub = [];
|
10
|
+
this.keepAlive = interval(25000)
|
11
|
+
.pipe(tap(() => {
|
12
|
+
if (this.connected) {
|
13
|
+
this.ws.send('ping');
|
14
|
+
}
|
15
|
+
}))
|
16
|
+
.subscribe();
|
9
17
|
// this.ws.
|
10
18
|
this.ws.addEventListener('open', () => {
|
11
19
|
this.connected = true;
|
@@ -25,6 +33,9 @@ class OKXWsClient {
|
|
25
33
|
// 处理消息
|
26
34
|
handleMessage(raw) {
|
27
35
|
var _a, _b;
|
36
|
+
if (raw.data === 'pong') {
|
37
|
+
return;
|
38
|
+
}
|
28
39
|
const msg = JSON.parse(raw.data);
|
29
40
|
if ((_a = msg.arg) === null || _a === void 0 ? void 0 : _a.channel) {
|
30
41
|
const channelId = encodePath(msg.arg.channel, msg.arg.instId);
|
@@ -72,9 +83,11 @@ class OKXWsClient {
|
|
72
83
|
};
|
73
84
|
this.ws.send(JSON.stringify(unSubMsg));
|
74
85
|
this.subscriptions.delete(channelId);
|
86
|
+
if (this.subscriptions.size === 0) {
|
87
|
+
this.keepAlive.unsubscribe();
|
88
|
+
}
|
75
89
|
delete this.handlers[channelId];
|
76
90
|
console.info(`📩 Sent unsubscribe for ${channelId}`);
|
77
91
|
}
|
78
92
|
}
|
79
|
-
export const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');
|
80
93
|
//# sourceMappingURL=websocket.js.map
|
package/dist/websocket.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvD,8BAA8B;AAE9B,MAAM,WAAW;
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodePath, formatTime } from '@yuants/utils';\nimport { interval, Subscription, tap } from 'rxjs';\n// import WebSocket from 'ws';\n\nexport class OKXWsClient {\n ws: WebSocket;\n connected: boolean = false;\n subscriptions: Set<string>;\n handlers: Record<string, Function>;\n pendingSub: string[];\n keepAlive: Subscription;\n constructor(url: string) {\n // this.instId = instId;\n this.ws = new WebSocket(url);\n this.pendingSub = [];\n this.keepAlive = interval(25000)\n .pipe(\n tap(() => {\n if (this.connected) {\n this.ws.send('ping');\n }\n }),\n )\n .subscribe();\n // this.ws.\n this.ws.addEventListener('open', () => {\n this.connected = true;\n console.info(formatTime(Date.now()), '✅ WS connected');\n while (this.pendingSub.length > 0) {\n const msg = this.pendingSub.shift();\n if (msg) {\n this.ws.send(msg);\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${msg}`);\n }\n }\n });\n\n this.ws.addEventListener('message', (raw) => this.handleMessage(raw));\n this.subscriptions = new Set();\n this.handlers = {}; // key: channel, value: callback\n }\n\n // 处理消息\n handleMessage(raw: any) {\n if (raw.data === 'pong') {\n return;\n }\n const msg = JSON.parse(raw.data);\n if (msg.arg?.channel) {\n const channelId = encodePath(msg.arg.channel, msg.arg.instId);\n const data = msg.data?.[0];\n if (data && this.handlers[channelId]) {\n this.handlers[channelId](data, msg.arg);\n }\n } else if (msg.event) {\n console.info('Event:', msg);\n }\n }\n\n // 调用订阅\n subscribe(channel: string, instId?: string, handler?: Function) {\n const channelId = encodePath(channel, instId);\n if (this.subscriptions.has(channelId)) {\n console.info(formatTime(Date.now()), `⚠️ Already subscribed: ${channelId}`);\n return;\n }\n\n const subMsg = {\n op: 'subscribe',\n args: [{ channel, instId }],\n };\n\n if (this.connected) {\n this.ws.send(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${channelId}`);\n } else {\n this.pendingSub.push(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 add subscribe for ${channelId} to pending list`);\n }\n this.subscriptions.add(channelId);\n if (handler) {\n this.handlers[channelId] = handler;\n }\n }\n\n // 取消订阅\n unsubscribe(channel: string, instId?: string) {\n const channelId = encodePath(channel, instId);\n if (!this.subscriptions.has(channelId)) return;\n\n const unSubMsg = {\n op: 'unsubscribe',\n args: [{ channel, instId }],\n };\n\n this.ws.send(JSON.stringify(unSubMsg));\n this.subscriptions.delete(channelId);\n if (this.subscriptions.size === 0) {\n this.keepAlive.unsubscribe();\n }\n delete this.handlers[channelId];\n console.info(`📩 Sent unsubscribe for ${channelId}`);\n }\n}\n"]}
|
package/lib/ohlc.js
CHANGED
@@ -132,7 +132,8 @@ protocol_1.Terminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OK
|
|
132
132
|
console.info((0, utils_1.formatTime)(Date.now()), `subscribe`, series_id);
|
133
133
|
return new rxjs_1.Observable((subscriber) => {
|
134
134
|
console.info((0, utils_1.formatTime)(Date.now()), `subscribe`, candleType, instId);
|
135
|
-
|
135
|
+
const okxBusinessWsClient = new websocket_1.OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');
|
136
|
+
okxBusinessWsClient.subscribe(candleType, instId, async (data) => {
|
136
137
|
const created_at = Number(data[0]);
|
137
138
|
const closed_at = created_at + offset;
|
138
139
|
const open = data[1];
|
@@ -160,7 +161,7 @@ protocol_1.Terminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OK
|
|
160
161
|
subscriber.next(cancelData);
|
161
162
|
});
|
162
163
|
return () => {
|
163
|
-
|
164
|
+
okxBusinessWsClient.unsubscribe(candleType, instId);
|
164
165
|
};
|
165
166
|
}).pipe((0, sql_1.writeToSQL)({
|
166
167
|
tableName: 'ohlc',
|
package/lib/ohlc.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AACA,qDAA2D;AAC3D,+CAA4C;AAC5C,yCAA4F;AAC5F,+BAA6D;AAC7D,+BAA+B;AAC/B,
|
1
|
+
{"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":"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","sourcesContent":["import { IOHLC } from '@yuants/data-ohlc';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { Terminal } from '@yuants/protocol';\nimport { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, Observable, of, timer } from 'rxjs';\nimport { client } from './api';\nimport { OKXWsClient } from './websocket';\nimport { writeToSQL } from '@yuants/sql';\n\n// 时间粒度,默认值1m\n// 如 [1m/3m/5m/15m/30m/1H/2H/4H]\n// 香港时间开盘价k线:[6H/12H/1D/1W/1M]\n// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/1Wutc/1Mutc]\n\nconst DURATION_TO_OKX_BAR_TYPE: Record<string, string> = {\n PT1M: '1m',\n PT3M: '3m',\n PT5M: '5m',\n PT15M: '15m',\n PT30M: '30m',\n\n PT1H: '1H',\n PT2H: '2H',\n PT4H: '4H',\n PT6H: '6H',\n PT12H: '12H',\n\n P1D: '1D',\n P1W: '1W',\n P1M: '1M',\n};\n\nconst DURATION_TO_OKX_CANDLE_TYPE: Record<string, string> = {\n PT1M: 'mark-price-candle1m',\n PT3M: 'mark-price-candle3m',\n PT5M: 'mark-price-candle5m',\n PT15M: 'mark-price-candle15m',\n PT30M: 'mark-price-candle30m',\n\n PT1H: 'mark-price-candle1H',\n PT2H: 'mark-price-candle2H',\n PT4H: 'mark-price-candle4H',\n PT6H: 'mark-price-candle6H',\n PT12H: 'mark-price-candle12H',\n\n P1D: 'mark-price-candle1D',\n P1W: 'mark-price-candle1W',\n P1M: 'mark-price-candle1M',\n};\n\ncreateSeriesProvider<IOHLC>(Terminal.fromNodeEnv(), {\n tableName: 'ohlc',\n series_id_prefix_parts: ['OKX'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, ended_at }) {\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const [instType, instId] = decodePath(product_id);\n if (!instId) {\n throw `invalid product_id: ${product_id}`;\n }\n\n const bar = DURATION_TO_OKX_BAR_TYPE[duration];\n if (!bar) {\n throw `unsupported duration: ${duration}`;\n }\n\n let currentStartTime = ended_at;\n\n while (true) {\n // 向前翻页,时间降序,不含 after 时间点\n const res = await client.getHistoryCandles({\n instId,\n bar,\n after: `${currentStartTime}`,\n limit: '100',\n });\n if (res.code !== '0') {\n throw `API failed: ${res.code} ${res.msg}`;\n }\n if (res.data.length === 0) break;\n currentStartTime = +res.data[res.data.length - 1][0];\n const data = res.data.map(\n (x): IOHLC => ({\n series_id,\n datasource_id,\n product_id,\n duration,\n created_at: formatTime(+x[0]),\n closed_at: formatTime(+x[0] + offset),\n open: x[1],\n high: x[2],\n low: x[3],\n close: x[4],\n volume: x[5],\n open_interest: '0',\n }),\n );\n yield data;\n await firstValueFrom(timer(1000));\n }\n },\n});\n\nTerminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (series_id) => {\n // const [] = decodePath(args)\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const [, instId] = decodePath(product_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const candleType = DURATION_TO_OKX_CANDLE_TYPE[duration];\n console.info(formatTime(Date.now()), `subscribe`, series_id);\n return new Observable<IOHLC>((subscriber) => {\n console.info(formatTime(Date.now()), `subscribe`, candleType, instId);\n const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');\n okxBusinessWsClient.subscribe(candleType, instId, async (data: string[]) => {\n const created_at = Number(data[0]);\n const closed_at = created_at + offset;\n const open = data[1];\n const high = data[2];\n const low = data[3];\n const close = data[4];\n if (isNaN(closed_at)) {\n return;\n }\n console.info(formatTime(Date.now()), `insertData`, data);\n const cancelData: IOHLC = {\n closed_at: formatTime(closed_at),\n created_at: formatTime(created_at),\n open,\n high,\n low,\n close,\n series_id,\n datasource_id,\n duration,\n product_id,\n volume: '0',\n open_interest: '0',\n };\n subscriber.next(cancelData);\n });\n return () => {\n okxBusinessWsClient.unsubscribe(candleType, instId);\n };\n }).pipe(\n writeToSQL({\n tableName: 'ohlc',\n conflictKeys: ['created_at', 'series_id'],\n writeInterval: 1000,\n terminal: Terminal.fromNodeEnv(),\n keyFn: (x) => encodePath(x.created_at, x.series_id),\n }),\n );\n});\n"]}
|
package/lib/websocket.d.ts
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
|
1
|
+
import { Subscription } from 'rxjs';
|
2
|
+
export declare class OKXWsClient {
|
2
3
|
ws: WebSocket;
|
3
4
|
connected: boolean;
|
4
5
|
subscriptions: Set<string>;
|
5
6
|
handlers: Record<string, Function>;
|
6
7
|
pendingSub: string[];
|
8
|
+
keepAlive: Subscription;
|
7
9
|
constructor(url: string);
|
8
10
|
handleMessage(raw: any): void;
|
9
11
|
subscribe(channel: string, instId?: string, handler?: Function): void;
|
10
12
|
unsubscribe(channel: string, instId?: string): void;
|
11
13
|
}
|
12
|
-
export declare const okxBusinessWsClient: OKXWsClient;
|
13
|
-
export {};
|
14
14
|
//# sourceMappingURL=websocket.d.ts.map
|
package/lib/websocket.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,YAAY,EAAO,MAAM,MAAM,CAAC;AAGnD,qBAAa,WAAW;IACtB,EAAE,EAAE,SAAS,CAAC;IACd,SAAS,EAAE,OAAO,CAAS;IAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,YAAY,CAAC;gBACZ,GAAG,EAAE,MAAM;IAgCvB,aAAa,CAAC,GAAG,EAAE,GAAG;IAiBtB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ;IA0B9D,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAiB7C"}
|
package/lib/websocket.js
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.OKXWsClient = void 0;
|
4
4
|
const utils_1 = require("@yuants/utils");
|
5
|
+
const rxjs_1 = require("rxjs");
|
5
6
|
// import WebSocket from 'ws';
|
6
7
|
class OKXWsClient {
|
7
8
|
constructor(url) {
|
@@ -9,6 +10,13 @@ class OKXWsClient {
|
|
9
10
|
// this.instId = instId;
|
10
11
|
this.ws = new WebSocket(url);
|
11
12
|
this.pendingSub = [];
|
13
|
+
this.keepAlive = (0, rxjs_1.interval)(25000)
|
14
|
+
.pipe((0, rxjs_1.tap)(() => {
|
15
|
+
if (this.connected) {
|
16
|
+
this.ws.send('ping');
|
17
|
+
}
|
18
|
+
}))
|
19
|
+
.subscribe();
|
12
20
|
// this.ws.
|
13
21
|
this.ws.addEventListener('open', () => {
|
14
22
|
this.connected = true;
|
@@ -28,6 +36,9 @@ class OKXWsClient {
|
|
28
36
|
// 处理消息
|
29
37
|
handleMessage(raw) {
|
30
38
|
var _a, _b;
|
39
|
+
if (raw.data === 'pong') {
|
40
|
+
return;
|
41
|
+
}
|
31
42
|
const msg = JSON.parse(raw.data);
|
32
43
|
if ((_a = msg.arg) === null || _a === void 0 ? void 0 : _a.channel) {
|
33
44
|
const channelId = (0, utils_1.encodePath)(msg.arg.channel, msg.arg.instId);
|
@@ -75,9 +86,12 @@ class OKXWsClient {
|
|
75
86
|
};
|
76
87
|
this.ws.send(JSON.stringify(unSubMsg));
|
77
88
|
this.subscriptions.delete(channelId);
|
89
|
+
if (this.subscriptions.size === 0) {
|
90
|
+
this.keepAlive.unsubscribe();
|
91
|
+
}
|
78
92
|
delete this.handlers[channelId];
|
79
93
|
console.info(`📩 Sent unsubscribe for ${channelId}`);
|
80
94
|
}
|
81
95
|
}
|
82
|
-
exports.
|
96
|
+
exports.OKXWsClient = OKXWsClient;
|
83
97
|
//# sourceMappingURL=websocket.js.map
|
package/lib/websocket.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":";;;AAAA,yCAAuD;AACvD,8BAA8B;AAE9B,
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodePath, formatTime } from '@yuants/utils';\nimport { interval, Subscription, tap } from 'rxjs';\n// import WebSocket from 'ws';\n\nexport class OKXWsClient {\n ws: WebSocket;\n connected: boolean = false;\n subscriptions: Set<string>;\n handlers: Record<string, Function>;\n pendingSub: string[];\n keepAlive: Subscription;\n constructor(url: string) {\n // this.instId = instId;\n this.ws = new WebSocket(url);\n this.pendingSub = [];\n this.keepAlive = interval(25000)\n .pipe(\n tap(() => {\n if (this.connected) {\n this.ws.send('ping');\n }\n }),\n )\n .subscribe();\n // this.ws.\n this.ws.addEventListener('open', () => {\n this.connected = true;\n console.info(formatTime(Date.now()), '✅ WS connected');\n while (this.pendingSub.length > 0) {\n const msg = this.pendingSub.shift();\n if (msg) {\n this.ws.send(msg);\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${msg}`);\n }\n }\n });\n\n this.ws.addEventListener('message', (raw) => this.handleMessage(raw));\n this.subscriptions = new Set();\n this.handlers = {}; // key: channel, value: callback\n }\n\n // 处理消息\n handleMessage(raw: any) {\n if (raw.data === 'pong') {\n return;\n }\n const msg = JSON.parse(raw.data);\n if (msg.arg?.channel) {\n const channelId = encodePath(msg.arg.channel, msg.arg.instId);\n const data = msg.data?.[0];\n if (data && this.handlers[channelId]) {\n this.handlers[channelId](data, msg.arg);\n }\n } else if (msg.event) {\n console.info('Event:', msg);\n }\n }\n\n // 调用订阅\n subscribe(channel: string, instId?: string, handler?: Function) {\n const channelId = encodePath(channel, instId);\n if (this.subscriptions.has(channelId)) {\n console.info(formatTime(Date.now()), `⚠️ Already subscribed: ${channelId}`);\n return;\n }\n\n const subMsg = {\n op: 'subscribe',\n args: [{ channel, instId }],\n };\n\n if (this.connected) {\n this.ws.send(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${channelId}`);\n } else {\n this.pendingSub.push(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 add subscribe for ${channelId} to pending list`);\n }\n this.subscriptions.add(channelId);\n if (handler) {\n this.handlers[channelId] = handler;\n }\n }\n\n // 取消订阅\n unsubscribe(channel: string, instId?: string) {\n const channelId = encodePath(channel, instId);\n if (!this.subscriptions.has(channelId)) return;\n\n const unSubMsg = {\n op: 'unsubscribe',\n args: [{ channel, instId }],\n };\n\n this.ws.send(JSON.stringify(unSubMsg));\n this.subscriptions.delete(channelId);\n if (this.subscriptions.size === 0) {\n this.keepAlive.unsubscribe();\n }\n delete this.handlers[channelId];\n console.info(`📩 Sent unsubscribe for ${channelId}`);\n }\n}\n"]}
|
package/package.json
CHANGED
package/temp/image-tag
CHANGED
@@ -1 +1 @@
|
|
1
|
-
sha-
|
1
|
+
sha-d95979d74a67e3acd2992d0122adf5416f2953aa
|
package/temp/package-deps.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
|
-
"apps/vendor-okx/CHANGELOG.json": "
|
3
|
-
"apps/vendor-okx/CHANGELOG.md": "
|
2
|
+
"apps/vendor-okx/CHANGELOG.json": "87a6ba0fc2a5e991bf0e1effc2c23e42438992e2",
|
3
|
+
"apps/vendor-okx/CHANGELOG.md": "405b54aa42cb886fc0c9b5a441695bad90b5d95a",
|
4
4
|
"apps/vendor-okx/README.md": "ac3d1f6c4c8d73066664699b0bb1b01db02e67a2",
|
5
5
|
"apps/vendor-okx/api-extractor.json": "62f4fd324425b9a235f0c117975967aab09ced0c",
|
6
6
|
"apps/vendor-okx/build/Dockerfile": "e625b9593e496c343297c9ce133d6cc4be9617a7",
|
@@ -8,7 +8,7 @@
|
|
8
8
|
"apps/vendor-okx/config/rig.json": "f6c7b5537dc77a3170ba9f008bae3b6c3ee11956",
|
9
9
|
"apps/vendor-okx/config/typescript.json": "854907e8a821f2050f6533368db160c649c25348",
|
10
10
|
"apps/vendor-okx/etc/vendor-okx.api.md": "92c54ccd547d2ad81ca6088158ca193e85c208df",
|
11
|
-
"apps/vendor-okx/package.json": "
|
11
|
+
"apps/vendor-okx/package.json": "2fa5993fee4ef8b59320546bfa9c1dd4593f3ed2",
|
12
12
|
"apps/vendor-okx/src/account.ts": "7e8bb44845269a401a850aff2e5bf170b0811bd8",
|
13
13
|
"apps/vendor-okx/src/api.ts": "0433a359ec1fb84c866c1875b630cbb861696533",
|
14
14
|
"apps/vendor-okx/src/cli.ts": "9bf6b5559a6c6f33da20e74cc6c5d702c60ec891",
|
@@ -18,11 +18,11 @@
|
|
18
18
|
"apps/vendor-okx/src/interest_rate.ts": "da173624ffed4cb083d797328174fe717809769c",
|
19
19
|
"apps/vendor-okx/src/legacy_index.ts": "19f9e4af4b6b8ae846e0800b1bd52d5eeaa8a2ce",
|
20
20
|
"apps/vendor-okx/src/logger.ts": "d25d427e74f46819a601e0cb17d5358b22c8db7b",
|
21
|
-
"apps/vendor-okx/src/ohlc.ts": "
|
21
|
+
"apps/vendor-okx/src/ohlc.ts": "0b8c9b32238a4e26954dbd5360e129b3850df1ae",
|
22
22
|
"apps/vendor-okx/src/order.ts": "09509ae5af4b212cc1c99c55c436b3b0ce8bda33",
|
23
23
|
"apps/vendor-okx/src/product.ts": "a2e7feb86bc01fe3b1af6dcb9a9ebfba6be91434",
|
24
24
|
"apps/vendor-okx/src/quote.ts": "b8dd019e6cceb50e486a9d41e54385bda4e21ab0",
|
25
|
-
"apps/vendor-okx/src/websocket.ts": "
|
25
|
+
"apps/vendor-okx/src/websocket.ts": "59791907faef7adf2d1d4b6876cc6a476b5f7e3e",
|
26
26
|
"apps/vendor-okx/tsconfig.json": "81da8f78196974b5d15da0edb6b2d9f48641063c",
|
27
27
|
"apps/vendor-okx/.rush/temp/shrinkwrap-deps.json": "87df045a10e829fd62d50013da30fd929442d54c",
|
28
28
|
"libraries/protocol/temp/package-deps.json": "d326f24867d9ae3fef16ff84ba537eabb7c8adf0",
|