@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/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 import_async2 = require("@tradejs/core/async");
55
- var import_constants2 = require("@tradejs/core/constants");
56
- var import_data2 = require("@tradejs/core/data");
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 import_time3 = require("@tradejs/core/time");
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
- var import_logger = require("@tradejs/infra/logger");
65
- var import_tradingAccounts = require("@tradejs/infra/tradingAccounts");
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 getClient = async (config, access = "private") => {
68
- const account = access === "public" && !config.accountId ? null : await (0, import_tradingAccounts.resolveTradingAccount)({
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
- import_logger.logger.log(
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
- import_logger.logger.log("error", "connection config not found: %s", config.userName);
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 import_time2 = require("@tradejs/core/time");
131
+ var import_time = require("@tradejs/core/time");
408
132
  var BYBIT_CATEGORY = "linear";
409
133
  var parseKlineItem = (item) => ({
410
- dt: (0, import_time2.formatUnix)(parseInt(item[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
- import_logger3.logger.log(
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
- import_logger3.logger.log("debug", "funding transaction log failed: %s", error);
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, import_time3.getTimestamp)(import_constants2.PRELOAD_FALLBACK_DAYS),
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
- import_logger3.logger.log(
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, import_async2.delay)(waitMs);
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
615
+ logger.log(
890
616
  "info",
891
617
  "%s %s %s %s",
892
- import_chalk.default.yellow((0, import_time3.formatUnix)(normalizedEnd)),
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log("error", "getPositionSnapshot failed: %s %s", symbol, error);
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
- import_logger3.logger.log(
720
+ logger.log(
995
721
  "warn",
996
722
  "setTakeProfits: missing position qty: %s",
997
- (0, import_data2.toJson)({ symbol, qty, positionQty, takeProfits }, true)
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
- import_logger3.logger.log(
735
+ logger.log(
1010
736
  "warn",
1011
737
  "tp skipped: size too small %s",
1012
- (0, import_data2.toJson)(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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, import_data2.toJson)(tpRes, true)
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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, import_data2.toJson)(slRes, true)
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: createTimescaleCachedKline({
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
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
- import_logger3.logger.log(
1145
+ logger.log(
1418
1146
  "warn",
1419
1147
  "placeOrder: rejected position increase: %s",
1420
- (0, import_data2.toJson)(
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
- import_logger3.logger.log(
1170
+ logger.log(
1443
1171
  "warn",
1444
1172
  "placeOrder: rejected qty below minOrderQty: %s",
1445
- (0, import_data2.toJson)(
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
- import_logger3.logger.log(
1192
+ logger.log(
1465
1193
  "info",
1466
1194
  "placeOrder: %s",
1467
- (0, import_data2.toJson)(
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
- import_logger3.logger.log(
1225
+ logger.log(
1498
1226
  getLogLevel(orderRes),
1499
1227
  "placeOrder:response: %s",
1500
- (0, import_data2.toJson)(orderRes, true)
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
- import_logger3.logger.log(
1258
+ logger.log(
1531
1259
  getLogLevel(closeRes),
1532
1260
  "closePosition: %s, %s, %s",
1533
1261
  symbol,
1534
1262
  direction,
1535
- (0, import_data2.toJson)(closeRes, true)
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: createTimescaleCachedKline({
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: createTimescaleCachedKline({
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/infra/http");
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 import_time4 = require("@tradejs/core/time");
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, import_time4.formatUnix)(timestamp),
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
- import_logger4.logger.error("Bybit kline stream handler failed: %s", String(error));
2031
+ logger.error("Bybit kline stream handler failed: %s", String(error));
2305
2032
  });
2306
2033
  }
2307
2034
  });
2308
2035
  client.on("reconnected", ({ wsKey }) => {
2309
- import_logger4.logger.info("Bybit kline stream reconnected: %s", wsKey);
2036
+ logger.info("Bybit kline stream reconnected: %s", wsKey);
2310
2037
  });
2311
2038
  client.on("exception", (error) => {
2312
- import_logger4.logger.error("Bybit kline stream exception: %s", String(error));
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) => import_logger4.logger.error("Bybit kline unsubscribe failed: %s", String(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) => import_logger4.logger.error("Bybit kline subscribe failed: %s", String(error))
2058
+ (error) => logger.error("Bybit kline subscribe failed: %s", String(error))
2332
2059
  );
2333
2060
  }
2334
2061
  topics = nextTopics;
2335
- import_logger4.logger.info(
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 account = config.accountId ? await (0, import_tradingAccounts2.resolveTradingAccount)({
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({ client, onEvent });
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 import_async3 = require("@tradejs/core/async");
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, import_async3.delay)(waitMs);
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, import_async3.delay)(retryAfterMs ?? backoffMs);
2247
+ await (0, import_async2.delay)(retryAfterMs ?? backoffMs);
2515
2248
  continue;
2516
2249
  }
2517
2250
  throw new Error(`Coinalyze ${endpoint} ${response.status}: ${text}`);