@tradejs/connectors 3.0.1 → 3.1.1
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 +2 -0
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +114 -381
- package/dist/index.mjs +96 -368
- package/package.json +7 -5
package/dist/index.js
CHANGED
|
@@ -51,21 +51,42 @@ module.exports = __toCommonJS(index_exports);
|
|
|
51
51
|
// src/ByBit/index.ts
|
|
52
52
|
var import_lodash = __toESM(require("lodash"));
|
|
53
53
|
var import_chalk = __toESM(require("chalk"));
|
|
54
|
-
var
|
|
55
|
-
var
|
|
56
|
-
var
|
|
54
|
+
var import_async = require("@tradejs/core/async");
|
|
55
|
+
var import_constants = require("@tradejs/core/constants");
|
|
56
|
+
var import_data = require("@tradejs/core/data");
|
|
57
57
|
var import_math = require("@tradejs/core/math");
|
|
58
58
|
var import_tickers = require("@tradejs/core/tickers");
|
|
59
|
-
var
|
|
60
|
-
var import_logger3 = require("@tradejs/infra/logger");
|
|
59
|
+
var import_time2 = require("@tradejs/core/time");
|
|
61
60
|
|
|
62
61
|
// src/ByBit/client.ts
|
|
63
62
|
var import_bybit_api = require("bybit-api");
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
|
|
64
|
+
// src/shared/runtime.ts
|
|
65
|
+
var noop = () => void 0;
|
|
66
|
+
var silentConnectorLogger = {
|
|
67
|
+
log: noop,
|
|
68
|
+
info: noop,
|
|
69
|
+
warn: noop,
|
|
70
|
+
error: noop
|
|
71
|
+
};
|
|
72
|
+
var getConnectorLogger = (runtime) => runtime?.logger ?? silentConnectorLogger;
|
|
73
|
+
var getConnectorAccountResolver = (runtime) => runtime?.resolveTradingAccount ?? (async () => null);
|
|
74
|
+
var decorateConnectorKline = (runtime, options) => runtime?.createCachedKline(options) ?? options.request;
|
|
75
|
+
|
|
76
|
+
// src/ByBit/client.ts
|
|
66
77
|
var PRIVATE_RECV_WINDOW_MS = 1e4;
|
|
67
|
-
var
|
|
68
|
-
const
|
|
78
|
+
var getApiRegion = () => {
|
|
79
|
+
const apiRegion = process.env.TRADEJS_BYBIT_API_REGION?.trim();
|
|
80
|
+
return apiRegion ? apiRegion : void 0;
|
|
81
|
+
};
|
|
82
|
+
var getApiRegionOptions = () => {
|
|
83
|
+
const apiRegion = getApiRegion();
|
|
84
|
+
return apiRegion ? { apiRegion } : {};
|
|
85
|
+
};
|
|
86
|
+
var getClient = async (config, access = "private", runtime) => {
|
|
87
|
+
const logger = getConnectorLogger(runtime);
|
|
88
|
+
const resolveTradingAccount = getConnectorAccountResolver(runtime);
|
|
89
|
+
const account = access === "public" && !config.accountId ? null : await resolveTradingAccount({
|
|
69
90
|
userName: config.userName,
|
|
70
91
|
accountId: config.accountId,
|
|
71
92
|
provider: "bybit",
|
|
@@ -74,24 +95,26 @@ var getClient = async (config, access = "private") => {
|
|
|
74
95
|
const useTestnet = account?.environment === "testnet";
|
|
75
96
|
if (access === "public") {
|
|
76
97
|
return new import_bybit_api.RestClientV5({
|
|
98
|
+
...getApiRegionOptions(),
|
|
77
99
|
parseAPIRateLimits: true,
|
|
78
100
|
testnet: useTestnet
|
|
79
101
|
});
|
|
80
102
|
}
|
|
81
103
|
if (!account?.apiKey || !account.apiSecret) {
|
|
82
104
|
if (config.accountId) {
|
|
83
|
-
|
|
105
|
+
logger.log(
|
|
84
106
|
"error",
|
|
85
107
|
"Bybit trading account config not found: user=%s account=%s",
|
|
86
108
|
config.userName,
|
|
87
109
|
config.accountId
|
|
88
110
|
);
|
|
89
111
|
} else {
|
|
90
|
-
|
|
112
|
+
logger.log("error", "connection config not found: %s", config.userName);
|
|
91
113
|
}
|
|
92
114
|
return null;
|
|
93
115
|
}
|
|
94
116
|
const client = new import_bybit_api.RestClientV5({
|
|
117
|
+
...getApiRegionOptions(),
|
|
95
118
|
key: account.apiKey,
|
|
96
119
|
secret: account.apiSecret,
|
|
97
120
|
parseAPIRateLimits: true,
|
|
@@ -104,310 +127,11 @@ var getClient = async (config, access = "private") => {
|
|
|
104
127
|
return client;
|
|
105
128
|
};
|
|
106
129
|
|
|
107
|
-
// src/shared/timescaleKlineCache.ts
|
|
108
|
-
var import_constants = require("@tradejs/core/constants");
|
|
109
|
-
var import_data = require("@tradejs/core/data");
|
|
110
|
-
var import_time = require("@tradejs/core/time");
|
|
111
|
-
var import_async = require("@tradejs/core/async");
|
|
112
|
-
var import_logger2 = require("@tradejs/infra/logger");
|
|
113
|
-
var import_candles = require("@tradejs/infra/timescale/candles");
|
|
114
|
-
var DEFAULT_LIMIT = 1e3;
|
|
115
|
-
var DEFAULT_CACHE_FALLBACK_WINDOW = 1e3;
|
|
116
|
-
var DEFAULT_TIMESCALE_RETRIES = 2;
|
|
117
|
-
var DEFAULT_TIMESCALE_RETRY_DELAY_MS = 1e3;
|
|
118
|
-
var resolveNonNegativeInt = (value, fallback) => {
|
|
119
|
-
const parsed = Number(value);
|
|
120
|
-
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
121
|
-
return fallback;
|
|
122
|
-
}
|
|
123
|
-
return Math.floor(parsed);
|
|
124
|
-
};
|
|
125
|
-
var getTimescaleRetryCount = () => resolveNonNegativeInt(
|
|
126
|
-
process.env.TIMESCALE_KLINE_RETRIES,
|
|
127
|
-
DEFAULT_TIMESCALE_RETRIES
|
|
128
|
-
);
|
|
129
|
-
var getTimescaleRetryDelayMs = () => resolveNonNegativeInt(
|
|
130
|
-
process.env.TIMESCALE_KLINE_RETRY_DELAY_MS,
|
|
131
|
-
DEFAULT_TIMESCALE_RETRY_DELAY_MS
|
|
132
|
-
);
|
|
133
|
-
var intervalMsOf = (interval) => interval * 6e4;
|
|
134
|
-
var clampToClosedCandle = (value, intervalMs) => Math.floor(value / intervalMs) * intervalMs;
|
|
135
|
-
var normalizeRangeToClosed = (intervalMs, start, end) => {
|
|
136
|
-
const lastClosed = Math.floor(Date.now() / intervalMs) * intervalMs;
|
|
137
|
-
const normStart = start !== void 0 ? clampToClosedCandle(start, intervalMs) : 0;
|
|
138
|
-
const cappedEnd = Math.min(end ?? Date.now(), lastClosed);
|
|
139
|
-
const normEnd = clampToClosedCandle(cappedEnd, intervalMs);
|
|
140
|
-
return { normStart, normEnd };
|
|
141
|
-
};
|
|
142
|
-
var rowsToKline = (rows) => rows.map(({ ts, ...data }) => ({
|
|
143
|
-
timestamp: new Date(ts).getTime(),
|
|
144
|
-
...data
|
|
145
|
-
}));
|
|
146
|
-
var createTimescaleCachedKline = ({
|
|
147
|
-
provider,
|
|
148
|
-
request,
|
|
149
|
-
intervalToMinutes: intervalToMinutes3,
|
|
150
|
-
limit = DEFAULT_LIMIT,
|
|
151
|
-
cacheFallbackWindow = DEFAULT_CACHE_FALLBACK_WINDOW
|
|
152
|
-
}) => {
|
|
153
|
-
let isTimescaleFallbackMode = false;
|
|
154
|
-
const runTimescaleOperation = async (operation) => {
|
|
155
|
-
const retries = getTimescaleRetryCount();
|
|
156
|
-
const retryDelayMs = getTimescaleRetryDelayMs();
|
|
157
|
-
for (let attempt = 0; ; attempt += 1) {
|
|
158
|
-
try {
|
|
159
|
-
return await operation();
|
|
160
|
-
} catch (error) {
|
|
161
|
-
if (attempt >= retries) {
|
|
162
|
-
throw error;
|
|
163
|
-
}
|
|
164
|
-
const waitMs = retryDelayMs * 2 ** attempt;
|
|
165
|
-
if (waitMs > 0) {
|
|
166
|
-
await (0, import_async.delay)(waitMs);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
const loadData = async (direction, pointer, limitBoundary, requestParams, intervalMs, options = {}) => {
|
|
172
|
-
if (pointer === void 0) return { data: [], loaded: false };
|
|
173
|
-
let accumulated = [];
|
|
174
|
-
let fulfilled = false;
|
|
175
|
-
let loaded = false;
|
|
176
|
-
const shouldAccumulate = options.accumulate ?? true;
|
|
177
|
-
while (!fulfilled) {
|
|
178
|
-
const currentPointer = pointer;
|
|
179
|
-
const params = {
|
|
180
|
-
symbol: requestParams.symbol,
|
|
181
|
-
interval: requestParams.interval,
|
|
182
|
-
silent: requestParams.silent,
|
|
183
|
-
end: requestParams.end
|
|
184
|
-
};
|
|
185
|
-
if (direction === "older") {
|
|
186
|
-
params.end = pointer;
|
|
187
|
-
if (limitBoundary !== void 0) params.start = limitBoundary;
|
|
188
|
-
} else {
|
|
189
|
-
params.start = pointer;
|
|
190
|
-
if (limitBoundary !== void 0) params.end = limitBoundary;
|
|
191
|
-
}
|
|
192
|
-
const partData = await request(params);
|
|
193
|
-
if (!partData.length) {
|
|
194
|
-
fulfilled = true;
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
loaded = true;
|
|
198
|
-
if (options.onPartData) {
|
|
199
|
-
await options.onPartData(partData);
|
|
200
|
-
}
|
|
201
|
-
if (shouldAccumulate) {
|
|
202
|
-
accumulated = direction === "older" ? (0, import_data.mergeData)(partData, accumulated) : (0, import_data.mergeData)(accumulated, partData);
|
|
203
|
-
}
|
|
204
|
-
const boundaryReached = limitBoundary !== void 0 && (direction === "older" && currentPointer <= limitBoundary || direction === "newer" && currentPointer >= limitBoundary);
|
|
205
|
-
if (partData.length < limit || boundaryReached) {
|
|
206
|
-
fulfilled = true;
|
|
207
|
-
break;
|
|
208
|
-
}
|
|
209
|
-
const nextPointer = direction === "older" ? (0, import_time.getItemTimestamp)(partData[0]) - intervalMs : (0, import_time.getItemTimestamp)(partData[partData.length - 1]) + intervalMs;
|
|
210
|
-
if (!Number.isFinite(nextPointer) || nextPointer === currentPointer) {
|
|
211
|
-
fulfilled = true;
|
|
212
|
-
break;
|
|
213
|
-
}
|
|
214
|
-
pointer = nextPointer;
|
|
215
|
-
}
|
|
216
|
-
return { data: accumulated, loaded };
|
|
217
|
-
};
|
|
218
|
-
const refreshTail = async ({
|
|
219
|
-
symbol,
|
|
220
|
-
interval,
|
|
221
|
-
silent,
|
|
222
|
-
tailCount = 2
|
|
223
|
-
}) => {
|
|
224
|
-
const intMinutes = intervalToMinutes3(interval);
|
|
225
|
-
if (!intMinutes) {
|
|
226
|
-
import_logger2.logger.log("error", "refreshTail: invalid interval %s", interval);
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
const intervalMs = intervalMsOf(intMinutes);
|
|
230
|
-
const lastClosed = Math.floor(Date.now() / intervalMs) * intervalMs;
|
|
231
|
-
const tailEnd = lastClosed + intervalMs;
|
|
232
|
-
const tailStart = tailEnd - tailCount * intervalMs;
|
|
233
|
-
const part = await request({
|
|
234
|
-
symbol,
|
|
235
|
-
interval,
|
|
236
|
-
start: tailStart,
|
|
237
|
-
end: tailEnd,
|
|
238
|
-
silent
|
|
239
|
-
});
|
|
240
|
-
if (part.length) {
|
|
241
|
-
await runTimescaleOperation(
|
|
242
|
-
() => (0, import_candles.upsertCandles)((0, import_candles.toRows)(provider, symbol, intMinutes, part))
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
return async ({
|
|
247
|
-
symbol,
|
|
248
|
-
interval,
|
|
249
|
-
start: defaultStart,
|
|
250
|
-
end: defaultEnd,
|
|
251
|
-
silent = false,
|
|
252
|
-
cacheOnly = false,
|
|
253
|
-
warmOnly = false
|
|
254
|
-
}) => {
|
|
255
|
-
const intMinutes = intervalToMinutes3(interval);
|
|
256
|
-
if (!intMinutes) {
|
|
257
|
-
import_logger2.logger.log("error", "kline: invalid interval %s", interval);
|
|
258
|
-
return [];
|
|
259
|
-
}
|
|
260
|
-
if (defaultStart !== void 0 && defaultEnd !== void 0 && defaultEnd <= defaultStart) {
|
|
261
|
-
return [];
|
|
262
|
-
}
|
|
263
|
-
const intervalMs = intervalMsOf(intMinutes);
|
|
264
|
-
try {
|
|
265
|
-
const edges = await runTimescaleOperation(
|
|
266
|
-
() => (0, import_candles.getDataEdges)(provider, symbol, intMinutes)
|
|
267
|
-
);
|
|
268
|
-
let dataStart = edges.min;
|
|
269
|
-
let dataEnd = edges.max;
|
|
270
|
-
const { normStart, normEnd } = normalizeRangeToClosed(
|
|
271
|
-
intervalMs,
|
|
272
|
-
defaultStart,
|
|
273
|
-
defaultEnd
|
|
274
|
-
);
|
|
275
|
-
if (cacheOnly) {
|
|
276
|
-
const base = edges.max ?? Date.now();
|
|
277
|
-
const s = Math.max(
|
|
278
|
-
defaultStart ?? base - cacheFallbackWindow * intervalMs,
|
|
279
|
-
0
|
|
280
|
-
);
|
|
281
|
-
const e = defaultEnd ?? base;
|
|
282
|
-
const dbData2 = await runTimescaleOperation(
|
|
283
|
-
() => (0, import_candles.getCandlesRange)(provider, symbol, intMinutes, s, e)
|
|
284
|
-
);
|
|
285
|
-
return rowsToKline(dbData2);
|
|
286
|
-
}
|
|
287
|
-
const needOlderData = defaultStart !== void 0 && (dataStart === void 0 || normStart < dataStart);
|
|
288
|
-
const persistPartData = warmOnly ? (partData) => runTimescaleOperation(
|
|
289
|
-
() => (0, import_candles.upsertCandles)((0, import_candles.toRows)(provider, symbol, intMinutes, partData))
|
|
290
|
-
) : void 0;
|
|
291
|
-
if (needOlderData) {
|
|
292
|
-
const pointerForOlder = dataStart ?? normEnd ?? Date.now();
|
|
293
|
-
const olderResult = await loadData(
|
|
294
|
-
"older",
|
|
295
|
-
pointerForOlder,
|
|
296
|
-
normStart,
|
|
297
|
-
{
|
|
298
|
-
symbol,
|
|
299
|
-
interval,
|
|
300
|
-
silent,
|
|
301
|
-
start: normStart,
|
|
302
|
-
end: pointerForOlder
|
|
303
|
-
},
|
|
304
|
-
intervalMs,
|
|
305
|
-
{
|
|
306
|
-
accumulate: !warmOnly,
|
|
307
|
-
onPartData: persistPartData
|
|
308
|
-
}
|
|
309
|
-
);
|
|
310
|
-
if (warmOnly && olderResult.loaded) {
|
|
311
|
-
dataStart = normStart;
|
|
312
|
-
if (dataEnd === void 0) {
|
|
313
|
-
dataEnd = normEnd;
|
|
314
|
-
}
|
|
315
|
-
} else if (olderResult.data.length) {
|
|
316
|
-
await runTimescaleOperation(
|
|
317
|
-
() => (0, import_candles.upsertCandles)(
|
|
318
|
-
(0, import_candles.toRows)(provider, symbol, intMinutes, olderResult.data)
|
|
319
|
-
)
|
|
320
|
-
);
|
|
321
|
-
dataStart = normStart;
|
|
322
|
-
if (dataEnd === void 0) {
|
|
323
|
-
dataEnd = normEnd;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
const needNewerData = defaultEnd !== void 0 && (dataEnd === void 0 || normEnd > dataEnd);
|
|
328
|
-
if (needNewerData) {
|
|
329
|
-
const fallbackStart = (0, import_time.getTimestamp)(import_constants.PRELOAD_FALLBACK_DAYS);
|
|
330
|
-
const pointerForNewer = dataEnd ?? (defaultStart !== void 0 ? normStart : fallbackStart) ?? 0;
|
|
331
|
-
const newerResult = await loadData(
|
|
332
|
-
"newer",
|
|
333
|
-
pointerForNewer,
|
|
334
|
-
normEnd,
|
|
335
|
-
{
|
|
336
|
-
symbol,
|
|
337
|
-
interval,
|
|
338
|
-
silent,
|
|
339
|
-
start: pointerForNewer,
|
|
340
|
-
end: normEnd
|
|
341
|
-
},
|
|
342
|
-
intervalMs,
|
|
343
|
-
{
|
|
344
|
-
accumulate: !warmOnly,
|
|
345
|
-
onPartData: persistPartData
|
|
346
|
-
}
|
|
347
|
-
);
|
|
348
|
-
if (warmOnly && newerResult.loaded) {
|
|
349
|
-
dataEnd = normEnd;
|
|
350
|
-
} else if (newerResult.data.length) {
|
|
351
|
-
await runTimescaleOperation(
|
|
352
|
-
() => (0, import_candles.upsertCandles)(
|
|
353
|
-
(0, import_candles.toRows)(provider, symbol, intMinutes, newerResult.data)
|
|
354
|
-
)
|
|
355
|
-
);
|
|
356
|
-
dataEnd = normEnd;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
const isRightEdgeQuery = defaultEnd === void 0 || defaultEnd && defaultEnd >= Date.now() - intervalMs;
|
|
360
|
-
if (!cacheOnly && isRightEdgeQuery) {
|
|
361
|
-
await refreshTail({ symbol, interval, silent });
|
|
362
|
-
}
|
|
363
|
-
if (warmOnly) {
|
|
364
|
-
if (isTimescaleFallbackMode) {
|
|
365
|
-
isTimescaleFallbackMode = false;
|
|
366
|
-
import_logger2.logger.log("info", "TimescaleDB connection restored for kline cache");
|
|
367
|
-
}
|
|
368
|
-
return [];
|
|
369
|
-
}
|
|
370
|
-
const rangeStart = defaultStart ?? dataStart ?? 0;
|
|
371
|
-
const rangeEnd = defaultEnd ?? dataEnd ?? Date.now();
|
|
372
|
-
const { normStart: finalStart, normEnd: finalEnd } = normalizeRangeToClosed(intervalMs, rangeStart, rangeEnd);
|
|
373
|
-
const dbData = await runTimescaleOperation(
|
|
374
|
-
() => (0, import_candles.getCandlesRange)(provider, symbol, intMinutes, finalStart, finalEnd)
|
|
375
|
-
);
|
|
376
|
-
if (isTimescaleFallbackMode) {
|
|
377
|
-
isTimescaleFallbackMode = false;
|
|
378
|
-
import_logger2.logger.log("info", "TimescaleDB connection restored for kline cache");
|
|
379
|
-
}
|
|
380
|
-
return rowsToKline(dbData);
|
|
381
|
-
} catch (error) {
|
|
382
|
-
if (!isTimescaleFallbackMode) {
|
|
383
|
-
isTimescaleFallbackMode = true;
|
|
384
|
-
import_logger2.logger.log(
|
|
385
|
-
"warn",
|
|
386
|
-
"TimescaleDB unavailable for %s %s: %s. Falling back to exchange API.",
|
|
387
|
-
symbol,
|
|
388
|
-
interval,
|
|
389
|
-
String(error)
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
if (cacheOnly || warmOnly) {
|
|
393
|
-
return [];
|
|
394
|
-
}
|
|
395
|
-
return request({
|
|
396
|
-
symbol,
|
|
397
|
-
interval,
|
|
398
|
-
start: defaultStart,
|
|
399
|
-
end: defaultEnd,
|
|
400
|
-
silent
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
};
|
|
404
|
-
};
|
|
405
|
-
|
|
406
130
|
// src/ByBit/utils.ts
|
|
407
|
-
var
|
|
131
|
+
var import_time = require("@tradejs/core/time");
|
|
408
132
|
var BYBIT_CATEGORY = "linear";
|
|
409
133
|
var parseKlineItem = (item) => ({
|
|
410
|
-
dt: (0,
|
|
134
|
+
dt: (0, import_time.formatUnix)(parseInt(item[0])),
|
|
411
135
|
timestamp: parseInt(item[0]),
|
|
412
136
|
open: parseFloat(item[1]),
|
|
413
137
|
high: parseFloat(item[2]),
|
|
@@ -598,7 +322,8 @@ var loadFundingFeeRows = async ({
|
|
|
598
322
|
client,
|
|
599
323
|
startTime,
|
|
600
324
|
endTime,
|
|
601
|
-
symbol
|
|
325
|
+
symbol,
|
|
326
|
+
logger
|
|
602
327
|
}) => {
|
|
603
328
|
if (typeof client.getTransactionLog !== "function") {
|
|
604
329
|
return [];
|
|
@@ -617,7 +342,7 @@ var loadFundingFeeRows = async ({
|
|
|
617
342
|
...cursor ? { cursor } : {}
|
|
618
343
|
});
|
|
619
344
|
if (response?.retCode !== 0) {
|
|
620
|
-
|
|
345
|
+
logger.log(
|
|
621
346
|
"debug",
|
|
622
347
|
"funding transaction log retCode: %s, %s",
|
|
623
348
|
response?.retCode,
|
|
@@ -649,7 +374,7 @@ var loadFundingFeeRows = async ({
|
|
|
649
374
|
}
|
|
650
375
|
return rows;
|
|
651
376
|
} catch (error) {
|
|
652
|
-
|
|
377
|
+
logger.log("debug", "funding transaction log failed: %s", error);
|
|
653
378
|
return [];
|
|
654
379
|
}
|
|
655
380
|
};
|
|
@@ -696,7 +421,8 @@ var resolveKlineRetryDelayMs = (res, attempt) => {
|
|
|
696
421
|
);
|
|
697
422
|
return backoffMs + jitterMs;
|
|
698
423
|
};
|
|
699
|
-
var ByBitConnectorCreator = async (config) => {
|
|
424
|
+
var ByBitConnectorCreator = async (config, runtime) => {
|
|
425
|
+
const logger = getConnectorLogger(runtime);
|
|
700
426
|
let state = {};
|
|
701
427
|
const universe = (0, import_types.resolveConnectorUniverse)(
|
|
702
428
|
BYBIT_CAPABILITIES,
|
|
@@ -707,11 +433,11 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
707
433
|
const positionSnapshotCache = /* @__PURE__ */ new Map();
|
|
708
434
|
const inflightPositionSnapshots = /* @__PURE__ */ new Map();
|
|
709
435
|
const getPublicClient = async () => {
|
|
710
|
-
publicClientPromise ??= getClient(config, "public");
|
|
436
|
+
publicClientPromise ??= getClient(config, "public", runtime);
|
|
711
437
|
return publicClientPromise;
|
|
712
438
|
};
|
|
713
439
|
const getPrivateClient = async () => {
|
|
714
|
-
privateClientPromise ??= getClient(config, "private");
|
|
440
|
+
privateClientPromise ??= getClient(config, "private", runtime);
|
|
715
441
|
return privateClientPromise;
|
|
716
442
|
};
|
|
717
443
|
const instrumentCache = /* @__PURE__ */ new Map();
|
|
@@ -839,7 +565,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
839
565
|
silent
|
|
840
566
|
}) => {
|
|
841
567
|
const normalizedStart = (0, import_math.round)(
|
|
842
|
-
start || (0,
|
|
568
|
+
start || (0, import_time2.getTimestamp)(import_constants.PRELOAD_FALLBACK_DAYS),
|
|
843
569
|
0
|
|
844
570
|
);
|
|
845
571
|
const normalizedEnd = (0, import_math.round)(end || Date.now());
|
|
@@ -861,7 +587,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
861
587
|
if (isKlineRateLimited(kline)) {
|
|
862
588
|
if (attempt < KLINE_RATE_LIMIT_MAX_ATTEMPTS) {
|
|
863
589
|
const waitMs = resolveKlineRetryDelayMs(kline, attempt);
|
|
864
|
-
|
|
590
|
+
logger.log(
|
|
865
591
|
"warn",
|
|
866
592
|
"kline rate limited for %s %s: attempt=%s/%s waitMs=%s",
|
|
867
593
|
symbol,
|
|
@@ -870,13 +596,13 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
870
596
|
KLINE_RATE_LIMIT_MAX_ATTEMPTS,
|
|
871
597
|
waitMs
|
|
872
598
|
);
|
|
873
|
-
await (0,
|
|
599
|
+
await (0, import_async.delay)(waitMs);
|
|
874
600
|
continue;
|
|
875
601
|
}
|
|
876
602
|
}
|
|
877
603
|
if (!kline?.result?.list) {
|
|
878
604
|
const responseError = typeof kline?.retMsg === "string" && kline.retMsg !== "OK" ? `${kline.retMsg}${typeof kline?.retCode === "number" ? ` (retCode: ${kline.retCode})` : ""}` : typeof kline?.retCode === "number" && kline.retCode !== 0 ? `retCode: ${kline.retCode}` : "";
|
|
879
|
-
|
|
605
|
+
logger.log(
|
|
880
606
|
"error",
|
|
881
607
|
"empty kline.list for %s %s%s",
|
|
882
608
|
symbol,
|
|
@@ -886,10 +612,10 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
886
612
|
return [];
|
|
887
613
|
}
|
|
888
614
|
if (!silent && (process.stdout.isTTY || process.env.TRADEJS_LOG_KLINE_REQUESTS === "1")) {
|
|
889
|
-
|
|
615
|
+
logger.log(
|
|
890
616
|
"info",
|
|
891
617
|
"%s %s %s %s",
|
|
892
|
-
import_chalk.default.yellow((0,
|
|
618
|
+
import_chalk.default.yellow((0, import_time2.formatUnix)(normalizedEnd)),
|
|
893
619
|
import_chalk.default.cyan(symbol),
|
|
894
620
|
import_chalk.default.cyan(interval),
|
|
895
621
|
import_chalk.default.yellow(kline.result.list.length)
|
|
@@ -899,7 +625,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
899
625
|
}
|
|
900
626
|
return [];
|
|
901
627
|
} catch (error) {
|
|
902
|
-
|
|
628
|
+
logger.log(
|
|
903
629
|
"error",
|
|
904
630
|
"request kline: %s %s %s",
|
|
905
631
|
normalizedStart,
|
|
@@ -927,7 +653,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
927
653
|
`bybit getPositionInfo ${symbol}`
|
|
928
654
|
);
|
|
929
655
|
if (positionRes.retCode !== 0) {
|
|
930
|
-
|
|
656
|
+
logger.log(
|
|
931
657
|
getLogLevel(positionRes),
|
|
932
658
|
"position retCode: %s, %s",
|
|
933
659
|
symbol,
|
|
@@ -940,7 +666,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
940
666
|
return null;
|
|
941
667
|
}
|
|
942
668
|
const position = positions[0];
|
|
943
|
-
|
|
669
|
+
logger.log(
|
|
944
670
|
"debug",
|
|
945
671
|
"position: %s %s qty=%s price=%s",
|
|
946
672
|
position.symbol,
|
|
@@ -952,7 +678,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
952
678
|
...position
|
|
953
679
|
};
|
|
954
680
|
} catch (error) {
|
|
955
|
-
|
|
681
|
+
logger.log("error", "getPositionSnapshot failed: %s %s", symbol, error);
|
|
956
682
|
return null;
|
|
957
683
|
}
|
|
958
684
|
};
|
|
@@ -991,10 +717,10 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
991
717
|
const meta = await getSymbolMeta(marketDataClient, symbol);
|
|
992
718
|
const positionQty = qty ?? (await getPositionSnapshot(symbol))?.qty ?? 0;
|
|
993
719
|
if (!Number.isFinite(positionQty) || positionQty <= 0) {
|
|
994
|
-
|
|
720
|
+
logger.log(
|
|
995
721
|
"warn",
|
|
996
722
|
"setTakeProfits: missing position qty: %s",
|
|
997
|
-
(0,
|
|
723
|
+
(0, import_data.toJson)({ symbol, qty, positionQty, takeProfits }, true)
|
|
998
724
|
);
|
|
999
725
|
return false;
|
|
1000
726
|
}
|
|
@@ -1006,10 +732,10 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1006
732
|
meta
|
|
1007
733
|
);
|
|
1008
734
|
if (!tpSizeNum || tpSizeNum < meta.minOrderQty) {
|
|
1009
|
-
|
|
735
|
+
logger.log(
|
|
1010
736
|
"warn",
|
|
1011
737
|
"tp skipped: size too small %s",
|
|
1012
|
-
(0,
|
|
738
|
+
(0, import_data.toJson)(
|
|
1013
739
|
{ symbol, tp, tpSizeNum, minOrderQty: meta.minOrderQty },
|
|
1014
740
|
true
|
|
1015
741
|
)
|
|
@@ -1033,7 +759,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1033
759
|
positionIdx: 0
|
|
1034
760
|
});
|
|
1035
761
|
if (isTradingStopNotModified(tpRes)) {
|
|
1036
|
-
|
|
762
|
+
logger.log(
|
|
1037
763
|
"debug",
|
|
1038
764
|
"tp unchanged: %s %s price=%s rate=%s",
|
|
1039
765
|
symbol,
|
|
@@ -1042,7 +768,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1042
768
|
tp.rate
|
|
1043
769
|
);
|
|
1044
770
|
} else if (tpRes.retCode === 0) {
|
|
1045
|
-
|
|
771
|
+
logger.log(
|
|
1046
772
|
"info",
|
|
1047
773
|
"tp updated: %s %s price=%s rate=%s",
|
|
1048
774
|
symbol,
|
|
@@ -1051,14 +777,14 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1051
777
|
tp.rate
|
|
1052
778
|
);
|
|
1053
779
|
} else {
|
|
1054
|
-
|
|
780
|
+
logger.log(
|
|
1055
781
|
"error",
|
|
1056
782
|
"tp failed: %s %s price=%s rate=%s %s",
|
|
1057
783
|
symbol,
|
|
1058
784
|
direction,
|
|
1059
785
|
tpPriceNorm.priceStr,
|
|
1060
786
|
tp.rate,
|
|
1061
|
-
(0,
|
|
787
|
+
(0, import_data.toJson)(tpRes, true)
|
|
1062
788
|
);
|
|
1063
789
|
}
|
|
1064
790
|
if (!isTradingStopAccepted(tpRes)) {
|
|
@@ -1096,7 +822,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1096
822
|
positionIdx: 0
|
|
1097
823
|
});
|
|
1098
824
|
if (isTradingStopNotModified(slRes)) {
|
|
1099
|
-
|
|
825
|
+
logger.log(
|
|
1100
826
|
"debug",
|
|
1101
827
|
"sl unchanged: %s %s stopLoss=%s",
|
|
1102
828
|
symbol,
|
|
@@ -1104,7 +830,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1104
830
|
slNormalized.priceStr
|
|
1105
831
|
);
|
|
1106
832
|
} else if (slRes.retCode === 0) {
|
|
1107
|
-
|
|
833
|
+
logger.log(
|
|
1108
834
|
"info",
|
|
1109
835
|
"sl updated: %s %s stopLoss=%s",
|
|
1110
836
|
symbol,
|
|
@@ -1112,13 +838,13 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1112
838
|
slNormalized.priceStr
|
|
1113
839
|
);
|
|
1114
840
|
} else {
|
|
1115
|
-
|
|
841
|
+
logger.log(
|
|
1116
842
|
"error",
|
|
1117
843
|
"sl failed: %s %s stopLoss=%s %s",
|
|
1118
844
|
symbol,
|
|
1119
845
|
direction,
|
|
1120
846
|
slNormalized.priceStr,
|
|
1121
|
-
(0,
|
|
847
|
+
(0, import_data.toJson)(slRes, true)
|
|
1122
848
|
);
|
|
1123
849
|
}
|
|
1124
850
|
return isTradingStopAccepted(slRes);
|
|
@@ -1133,7 +859,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1133
859
|
setState: async (newState) => {
|
|
1134
860
|
state = { ...state, ...newState };
|
|
1135
861
|
},
|
|
1136
|
-
kline:
|
|
862
|
+
kline: decorateConnectorKline(runtime, {
|
|
1137
863
|
provider: "bybit",
|
|
1138
864
|
request,
|
|
1139
865
|
intervalToMinutes: intervalToMinutes3,
|
|
@@ -1150,7 +876,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1150
876
|
settleCoin: "USDT"
|
|
1151
877
|
});
|
|
1152
878
|
if (positionRes.retCode !== 0) {
|
|
1153
|
-
|
|
879
|
+
logger.log(
|
|
1154
880
|
getLogLevel(positionRes),
|
|
1155
881
|
"positions retCode: %s, %s",
|
|
1156
882
|
positionRes.retCode
|
|
@@ -1173,7 +899,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1173
899
|
settleCoin: "USDT"
|
|
1174
900
|
});
|
|
1175
901
|
if (positionRes.retCode !== 0) {
|
|
1176
|
-
|
|
902
|
+
logger.log(
|
|
1177
903
|
getLogLevel(positionRes),
|
|
1178
904
|
"positions pnl retCode: %s, %s",
|
|
1179
905
|
positionRes.retCode
|
|
@@ -1233,7 +959,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1233
959
|
...cursor ? { cursor } : {}
|
|
1234
960
|
});
|
|
1235
961
|
if (response.retCode !== 0) {
|
|
1236
|
-
|
|
962
|
+
logger.log(
|
|
1237
963
|
"error",
|
|
1238
964
|
"closedPnl retCode: %s, %s",
|
|
1239
965
|
response.retCode,
|
|
@@ -1255,7 +981,8 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1255
981
|
client,
|
|
1256
982
|
startTime,
|
|
1257
983
|
endTime,
|
|
1258
|
-
symbol
|
|
984
|
+
symbol,
|
|
985
|
+
logger
|
|
1259
986
|
});
|
|
1260
987
|
return closedPnlRows.map((item) => {
|
|
1261
988
|
const qty = Number(item.qty ?? item.closedSize ?? Number.NaN);
|
|
@@ -1330,7 +1057,7 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1330
1057
|
...cursor ? { cursor } : {}
|
|
1331
1058
|
});
|
|
1332
1059
|
if (response.retCode !== 0) {
|
|
1333
|
-
|
|
1060
|
+
logger.log(
|
|
1334
1061
|
"error",
|
|
1335
1062
|
"entryExecutions retCode: %s, %s",
|
|
1336
1063
|
response.retCode,
|
|
@@ -1352,7 +1079,8 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1352
1079
|
client,
|
|
1353
1080
|
startTime,
|
|
1354
1081
|
endTime,
|
|
1355
|
-
symbol
|
|
1082
|
+
symbol,
|
|
1083
|
+
logger
|
|
1356
1084
|
});
|
|
1357
1085
|
return executionRows.map((item) => {
|
|
1358
1086
|
const qty = Number(item.execQty ?? item.orderQty ?? Number.NaN);
|
|
@@ -1414,10 +1142,10 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1414
1142
|
if (signal) {
|
|
1415
1143
|
signal.orderFailureReason = failureReason;
|
|
1416
1144
|
}
|
|
1417
|
-
|
|
1145
|
+
logger.log(
|
|
1418
1146
|
"warn",
|
|
1419
1147
|
"placeOrder: rejected position increase: %s",
|
|
1420
|
-
(0,
|
|
1148
|
+
(0, import_data.toJson)(
|
|
1421
1149
|
{
|
|
1422
1150
|
symbol,
|
|
1423
1151
|
direction,
|
|
@@ -1439,10 +1167,10 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1439
1167
|
signal.orderValue = normalizedQty.qtyNum * price;
|
|
1440
1168
|
signal.orderFailureReason = "QTY_BELOW_MIN_ORDER";
|
|
1441
1169
|
}
|
|
1442
|
-
|
|
1170
|
+
logger.log(
|
|
1443
1171
|
"warn",
|
|
1444
1172
|
"placeOrder: rejected qty below minOrderQty: %s",
|
|
1445
|
-
(0,
|
|
1173
|
+
(0, import_data.toJson)(
|
|
1446
1174
|
{
|
|
1447
1175
|
symbol,
|
|
1448
1176
|
qty,
|
|
@@ -1461,10 +1189,10 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1461
1189
|
signal.orderValue = orderQty * price;
|
|
1462
1190
|
}
|
|
1463
1191
|
const entryNormalized = isLimit ? normalizePrice(price, "ENTRY", meta) : void 0;
|
|
1464
|
-
|
|
1192
|
+
logger.log(
|
|
1465
1193
|
"info",
|
|
1466
1194
|
"placeOrder: %s",
|
|
1467
|
-
(0,
|
|
1195
|
+
(0, import_data.toJson)(
|
|
1468
1196
|
{
|
|
1469
1197
|
symbol,
|
|
1470
1198
|
price,
|
|
@@ -1494,10 +1222,10 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1494
1222
|
orderFilter: "Order",
|
|
1495
1223
|
orderLinkId: typeof orderId === "string" && orderId.trim() ? orderId : void 0
|
|
1496
1224
|
});
|
|
1497
|
-
|
|
1225
|
+
logger.log(
|
|
1498
1226
|
getLogLevel(orderRes),
|
|
1499
1227
|
"placeOrder:response: %s",
|
|
1500
|
-
(0,
|
|
1228
|
+
(0, import_data.toJson)(orderRes, true)
|
|
1501
1229
|
);
|
|
1502
1230
|
if (orderRes.retCode !== 0) {
|
|
1503
1231
|
if (signal) {
|
|
@@ -1527,12 +1255,12 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1527
1255
|
qty: "0",
|
|
1528
1256
|
reduceOnly: true
|
|
1529
1257
|
});
|
|
1530
|
-
|
|
1258
|
+
logger.log(
|
|
1531
1259
|
getLogLevel(closeRes),
|
|
1532
1260
|
"closePosition: %s, %s, %s",
|
|
1533
1261
|
symbol,
|
|
1534
1262
|
direction,
|
|
1535
|
-
(0,
|
|
1263
|
+
(0, import_data.toJson)(closeRes, true)
|
|
1536
1264
|
);
|
|
1537
1265
|
if (closeRes.retCode !== 0) {
|
|
1538
1266
|
return false;
|
|
@@ -1638,7 +1366,6 @@ var ByBitConnectorCreator = async (config) => {
|
|
|
1638
1366
|
};
|
|
1639
1367
|
|
|
1640
1368
|
// src/Binance/index.ts
|
|
1641
|
-
var import_http = require("@tradejs/infra/http");
|
|
1642
1369
|
var import_types2 = require("@tradejs/types");
|
|
1643
1370
|
|
|
1644
1371
|
// src/shared/binancePublicApi.ts
|
|
@@ -1646,6 +1373,7 @@ var DEFAULT_BINANCE_PUBLIC_API_URL = "https://data-api.binance.vision";
|
|
|
1646
1373
|
var getBinancePublicApiUrl = () => process.env.BINANCE_BASE_URL?.trim() || DEFAULT_BINANCE_PUBLIC_API_URL;
|
|
1647
1374
|
|
|
1648
1375
|
// src/Binance/index.ts
|
|
1376
|
+
var import_http = require("@tradejs/core/http");
|
|
1649
1377
|
var INTERVAL_MAP = {
|
|
1650
1378
|
"1": "1m",
|
|
1651
1379
|
"3": "3m",
|
|
@@ -1692,7 +1420,7 @@ var capabilities = {
|
|
|
1692
1420
|
supportedUniverses: ["crypto"],
|
|
1693
1421
|
defaultUniverse: "crypto"
|
|
1694
1422
|
};
|
|
1695
|
-
var BinanceConnectorCreator = async (config) => {
|
|
1423
|
+
var BinanceConnectorCreator = async (config, runtime) => {
|
|
1696
1424
|
let state = {};
|
|
1697
1425
|
const universe = (0, import_types2.resolveConnectorUniverse)(capabilities, config.universe);
|
|
1698
1426
|
const requestKline = async ({
|
|
@@ -1820,7 +1548,7 @@ var BinanceConnectorCreator = async (config) => {
|
|
|
1820
1548
|
setState: async (newState) => {
|
|
1821
1549
|
state = { ...state, ...newState };
|
|
1822
1550
|
},
|
|
1823
|
-
kline:
|
|
1551
|
+
kline: decorateConnectorKline(runtime, {
|
|
1824
1552
|
provider: "binance",
|
|
1825
1553
|
request: requestKline,
|
|
1826
1554
|
intervalToMinutes
|
|
@@ -1915,8 +1643,8 @@ var BinanceConnectorCreator = async (config) => {
|
|
|
1915
1643
|
};
|
|
1916
1644
|
|
|
1917
1645
|
// src/Coinbase/index.ts
|
|
1918
|
-
var import_http2 = require("@tradejs/infra/http");
|
|
1919
1646
|
var import_types3 = require("@tradejs/types");
|
|
1647
|
+
var import_http2 = require("@tradejs/core/http");
|
|
1920
1648
|
var INTERVAL_MS2 = {
|
|
1921
1649
|
"1": 6e4,
|
|
1922
1650
|
"3": 18e4,
|
|
@@ -1983,7 +1711,7 @@ var capabilities2 = {
|
|
|
1983
1711
|
supportedUniverses: ["crypto"],
|
|
1984
1712
|
defaultUniverse: "crypto"
|
|
1985
1713
|
};
|
|
1986
|
-
var CoinbaseConnectorCreator = async (config) => {
|
|
1714
|
+
var CoinbaseConnectorCreator = async (config, runtime) => {
|
|
1987
1715
|
let state = {};
|
|
1988
1716
|
const universe = (0, import_types3.resolveConnectorUniverse)(capabilities2, config.universe);
|
|
1989
1717
|
const requestKline = async ({
|
|
@@ -2111,7 +1839,7 @@ var CoinbaseConnectorCreator = async (config) => {
|
|
|
2111
1839
|
setState: async (newState) => {
|
|
2112
1840
|
state = { ...state, ...newState };
|
|
2113
1841
|
},
|
|
2114
|
-
kline:
|
|
1842
|
+
kline: decorateConnectorKline(runtime, {
|
|
2115
1843
|
provider: "coinbase",
|
|
2116
1844
|
request: requestKline,
|
|
2117
1845
|
intervalToMinutes: intervalToMinutes2
|
|
@@ -2131,7 +1859,7 @@ var CoinbaseConnectorCreator = async (config) => {
|
|
|
2131
1859
|
};
|
|
2132
1860
|
|
|
2133
1861
|
// src/marketData/spotKlineProviders.ts
|
|
2134
|
-
var import_http3 = require("@tradejs/
|
|
1862
|
+
var import_http3 = require("@tradejs/core/http");
|
|
2135
1863
|
var toIntervalToken = (interval) => interval === "1h" ? "1h" : "15m";
|
|
2136
1864
|
var mapBinanceKline = (payload) => payload.map((item) => {
|
|
2137
1865
|
if (!Array.isArray(item)) return null;
|
|
@@ -2235,9 +1963,7 @@ var spotKlineProviders = {
|
|
|
2235
1963
|
|
|
2236
1964
|
// src/ByBit/klineStream.ts
|
|
2237
1965
|
var import_bybit_api2 = require("bybit-api");
|
|
2238
|
-
var
|
|
2239
|
-
var import_logger4 = require("@tradejs/infra/logger");
|
|
2240
|
-
var import_tradingAccounts2 = require("@tradejs/infra/tradingAccounts");
|
|
1966
|
+
var import_time3 = require("@tradejs/core/time");
|
|
2241
1967
|
var CATEGORY = "linear";
|
|
2242
1968
|
var SUBSCRIPTION_BATCH_SIZE = 100;
|
|
2243
1969
|
var KLINE_TOPIC_PATTERN = /^kline\.([^.]+)\.(.+)$/;
|
|
@@ -2277,7 +2003,7 @@ var parseBybitKlineEvent = (value, receivedAt = Date.now()) => {
|
|
|
2277
2003
|
symbol: symbol.toUpperCase(),
|
|
2278
2004
|
interval,
|
|
2279
2005
|
candle: {
|
|
2280
|
-
dt: (0,
|
|
2006
|
+
dt: (0, import_time3.formatUnix)(timestamp),
|
|
2281
2007
|
timestamp,
|
|
2282
2008
|
open,
|
|
2283
2009
|
high,
|
|
@@ -2294,22 +2020,23 @@ var parseBybitKlineEvent = (value, receivedAt = Date.now()) => {
|
|
|
2294
2020
|
};
|
|
2295
2021
|
var createBybitKlineStreamWithClient = ({
|
|
2296
2022
|
client,
|
|
2297
|
-
onEvent
|
|
2023
|
+
onEvent,
|
|
2024
|
+
logger = getConnectorLogger()
|
|
2298
2025
|
}) => {
|
|
2299
2026
|
let topics = /* @__PURE__ */ new Set();
|
|
2300
2027
|
let closed = false;
|
|
2301
2028
|
client.on("update", (value) => {
|
|
2302
2029
|
for (const event of parseBybitKlineEvent(value)) {
|
|
2303
2030
|
void Promise.resolve(onEvent(event)).catch((error) => {
|
|
2304
|
-
|
|
2031
|
+
logger.error("Bybit kline stream handler failed: %s", String(error));
|
|
2305
2032
|
});
|
|
2306
2033
|
}
|
|
2307
2034
|
});
|
|
2308
2035
|
client.on("reconnected", ({ wsKey }) => {
|
|
2309
|
-
|
|
2036
|
+
logger.info("Bybit kline stream reconnected: %s", wsKey);
|
|
2310
2037
|
});
|
|
2311
2038
|
client.on("exception", (error) => {
|
|
2312
|
-
|
|
2039
|
+
logger.error("Bybit kline stream exception: %s", String(error));
|
|
2313
2040
|
});
|
|
2314
2041
|
return {
|
|
2315
2042
|
setSubscriptions: (symbols, interval) => {
|
|
@@ -2323,16 +2050,16 @@ var createBybitKlineStreamWithClient = ({
|
|
|
2323
2050
|
const removed = [...topics].filter((topic) => !nextTopics.has(topic));
|
|
2324
2051
|
for (const batch of chunk(removed, SUBSCRIPTION_BATCH_SIZE)) {
|
|
2325
2052
|
void Promise.all(client.unsubscribeV5(batch, CATEGORY)).catch(
|
|
2326
|
-
(error) =>
|
|
2053
|
+
(error) => logger.error("Bybit kline unsubscribe failed: %s", String(error))
|
|
2327
2054
|
);
|
|
2328
2055
|
}
|
|
2329
2056
|
for (const batch of chunk(added, SUBSCRIPTION_BATCH_SIZE)) {
|
|
2330
2057
|
void Promise.all(client.subscribeV5(batch, CATEGORY)).catch(
|
|
2331
|
-
(error) =>
|
|
2058
|
+
(error) => logger.error("Bybit kline subscribe failed: %s", String(error))
|
|
2332
2059
|
);
|
|
2333
2060
|
}
|
|
2334
2061
|
topics = nextTopics;
|
|
2335
|
-
|
|
2062
|
+
logger.info(
|
|
2336
2063
|
"Bybit kline stream subscriptions: topics=%s added=%s removed=%s",
|
|
2337
2064
|
topics.size,
|
|
2338
2065
|
added.length,
|
|
@@ -2353,9 +2080,11 @@ var createBybitKlineStreamWithClient = ({
|
|
|
2353
2080
|
};
|
|
2354
2081
|
var createBybitKlineStream = async ({
|
|
2355
2082
|
config,
|
|
2356
|
-
onEvent
|
|
2083
|
+
onEvent,
|
|
2084
|
+
runtime
|
|
2357
2085
|
}) => {
|
|
2358
|
-
const
|
|
2086
|
+
const resolveTradingAccount = getConnectorAccountResolver(runtime);
|
|
2087
|
+
const account = config.accountId ? await resolveTradingAccount({
|
|
2359
2088
|
userName: config.userName,
|
|
2360
2089
|
accountId: config.accountId,
|
|
2361
2090
|
provider: "bybit",
|
|
@@ -2368,7 +2097,11 @@ var createBybitKlineStream = async ({
|
|
|
2368
2097
|
Number(process.env.BYBIT_WS_RECONNECT_TIMEOUT_MS ?? 1e3)
|
|
2369
2098
|
)
|
|
2370
2099
|
});
|
|
2371
|
-
return createBybitKlineStreamWithClient({
|
|
2100
|
+
return createBybitKlineStreamWithClient({
|
|
2101
|
+
client,
|
|
2102
|
+
onEvent,
|
|
2103
|
+
logger: getConnectorLogger(runtime)
|
|
2104
|
+
});
|
|
2372
2105
|
};
|
|
2373
2106
|
|
|
2374
2107
|
// src/marketData/providers/binanceCoinbaseSpread.ts
|
|
@@ -2427,7 +2160,7 @@ var binanceCoinbaseSpreadProvider = {
|
|
|
2427
2160
|
};
|
|
2428
2161
|
|
|
2429
2162
|
// src/marketData/providers/coinalyze.ts
|
|
2430
|
-
var
|
|
2163
|
+
var import_async2 = require("@tradejs/core/async");
|
|
2431
2164
|
var import_indicators2 = require("@tradejs/core/indicators");
|
|
2432
2165
|
var coinalyzeIntervalMap = {
|
|
2433
2166
|
"15m": "15min",
|
|
@@ -2497,7 +2230,7 @@ var fetchCoinalyzeSeries = async (params) => {
|
|
|
2497
2230
|
lastRequestTs + coinalyzeMinRequestDelayMs - now
|
|
2498
2231
|
);
|
|
2499
2232
|
if (waitMs > 0) {
|
|
2500
|
-
await (0,
|
|
2233
|
+
await (0, import_async2.delay)(waitMs);
|
|
2501
2234
|
}
|
|
2502
2235
|
lastRequestTs = Date.now();
|
|
2503
2236
|
const response = await fetch(url.toString(), { headers });
|
|
@@ -2511,7 +2244,7 @@ var fetchCoinalyzeSeries = async (params) => {
|
|
|
2511
2244
|
const transient = response.status === 429 || response.status >= 500;
|
|
2512
2245
|
if (attempt < coinalyzeMaxRetries && transient) {
|
|
2513
2246
|
const backoffMs = Math.min(1e4, 750 * 2 ** attempt);
|
|
2514
|
-
await (0,
|
|
2247
|
+
await (0, import_async2.delay)(retryAfterMs ?? backoffMs);
|
|
2515
2248
|
continue;
|
|
2516
2249
|
}
|
|
2517
2250
|
throw new Error(`Coinalyze ${endpoint} ${response.status}: ${text}`);
|