@tradejs/connectors 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -51,21 +51,34 @@ 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 getClient = async (config, access = "private", runtime) => {
79
+ const logger = getConnectorLogger(runtime);
80
+ const resolveTradingAccount = getConnectorAccountResolver(runtime);
81
+ const account = access === "public" && !config.accountId ? null : await resolveTradingAccount({
69
82
  userName: config.userName,
70
83
  accountId: config.accountId,
71
84
  provider: "bybit",
@@ -80,14 +93,14 @@ var getClient = async (config, access = "private") => {
80
93
  }
81
94
  if (!account?.apiKey || !account.apiSecret) {
82
95
  if (config.accountId) {
83
- import_logger.logger.log(
96
+ logger.log(
84
97
  "error",
85
98
  "Bybit trading account config not found: user=%s account=%s",
86
99
  config.userName,
87
100
  config.accountId
88
101
  );
89
102
  } else {
90
- import_logger.logger.log("error", "connection config not found: %s", config.userName);
103
+ logger.log("error", "connection config not found: %s", config.userName);
91
104
  }
92
105
  return null;
93
106
  }
@@ -104,310 +117,11 @@ var getClient = async (config, access = "private") => {
104
117
  return client;
105
118
  };
106
119
 
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
120
  // src/ByBit/utils.ts
407
- var import_time2 = require("@tradejs/core/time");
121
+ var import_time = require("@tradejs/core/time");
408
122
  var BYBIT_CATEGORY = "linear";
409
123
  var parseKlineItem = (item) => ({
410
- dt: (0, import_time2.formatUnix)(parseInt(item[0])),
124
+ dt: (0, import_time.formatUnix)(parseInt(item[0])),
411
125
  timestamp: parseInt(item[0]),
412
126
  open: parseFloat(item[1]),
413
127
  high: parseFloat(item[2]),
@@ -598,7 +312,8 @@ var loadFundingFeeRows = async ({
598
312
  client,
599
313
  startTime,
600
314
  endTime,
601
- symbol
315
+ symbol,
316
+ logger
602
317
  }) => {
603
318
  if (typeof client.getTransactionLog !== "function") {
604
319
  return [];
@@ -617,7 +332,7 @@ var loadFundingFeeRows = async ({
617
332
  ...cursor ? { cursor } : {}
618
333
  });
619
334
  if (response?.retCode !== 0) {
620
- import_logger3.logger.log(
335
+ logger.log(
621
336
  "debug",
622
337
  "funding transaction log retCode: %s, %s",
623
338
  response?.retCode,
@@ -649,7 +364,7 @@ var loadFundingFeeRows = async ({
649
364
  }
650
365
  return rows;
651
366
  } catch (error) {
652
- import_logger3.logger.log("debug", "funding transaction log failed: %s", error);
367
+ logger.log("debug", "funding transaction log failed: %s", error);
653
368
  return [];
654
369
  }
655
370
  };
@@ -696,7 +411,8 @@ var resolveKlineRetryDelayMs = (res, attempt) => {
696
411
  );
697
412
  return backoffMs + jitterMs;
698
413
  };
699
- var ByBitConnectorCreator = async (config) => {
414
+ var ByBitConnectorCreator = async (config, runtime) => {
415
+ const logger = getConnectorLogger(runtime);
700
416
  let state = {};
701
417
  const universe = (0, import_types.resolveConnectorUniverse)(
702
418
  BYBIT_CAPABILITIES,
@@ -707,11 +423,11 @@ var ByBitConnectorCreator = async (config) => {
707
423
  const positionSnapshotCache = /* @__PURE__ */ new Map();
708
424
  const inflightPositionSnapshots = /* @__PURE__ */ new Map();
709
425
  const getPublicClient = async () => {
710
- publicClientPromise ??= getClient(config, "public");
426
+ publicClientPromise ??= getClient(config, "public", runtime);
711
427
  return publicClientPromise;
712
428
  };
713
429
  const getPrivateClient = async () => {
714
- privateClientPromise ??= getClient(config, "private");
430
+ privateClientPromise ??= getClient(config, "private", runtime);
715
431
  return privateClientPromise;
716
432
  };
717
433
  const instrumentCache = /* @__PURE__ */ new Map();
@@ -839,7 +555,7 @@ var ByBitConnectorCreator = async (config) => {
839
555
  silent
840
556
  }) => {
841
557
  const normalizedStart = (0, import_math.round)(
842
- start || (0, import_time3.getTimestamp)(import_constants2.PRELOAD_FALLBACK_DAYS),
558
+ start || (0, import_time2.getTimestamp)(import_constants.PRELOAD_FALLBACK_DAYS),
843
559
  0
844
560
  );
845
561
  const normalizedEnd = (0, import_math.round)(end || Date.now());
@@ -861,7 +577,7 @@ var ByBitConnectorCreator = async (config) => {
861
577
  if (isKlineRateLimited(kline)) {
862
578
  if (attempt < KLINE_RATE_LIMIT_MAX_ATTEMPTS) {
863
579
  const waitMs = resolveKlineRetryDelayMs(kline, attempt);
864
- import_logger3.logger.log(
580
+ logger.log(
865
581
  "warn",
866
582
  "kline rate limited for %s %s: attempt=%s/%s waitMs=%s",
867
583
  symbol,
@@ -870,13 +586,13 @@ var ByBitConnectorCreator = async (config) => {
870
586
  KLINE_RATE_LIMIT_MAX_ATTEMPTS,
871
587
  waitMs
872
588
  );
873
- await (0, import_async2.delay)(waitMs);
589
+ await (0, import_async.delay)(waitMs);
874
590
  continue;
875
591
  }
876
592
  }
877
593
  if (!kline?.result?.list) {
878
594
  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(
595
+ logger.log(
880
596
  "error",
881
597
  "empty kline.list for %s %s%s",
882
598
  symbol,
@@ -886,10 +602,10 @@ var ByBitConnectorCreator = async (config) => {
886
602
  return [];
887
603
  }
888
604
  if (!silent && (process.stdout.isTTY || process.env.TRADEJS_LOG_KLINE_REQUESTS === "1")) {
889
- import_logger3.logger.log(
605
+ logger.log(
890
606
  "info",
891
607
  "%s %s %s %s",
892
- import_chalk.default.yellow((0, import_time3.formatUnix)(normalizedEnd)),
608
+ import_chalk.default.yellow((0, import_time2.formatUnix)(normalizedEnd)),
893
609
  import_chalk.default.cyan(symbol),
894
610
  import_chalk.default.cyan(interval),
895
611
  import_chalk.default.yellow(kline.result.list.length)
@@ -899,7 +615,7 @@ var ByBitConnectorCreator = async (config) => {
899
615
  }
900
616
  return [];
901
617
  } catch (error) {
902
- import_logger3.logger.log(
618
+ logger.log(
903
619
  "error",
904
620
  "request kline: %s %s %s",
905
621
  normalizedStart,
@@ -927,7 +643,7 @@ var ByBitConnectorCreator = async (config) => {
927
643
  `bybit getPositionInfo ${symbol}`
928
644
  );
929
645
  if (positionRes.retCode !== 0) {
930
- import_logger3.logger.log(
646
+ logger.log(
931
647
  getLogLevel(positionRes),
932
648
  "position retCode: %s, %s",
933
649
  symbol,
@@ -940,7 +656,7 @@ var ByBitConnectorCreator = async (config) => {
940
656
  return null;
941
657
  }
942
658
  const position = positions[0];
943
- import_logger3.logger.log(
659
+ logger.log(
944
660
  "debug",
945
661
  "position: %s %s qty=%s price=%s",
946
662
  position.symbol,
@@ -952,7 +668,7 @@ var ByBitConnectorCreator = async (config) => {
952
668
  ...position
953
669
  };
954
670
  } catch (error) {
955
- import_logger3.logger.log("error", "getPositionSnapshot failed: %s %s", symbol, error);
671
+ logger.log("error", "getPositionSnapshot failed: %s %s", symbol, error);
956
672
  return null;
957
673
  }
958
674
  };
@@ -991,10 +707,10 @@ var ByBitConnectorCreator = async (config) => {
991
707
  const meta = await getSymbolMeta(marketDataClient, symbol);
992
708
  const positionQty = qty ?? (await getPositionSnapshot(symbol))?.qty ?? 0;
993
709
  if (!Number.isFinite(positionQty) || positionQty <= 0) {
994
- import_logger3.logger.log(
710
+ logger.log(
995
711
  "warn",
996
712
  "setTakeProfits: missing position qty: %s",
997
- (0, import_data2.toJson)({ symbol, qty, positionQty, takeProfits }, true)
713
+ (0, import_data.toJson)({ symbol, qty, positionQty, takeProfits }, true)
998
714
  );
999
715
  return false;
1000
716
  }
@@ -1006,10 +722,10 @@ var ByBitConnectorCreator = async (config) => {
1006
722
  meta
1007
723
  );
1008
724
  if (!tpSizeNum || tpSizeNum < meta.minOrderQty) {
1009
- import_logger3.logger.log(
725
+ logger.log(
1010
726
  "warn",
1011
727
  "tp skipped: size too small %s",
1012
- (0, import_data2.toJson)(
728
+ (0, import_data.toJson)(
1013
729
  { symbol, tp, tpSizeNum, minOrderQty: meta.minOrderQty },
1014
730
  true
1015
731
  )
@@ -1033,7 +749,7 @@ var ByBitConnectorCreator = async (config) => {
1033
749
  positionIdx: 0
1034
750
  });
1035
751
  if (isTradingStopNotModified(tpRes)) {
1036
- import_logger3.logger.log(
752
+ logger.log(
1037
753
  "debug",
1038
754
  "tp unchanged: %s %s price=%s rate=%s",
1039
755
  symbol,
@@ -1042,7 +758,7 @@ var ByBitConnectorCreator = async (config) => {
1042
758
  tp.rate
1043
759
  );
1044
760
  } else if (tpRes.retCode === 0) {
1045
- import_logger3.logger.log(
761
+ logger.log(
1046
762
  "info",
1047
763
  "tp updated: %s %s price=%s rate=%s",
1048
764
  symbol,
@@ -1051,14 +767,14 @@ var ByBitConnectorCreator = async (config) => {
1051
767
  tp.rate
1052
768
  );
1053
769
  } else {
1054
- import_logger3.logger.log(
770
+ logger.log(
1055
771
  "error",
1056
772
  "tp failed: %s %s price=%s rate=%s %s",
1057
773
  symbol,
1058
774
  direction,
1059
775
  tpPriceNorm.priceStr,
1060
776
  tp.rate,
1061
- (0, import_data2.toJson)(tpRes, true)
777
+ (0, import_data.toJson)(tpRes, true)
1062
778
  );
1063
779
  }
1064
780
  if (!isTradingStopAccepted(tpRes)) {
@@ -1096,7 +812,7 @@ var ByBitConnectorCreator = async (config) => {
1096
812
  positionIdx: 0
1097
813
  });
1098
814
  if (isTradingStopNotModified(slRes)) {
1099
- import_logger3.logger.log(
815
+ logger.log(
1100
816
  "debug",
1101
817
  "sl unchanged: %s %s stopLoss=%s",
1102
818
  symbol,
@@ -1104,7 +820,7 @@ var ByBitConnectorCreator = async (config) => {
1104
820
  slNormalized.priceStr
1105
821
  );
1106
822
  } else if (slRes.retCode === 0) {
1107
- import_logger3.logger.log(
823
+ logger.log(
1108
824
  "info",
1109
825
  "sl updated: %s %s stopLoss=%s",
1110
826
  symbol,
@@ -1112,13 +828,13 @@ var ByBitConnectorCreator = async (config) => {
1112
828
  slNormalized.priceStr
1113
829
  );
1114
830
  } else {
1115
- import_logger3.logger.log(
831
+ logger.log(
1116
832
  "error",
1117
833
  "sl failed: %s %s stopLoss=%s %s",
1118
834
  symbol,
1119
835
  direction,
1120
836
  slNormalized.priceStr,
1121
- (0, import_data2.toJson)(slRes, true)
837
+ (0, import_data.toJson)(slRes, true)
1122
838
  );
1123
839
  }
1124
840
  return isTradingStopAccepted(slRes);
@@ -1133,7 +849,7 @@ var ByBitConnectorCreator = async (config) => {
1133
849
  setState: async (newState) => {
1134
850
  state = { ...state, ...newState };
1135
851
  },
1136
- kline: createTimescaleCachedKline({
852
+ kline: decorateConnectorKline(runtime, {
1137
853
  provider: "bybit",
1138
854
  request,
1139
855
  intervalToMinutes: intervalToMinutes3,
@@ -1150,7 +866,7 @@ var ByBitConnectorCreator = async (config) => {
1150
866
  settleCoin: "USDT"
1151
867
  });
1152
868
  if (positionRes.retCode !== 0) {
1153
- import_logger3.logger.log(
869
+ logger.log(
1154
870
  getLogLevel(positionRes),
1155
871
  "positions retCode: %s, %s",
1156
872
  positionRes.retCode
@@ -1173,7 +889,7 @@ var ByBitConnectorCreator = async (config) => {
1173
889
  settleCoin: "USDT"
1174
890
  });
1175
891
  if (positionRes.retCode !== 0) {
1176
- import_logger3.logger.log(
892
+ logger.log(
1177
893
  getLogLevel(positionRes),
1178
894
  "positions pnl retCode: %s, %s",
1179
895
  positionRes.retCode
@@ -1233,7 +949,7 @@ var ByBitConnectorCreator = async (config) => {
1233
949
  ...cursor ? { cursor } : {}
1234
950
  });
1235
951
  if (response.retCode !== 0) {
1236
- import_logger3.logger.log(
952
+ logger.log(
1237
953
  "error",
1238
954
  "closedPnl retCode: %s, %s",
1239
955
  response.retCode,
@@ -1255,7 +971,8 @@ var ByBitConnectorCreator = async (config) => {
1255
971
  client,
1256
972
  startTime,
1257
973
  endTime,
1258
- symbol
974
+ symbol,
975
+ logger
1259
976
  });
1260
977
  return closedPnlRows.map((item) => {
1261
978
  const qty = Number(item.qty ?? item.closedSize ?? Number.NaN);
@@ -1330,7 +1047,7 @@ var ByBitConnectorCreator = async (config) => {
1330
1047
  ...cursor ? { cursor } : {}
1331
1048
  });
1332
1049
  if (response.retCode !== 0) {
1333
- import_logger3.logger.log(
1050
+ logger.log(
1334
1051
  "error",
1335
1052
  "entryExecutions retCode: %s, %s",
1336
1053
  response.retCode,
@@ -1352,7 +1069,8 @@ var ByBitConnectorCreator = async (config) => {
1352
1069
  client,
1353
1070
  startTime,
1354
1071
  endTime,
1355
- symbol
1072
+ symbol,
1073
+ logger
1356
1074
  });
1357
1075
  return executionRows.map((item) => {
1358
1076
  const qty = Number(item.execQty ?? item.orderQty ?? Number.NaN);
@@ -1414,10 +1132,10 @@ var ByBitConnectorCreator = async (config) => {
1414
1132
  if (signal) {
1415
1133
  signal.orderFailureReason = failureReason;
1416
1134
  }
1417
- import_logger3.logger.log(
1135
+ logger.log(
1418
1136
  "warn",
1419
1137
  "placeOrder: rejected position increase: %s",
1420
- (0, import_data2.toJson)(
1138
+ (0, import_data.toJson)(
1421
1139
  {
1422
1140
  symbol,
1423
1141
  direction,
@@ -1439,10 +1157,10 @@ var ByBitConnectorCreator = async (config) => {
1439
1157
  signal.orderValue = normalizedQty.qtyNum * price;
1440
1158
  signal.orderFailureReason = "QTY_BELOW_MIN_ORDER";
1441
1159
  }
1442
- import_logger3.logger.log(
1160
+ logger.log(
1443
1161
  "warn",
1444
1162
  "placeOrder: rejected qty below minOrderQty: %s",
1445
- (0, import_data2.toJson)(
1163
+ (0, import_data.toJson)(
1446
1164
  {
1447
1165
  symbol,
1448
1166
  qty,
@@ -1461,10 +1179,10 @@ var ByBitConnectorCreator = async (config) => {
1461
1179
  signal.orderValue = orderQty * price;
1462
1180
  }
1463
1181
  const entryNormalized = isLimit ? normalizePrice(price, "ENTRY", meta) : void 0;
1464
- import_logger3.logger.log(
1182
+ logger.log(
1465
1183
  "info",
1466
1184
  "placeOrder: %s",
1467
- (0, import_data2.toJson)(
1185
+ (0, import_data.toJson)(
1468
1186
  {
1469
1187
  symbol,
1470
1188
  price,
@@ -1494,10 +1212,10 @@ var ByBitConnectorCreator = async (config) => {
1494
1212
  orderFilter: "Order",
1495
1213
  orderLinkId: typeof orderId === "string" && orderId.trim() ? orderId : void 0
1496
1214
  });
1497
- import_logger3.logger.log(
1215
+ logger.log(
1498
1216
  getLogLevel(orderRes),
1499
1217
  "placeOrder:response: %s",
1500
- (0, import_data2.toJson)(orderRes, true)
1218
+ (0, import_data.toJson)(orderRes, true)
1501
1219
  );
1502
1220
  if (orderRes.retCode !== 0) {
1503
1221
  if (signal) {
@@ -1527,12 +1245,12 @@ var ByBitConnectorCreator = async (config) => {
1527
1245
  qty: "0",
1528
1246
  reduceOnly: true
1529
1247
  });
1530
- import_logger3.logger.log(
1248
+ logger.log(
1531
1249
  getLogLevel(closeRes),
1532
1250
  "closePosition: %s, %s, %s",
1533
1251
  symbol,
1534
1252
  direction,
1535
- (0, import_data2.toJson)(closeRes, true)
1253
+ (0, import_data.toJson)(closeRes, true)
1536
1254
  );
1537
1255
  if (closeRes.retCode !== 0) {
1538
1256
  return false;
@@ -1638,7 +1356,6 @@ var ByBitConnectorCreator = async (config) => {
1638
1356
  };
1639
1357
 
1640
1358
  // src/Binance/index.ts
1641
- var import_http = require("@tradejs/infra/http");
1642
1359
  var import_types2 = require("@tradejs/types");
1643
1360
 
1644
1361
  // src/shared/binancePublicApi.ts
@@ -1646,6 +1363,7 @@ var DEFAULT_BINANCE_PUBLIC_API_URL = "https://data-api.binance.vision";
1646
1363
  var getBinancePublicApiUrl = () => process.env.BINANCE_BASE_URL?.trim() || DEFAULT_BINANCE_PUBLIC_API_URL;
1647
1364
 
1648
1365
  // src/Binance/index.ts
1366
+ var import_http = require("@tradejs/core/http");
1649
1367
  var INTERVAL_MAP = {
1650
1368
  "1": "1m",
1651
1369
  "3": "3m",
@@ -1692,7 +1410,7 @@ var capabilities = {
1692
1410
  supportedUniverses: ["crypto"],
1693
1411
  defaultUniverse: "crypto"
1694
1412
  };
1695
- var BinanceConnectorCreator = async (config) => {
1413
+ var BinanceConnectorCreator = async (config, runtime) => {
1696
1414
  let state = {};
1697
1415
  const universe = (0, import_types2.resolveConnectorUniverse)(capabilities, config.universe);
1698
1416
  const requestKline = async ({
@@ -1820,7 +1538,7 @@ var BinanceConnectorCreator = async (config) => {
1820
1538
  setState: async (newState) => {
1821
1539
  state = { ...state, ...newState };
1822
1540
  },
1823
- kline: createTimescaleCachedKline({
1541
+ kline: decorateConnectorKline(runtime, {
1824
1542
  provider: "binance",
1825
1543
  request: requestKline,
1826
1544
  intervalToMinutes
@@ -1915,8 +1633,8 @@ var BinanceConnectorCreator = async (config) => {
1915
1633
  };
1916
1634
 
1917
1635
  // src/Coinbase/index.ts
1918
- var import_http2 = require("@tradejs/infra/http");
1919
1636
  var import_types3 = require("@tradejs/types");
1637
+ var import_http2 = require("@tradejs/core/http");
1920
1638
  var INTERVAL_MS2 = {
1921
1639
  "1": 6e4,
1922
1640
  "3": 18e4,
@@ -1983,7 +1701,7 @@ var capabilities2 = {
1983
1701
  supportedUniverses: ["crypto"],
1984
1702
  defaultUniverse: "crypto"
1985
1703
  };
1986
- var CoinbaseConnectorCreator = async (config) => {
1704
+ var CoinbaseConnectorCreator = async (config, runtime) => {
1987
1705
  let state = {};
1988
1706
  const universe = (0, import_types3.resolveConnectorUniverse)(capabilities2, config.universe);
1989
1707
  const requestKline = async ({
@@ -2111,7 +1829,7 @@ var CoinbaseConnectorCreator = async (config) => {
2111
1829
  setState: async (newState) => {
2112
1830
  state = { ...state, ...newState };
2113
1831
  },
2114
- kline: createTimescaleCachedKline({
1832
+ kline: decorateConnectorKline(runtime, {
2115
1833
  provider: "coinbase",
2116
1834
  request: requestKline,
2117
1835
  intervalToMinutes: intervalToMinutes2
@@ -2131,7 +1849,7 @@ var CoinbaseConnectorCreator = async (config) => {
2131
1849
  };
2132
1850
 
2133
1851
  // src/marketData/spotKlineProviders.ts
2134
- var import_http3 = require("@tradejs/infra/http");
1852
+ var import_http3 = require("@tradejs/core/http");
2135
1853
  var toIntervalToken = (interval) => interval === "1h" ? "1h" : "15m";
2136
1854
  var mapBinanceKline = (payload) => payload.map((item) => {
2137
1855
  if (!Array.isArray(item)) return null;
@@ -2235,9 +1953,7 @@ var spotKlineProviders = {
2235
1953
 
2236
1954
  // src/ByBit/klineStream.ts
2237
1955
  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");
1956
+ var import_time3 = require("@tradejs/core/time");
2241
1957
  var CATEGORY = "linear";
2242
1958
  var SUBSCRIPTION_BATCH_SIZE = 100;
2243
1959
  var KLINE_TOPIC_PATTERN = /^kline\.([^.]+)\.(.+)$/;
@@ -2277,7 +1993,7 @@ var parseBybitKlineEvent = (value, receivedAt = Date.now()) => {
2277
1993
  symbol: symbol.toUpperCase(),
2278
1994
  interval,
2279
1995
  candle: {
2280
- dt: (0, import_time4.formatUnix)(timestamp),
1996
+ dt: (0, import_time3.formatUnix)(timestamp),
2281
1997
  timestamp,
2282
1998
  open,
2283
1999
  high,
@@ -2294,22 +2010,23 @@ var parseBybitKlineEvent = (value, receivedAt = Date.now()) => {
2294
2010
  };
2295
2011
  var createBybitKlineStreamWithClient = ({
2296
2012
  client,
2297
- onEvent
2013
+ onEvent,
2014
+ logger = getConnectorLogger()
2298
2015
  }) => {
2299
2016
  let topics = /* @__PURE__ */ new Set();
2300
2017
  let closed = false;
2301
2018
  client.on("update", (value) => {
2302
2019
  for (const event of parseBybitKlineEvent(value)) {
2303
2020
  void Promise.resolve(onEvent(event)).catch((error) => {
2304
- import_logger4.logger.error("Bybit kline stream handler failed: %s", String(error));
2021
+ logger.error("Bybit kline stream handler failed: %s", String(error));
2305
2022
  });
2306
2023
  }
2307
2024
  });
2308
2025
  client.on("reconnected", ({ wsKey }) => {
2309
- import_logger4.logger.info("Bybit kline stream reconnected: %s", wsKey);
2026
+ logger.info("Bybit kline stream reconnected: %s", wsKey);
2310
2027
  });
2311
2028
  client.on("exception", (error) => {
2312
- import_logger4.logger.error("Bybit kline stream exception: %s", String(error));
2029
+ logger.error("Bybit kline stream exception: %s", String(error));
2313
2030
  });
2314
2031
  return {
2315
2032
  setSubscriptions: (symbols, interval) => {
@@ -2323,16 +2040,16 @@ var createBybitKlineStreamWithClient = ({
2323
2040
  const removed = [...topics].filter((topic) => !nextTopics.has(topic));
2324
2041
  for (const batch of chunk(removed, SUBSCRIPTION_BATCH_SIZE)) {
2325
2042
  void Promise.all(client.unsubscribeV5(batch, CATEGORY)).catch(
2326
- (error) => import_logger4.logger.error("Bybit kline unsubscribe failed: %s", String(error))
2043
+ (error) => logger.error("Bybit kline unsubscribe failed: %s", String(error))
2327
2044
  );
2328
2045
  }
2329
2046
  for (const batch of chunk(added, SUBSCRIPTION_BATCH_SIZE)) {
2330
2047
  void Promise.all(client.subscribeV5(batch, CATEGORY)).catch(
2331
- (error) => import_logger4.logger.error("Bybit kline subscribe failed: %s", String(error))
2048
+ (error) => logger.error("Bybit kline subscribe failed: %s", String(error))
2332
2049
  );
2333
2050
  }
2334
2051
  topics = nextTopics;
2335
- import_logger4.logger.info(
2052
+ logger.info(
2336
2053
  "Bybit kline stream subscriptions: topics=%s added=%s removed=%s",
2337
2054
  topics.size,
2338
2055
  added.length,
@@ -2353,9 +2070,11 @@ var createBybitKlineStreamWithClient = ({
2353
2070
  };
2354
2071
  var createBybitKlineStream = async ({
2355
2072
  config,
2356
- onEvent
2073
+ onEvent,
2074
+ runtime
2357
2075
  }) => {
2358
- const account = config.accountId ? await (0, import_tradingAccounts2.resolveTradingAccount)({
2076
+ const resolveTradingAccount = getConnectorAccountResolver(runtime);
2077
+ const account = config.accountId ? await resolveTradingAccount({
2359
2078
  userName: config.userName,
2360
2079
  accountId: config.accountId,
2361
2080
  provider: "bybit",
@@ -2368,7 +2087,11 @@ var createBybitKlineStream = async ({
2368
2087
  Number(process.env.BYBIT_WS_RECONNECT_TIMEOUT_MS ?? 1e3)
2369
2088
  )
2370
2089
  });
2371
- return createBybitKlineStreamWithClient({ client, onEvent });
2090
+ return createBybitKlineStreamWithClient({
2091
+ client,
2092
+ onEvent,
2093
+ logger: getConnectorLogger(runtime)
2094
+ });
2372
2095
  };
2373
2096
 
2374
2097
  // src/marketData/providers/binanceCoinbaseSpread.ts
@@ -2427,7 +2150,7 @@ var binanceCoinbaseSpreadProvider = {
2427
2150
  };
2428
2151
 
2429
2152
  // src/marketData/providers/coinalyze.ts
2430
- var import_async3 = require("@tradejs/core/async");
2153
+ var import_async2 = require("@tradejs/core/async");
2431
2154
  var import_indicators2 = require("@tradejs/core/indicators");
2432
2155
  var coinalyzeIntervalMap = {
2433
2156
  "15m": "15min",
@@ -2497,7 +2220,7 @@ var fetchCoinalyzeSeries = async (params) => {
2497
2220
  lastRequestTs + coinalyzeMinRequestDelayMs - now
2498
2221
  );
2499
2222
  if (waitMs > 0) {
2500
- await (0, import_async3.delay)(waitMs);
2223
+ await (0, import_async2.delay)(waitMs);
2501
2224
  }
2502
2225
  lastRequestTs = Date.now();
2503
2226
  const response = await fetch(url.toString(), { headers });
@@ -2511,7 +2234,7 @@ var fetchCoinalyzeSeries = async (params) => {
2511
2234
  const transient = response.status === 429 || response.status >= 500;
2512
2235
  if (attempt < coinalyzeMaxRetries && transient) {
2513
2236
  const backoffMs = Math.min(1e4, 750 * 2 ** attempt);
2514
- await (0, import_async3.delay)(retryAfterMs ?? backoffMs);
2237
+ await (0, import_async2.delay)(retryAfterMs ?? backoffMs);
2515
2238
  continue;
2516
2239
  }
2517
2240
  throw new Error(`Coinalyze ${endpoint} ${response.status}: ${text}`);