@tradejs/cli 1.0.12 → 2.0.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.
@@ -2610,7 +2610,7 @@ var import_userSettings = require("@tradejs/infra/userSettings");
2610
2610
  var HOUR_MS = 60 * 60 * 1e3;
2611
2611
  var DAY_MS2 = 24 * HOUR_MS;
2612
2612
  var DEFAULT_LOOKBACK_HOURS = 48;
2613
- var DEFAULT_INTERVALS = ["15m", "1h"];
2613
+ var SOURCE_INTERVALS = ["15m"];
2614
2614
  var coinalyzeIntervalMap = {
2615
2615
  "15m": "15min",
2616
2616
  "1h": "1hour"
@@ -2671,10 +2671,7 @@ var isDerivativesContextBackfillEnabled = (env) => {
2671
2671
  var shouldBackfillDerivativesContextForBacktest = (params) => !params.cacheOnly && (params.aiEnabled || params.mlEnabled) && isBacktestDerivativesContextEnabled();
2672
2672
  var shouldBackfillDerivativesContextForSignals = (params) => !params.cacheOnly && isSignalsDerivativesContextEnabled();
2673
2673
  var resolveDerivativesContextIntervals = () => {
2674
- const intervals = (0, import_indicators2.normalizeDerivativesIntervals)(
2675
- process.env.DERIVATIVES_CONTEXT_INTERVALS
2676
- );
2677
- return intervals.length ? intervals : DEFAULT_INTERVALS;
2674
+ return [...SOURCE_INTERVALS];
2678
2675
  };
2679
2676
  var resolveDerivativesContextLookbackMs = () => {
2680
2677
  const hours = Number(process.env.DERIVATIVES_CONTEXT_LOOKBACK_HOURS);
@@ -2709,9 +2706,10 @@ var resolveDerivativesContextBackfillWindow = (params) => {
2709
2706
  };
2710
2707
  var resolveDerivativesContextIntervalBackfillWindow = (params) => {
2711
2708
  const intervalMs2 = derivativesIntervalMs(params.interval);
2709
+ const alignedToMs = params.closedOnly ? (0, import_indicators2.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs2) * intervalMs2;
2712
2710
  return {
2713
2711
  fromMs: Math.floor(params.fromMs / intervalMs2) * intervalMs2,
2714
- toMs: Math.floor(params.toMs / intervalMs2) * intervalMs2,
2712
+ toMs: alignedToMs,
2715
2713
  intervalMs: intervalMs2
2716
2714
  };
2717
2715
  };
@@ -2729,6 +2727,7 @@ var resolveDerivativesContextMissingFetchFromMs = (params) => {
2729
2727
  }
2730
2728
  return null;
2731
2729
  };
2730
+ var resolveDerivativesContextFetchFromMs = (params) => resolveDerivativesContextMissingFetchFromMs(params) ?? (params.refreshClosedTail ? params.toMs : null);
2732
2731
  var countBackfillWindows = (params) => {
2733
2732
  let count = 0;
2734
2733
  let cursor = params.fromMs;
@@ -2792,6 +2791,14 @@ var groupDerivativesContextMissingFetchRanges = (ranges) => {
2792
2791
  }
2793
2792
  return [...groups.entries()].sort(([a], [b]) => a - b).map(([fromMs, items]) => ({ fromMs, items }));
2794
2793
  };
2794
+ var getMissingClosedDerivativesSymbols = (params) => {
2795
+ const availableSymbols = new Set(
2796
+ params.rows.filter((row) => row.ts.getTime() === params.expectedTimestamp).map((row) => row.symbol.trim().toUpperCase())
2797
+ );
2798
+ return params.symbols.filter(
2799
+ (symbol) => !availableSymbols.has(symbol.trim().toUpperCase())
2800
+ );
2801
+ };
2795
2802
  var coverageKey = (params) => [
2796
2803
  params.symbol.trim().toUpperCase(),
2797
2804
  params.interval,
@@ -3071,7 +3078,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3071
3078
  ...resolveDerivativesContextIntervalBackfillWindow({
3072
3079
  fromMs,
3073
3080
  toMs: safeEndMs,
3074
- interval: interval2
3081
+ interval: interval2,
3082
+ closedOnly: mode === "signals"
3075
3083
  })
3076
3084
  })).filter((item) => item.toMs > item.fromMs);
3077
3085
  if (!intervalWindows.length) {
@@ -3130,7 +3138,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3130
3138
  }),
3131
3139
  0
3132
3140
  );
3133
- const allBackfillWindowsCached = intervalWindows.every((window2) => {
3141
+ const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window2) => {
3134
3142
  const edgesBySymbol = edgesByInterval.get(window2.interval);
3135
3143
  const coverageKeys = coverageKeysByInterval.get(window2.interval);
3136
3144
  const backfillWindows = buildBackfillWindows({
@@ -3260,7 +3268,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3260
3268
  return null;
3261
3269
  }
3262
3270
  const normalizedSymbol = item.symbol.toUpperCase();
3263
- const coverageFromMs = resolveDerivativesContextMissingCoverageFetchFromMs({
3271
+ const coverageFromMs = mode === "signals" ? cursor : resolveDerivativesContextMissingCoverageFetchFromMs({
3264
3272
  ranges: coverageRangesBySymbol.get(normalizedSymbol),
3265
3273
  fromMs: cursor,
3266
3274
  toMs,
@@ -3270,16 +3278,20 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3270
3278
  return null;
3271
3279
  }
3272
3280
  const edges = edgesBySymbol.get(normalizedSymbol);
3273
- const edgesFromMs = resolveDerivativesContextMissingFetchFromMs({
3281
+ const edgesFromMs = resolveDerivativesContextFetchFromMs({
3274
3282
  edges,
3275
3283
  fromMs: cursor,
3276
3284
  toMs,
3277
- intervalMs: intervalMs2
3285
+ intervalMs: intervalMs2,
3286
+ refreshClosedTail: mode === "signals"
3278
3287
  });
3279
3288
  if (edgesFromMs == null) {
3280
3289
  return null;
3281
3290
  }
3282
- return { item, fromMs: Math.max(coverageFromMs, edgesFromMs) };
3291
+ return {
3292
+ item,
3293
+ fromMs: Math.max(coverageFromMs, edgesFromMs)
3294
+ };
3283
3295
  }).filter(
3284
3296
  (item) => item != null
3285
3297
  );
@@ -3293,85 +3305,113 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3293
3305
  const marketSymbols = missingBatch.map(
3294
3306
  (item) => item.marketSymbol
3295
3307
  );
3296
- const oiMap = await fetchMetricBatch({
3297
- endpoint: oiPath,
3298
- metric: "oi",
3299
- marketSymbols,
3300
- apiKey,
3301
- interval: interval2,
3302
- fromMs: group.fromMs,
3303
- toMs
3304
- });
3305
- const fundingMap = await fetchMetricBatch({
3306
- endpoint: fundingPath,
3307
- metric: "funding",
3308
- marketSymbols,
3309
- apiKey,
3310
- interval: interval2,
3311
- fromMs: group.fromMs,
3312
- toMs
3313
- });
3314
- const liqMap = await fetchMetricBatch({
3315
- endpoint: liqPath,
3316
- metric: "liq",
3317
- marketSymbols,
3318
- apiKey,
3319
- interval: interval2,
3320
- fromMs: group.fromMs,
3321
- toMs
3322
- });
3323
- const rows = missingBatch.flatMap((item) => {
3324
- const marketSymbol = item.marketSymbol.toUpperCase();
3325
- const points = (0, import_indicators2.mergeCoinalyzeMetrics)({
3326
- symbol: item.symbol,
3327
- oiRaw: oiMap.get(marketSymbol) ?? [],
3328
- fundingRaw: fundingMap.get(marketSymbol) ?? [],
3329
- liqRaw: liqMap.get(marketSymbol) ?? []
3308
+ const maxClosedBarAttempts = mode === "signals" ? asInt2(
3309
+ process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_MAX_ATTEMPTS,
3310
+ 3
3311
+ ) : 1;
3312
+ const closedBarRetryDelayMs = asInt2(
3313
+ process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_RETRY_DELAY_MS,
3314
+ 2e3
3315
+ );
3316
+ let rows = [];
3317
+ let missingClosedSymbols = [];
3318
+ for (let attempt = 1; attempt <= maxClosedBarAttempts; attempt += 1) {
3319
+ const oiMap = await fetchMetricBatch({
3320
+ endpoint: oiPath,
3321
+ metric: "oi",
3322
+ marketSymbols,
3323
+ apiKey,
3324
+ interval: interval2,
3325
+ fromMs: group.fromMs,
3326
+ toMs
3327
+ });
3328
+ const fundingMap = await fetchMetricBatch({
3329
+ endpoint: fundingPath,
3330
+ metric: "funding",
3331
+ marketSymbols,
3332
+ apiKey,
3333
+ interval: interval2,
3334
+ fromMs: group.fromMs,
3335
+ toMs
3330
3336
  });
3331
- return (0, import_indicators2.coinalyzePointsToRows)(points, interval2, "coinalyze");
3332
- });
3337
+ const liqMap = await fetchMetricBatch({
3338
+ endpoint: liqPath,
3339
+ metric: "liq",
3340
+ marketSymbols,
3341
+ apiKey,
3342
+ interval: interval2,
3343
+ fromMs: group.fromMs,
3344
+ toMs
3345
+ });
3346
+ rows = missingBatch.flatMap((item) => {
3347
+ const marketSymbol = item.marketSymbol.toUpperCase();
3348
+ const points = (0, import_indicators2.mergeCoinalyzeMetrics)({
3349
+ symbol: item.symbol,
3350
+ oiRaw: oiMap.get(marketSymbol) ?? [],
3351
+ fundingRaw: fundingMap.get(marketSymbol) ?? [],
3352
+ liqRaw: liqMap.get(marketSymbol) ?? []
3353
+ });
3354
+ return (0, import_indicators2.coinalyzePointsToRows)(points, interval2, "coinalyze");
3355
+ });
3356
+ missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
3357
+ symbols: missingBatch.map((item) => item.symbol),
3358
+ rows,
3359
+ expectedTimestamp: toMs
3360
+ }) : [];
3361
+ if (!missingClosedSymbols.length) break;
3362
+ if (attempt < maxClosedBarAttempts) {
3363
+ await (0, import_async.delay)(closedBarRetryDelayMs);
3364
+ }
3365
+ }
3366
+ if (missingClosedSymbols.length) {
3367
+ throw new Error(
3368
+ `Coinalyze closed ${interval2} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
3369
+ );
3370
+ }
3333
3371
  if (rows.length) {
3334
3372
  await (0, import_timescale2.upsertDerivatives)(rows);
3335
3373
  totalRows += rows.length;
3336
3374
  }
3337
- const rowsCountBySymbol = /* @__PURE__ */ new Map();
3338
- for (const row of rows) {
3339
- const symbol = row.symbol.toUpperCase();
3340
- rowsCountBySymbol.set(
3341
- symbol,
3342
- (rowsCountBySymbol.get(symbol) ?? 0) + 1
3343
- );
3344
- }
3345
- const coverageRows = missingBatch.map((item) => {
3346
- const normalizedSymbol = item.symbol.toUpperCase();
3347
- const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
3348
- return {
3349
- source: "coinalyze",
3350
- symbol: item.symbol,
3351
- interval: interval2,
3352
- fromMs: cursor,
3353
- toMs,
3354
- rowsCount
3355
- };
3356
- });
3357
- await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
3358
- for (const coverageRow of coverageRows) {
3359
- const symbol = coverageRow.symbol.toUpperCase();
3360
- edgesBySymbol.set(
3361
- symbol,
3362
- extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
3363
- );
3364
- coverageKeys.add(
3365
- coverageKey({
3375
+ if (mode === "backtest") {
3376
+ const rowsCountBySymbol = /* @__PURE__ */ new Map();
3377
+ for (const row of rows) {
3378
+ const symbol = row.symbol.toUpperCase();
3379
+ rowsCountBySymbol.set(
3366
3380
  symbol,
3381
+ (rowsCountBySymbol.get(symbol) ?? 0) + 1
3382
+ );
3383
+ }
3384
+ const coverageRows = missingBatch.map((item) => {
3385
+ const normalizedSymbol = item.symbol.toUpperCase();
3386
+ const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
3387
+ return {
3388
+ source: "coinalyze",
3389
+ symbol: item.symbol,
3367
3390
  interval: interval2,
3368
3391
  fromMs: cursor,
3369
- toMs
3370
- })
3371
- );
3372
- const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
3373
- coverageRanges.push({ fromMs: cursor, toMs });
3374
- coverageRangesBySymbol.set(symbol, coverageRanges);
3392
+ toMs,
3393
+ rowsCount
3394
+ };
3395
+ });
3396
+ await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
3397
+ for (const coverageRow of coverageRows) {
3398
+ const symbol = coverageRow.symbol.toUpperCase();
3399
+ edgesBySymbol.set(
3400
+ symbol,
3401
+ extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
3402
+ );
3403
+ coverageKeys.add(
3404
+ coverageKey({
3405
+ symbol,
3406
+ interval: interval2,
3407
+ fromMs: cursor,
3408
+ toMs
3409
+ })
3410
+ );
3411
+ const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
3412
+ coverageRanges.push({ fromMs: cursor, toMs });
3413
+ coverageRangesBySymbol.set(symbol, coverageRanges);
3414
+ }
3375
3415
  }
3376
3416
  }
3377
3417
  }
@@ -2608,7 +2608,7 @@ var import_userSettings = require("@tradejs/infra/userSettings");
2608
2608
  var HOUR_MS = 60 * 60 * 1e3;
2609
2609
  var DAY_MS2 = 24 * HOUR_MS;
2610
2610
  var DEFAULT_LOOKBACK_HOURS = 48;
2611
- var DEFAULT_INTERVALS = ["15m", "1h"];
2611
+ var SOURCE_INTERVALS = ["15m"];
2612
2612
  var coinalyzeIntervalMap = {
2613
2613
  "15m": "15min",
2614
2614
  "1h": "1hour"
@@ -2669,10 +2669,7 @@ var isDerivativesContextBackfillEnabled = (env) => {
2669
2669
  var shouldBackfillDerivativesContextForBacktest = (params) => !params.cacheOnly && (params.aiEnabled || params.mlEnabled) && isBacktestDerivativesContextEnabled();
2670
2670
  var shouldBackfillDerivativesContextForSignals = (params) => !params.cacheOnly && isSignalsDerivativesContextEnabled();
2671
2671
  var resolveDerivativesContextIntervals = () => {
2672
- const intervals = (0, import_indicators2.normalizeDerivativesIntervals)(
2673
- process.env.DERIVATIVES_CONTEXT_INTERVALS
2674
- );
2675
- return intervals.length ? intervals : DEFAULT_INTERVALS;
2672
+ return [...SOURCE_INTERVALS];
2676
2673
  };
2677
2674
  var resolveDerivativesContextLookbackMs = () => {
2678
2675
  const hours = Number(process.env.DERIVATIVES_CONTEXT_LOOKBACK_HOURS);
@@ -2707,9 +2704,10 @@ var resolveDerivativesContextBackfillWindow = (params) => {
2707
2704
  };
2708
2705
  var resolveDerivativesContextIntervalBackfillWindow = (params) => {
2709
2706
  const intervalMs2 = derivativesIntervalMs(params.interval);
2707
+ const alignedToMs = params.closedOnly ? (0, import_indicators2.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs2) * intervalMs2;
2710
2708
  return {
2711
2709
  fromMs: Math.floor(params.fromMs / intervalMs2) * intervalMs2,
2712
- toMs: Math.floor(params.toMs / intervalMs2) * intervalMs2,
2710
+ toMs: alignedToMs,
2713
2711
  intervalMs: intervalMs2
2714
2712
  };
2715
2713
  };
@@ -2727,6 +2725,7 @@ var resolveDerivativesContextMissingFetchFromMs = (params) => {
2727
2725
  }
2728
2726
  return null;
2729
2727
  };
2728
+ var resolveDerivativesContextFetchFromMs = (params) => resolveDerivativesContextMissingFetchFromMs(params) ?? (params.refreshClosedTail ? params.toMs : null);
2730
2729
  var countBackfillWindows = (params) => {
2731
2730
  let count = 0;
2732
2731
  let cursor = params.fromMs;
@@ -2790,6 +2789,14 @@ var groupDerivativesContextMissingFetchRanges = (ranges) => {
2790
2789
  }
2791
2790
  return [...groups.entries()].sort(([a], [b]) => a - b).map(([fromMs, items]) => ({ fromMs, items }));
2792
2791
  };
2792
+ var getMissingClosedDerivativesSymbols = (params) => {
2793
+ const availableSymbols = new Set(
2794
+ params.rows.filter((row) => row.ts.getTime() === params.expectedTimestamp).map((row) => row.symbol.trim().toUpperCase())
2795
+ );
2796
+ return params.symbols.filter(
2797
+ (symbol) => !availableSymbols.has(symbol.trim().toUpperCase())
2798
+ );
2799
+ };
2793
2800
  var coverageKey = (params) => [
2794
2801
  params.symbol.trim().toUpperCase(),
2795
2802
  params.interval,
@@ -3069,7 +3076,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3069
3076
  ...resolveDerivativesContextIntervalBackfillWindow({
3070
3077
  fromMs,
3071
3078
  toMs: safeEndMs,
3072
- interval: interval2
3079
+ interval: interval2,
3080
+ closedOnly: mode === "signals"
3073
3081
  })
3074
3082
  })).filter((item) => item.toMs > item.fromMs);
3075
3083
  if (!intervalWindows.length) {
@@ -3128,7 +3136,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3128
3136
  }),
3129
3137
  0
3130
3138
  );
3131
- const allBackfillWindowsCached = intervalWindows.every((window2) => {
3139
+ const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window2) => {
3132
3140
  const edgesBySymbol = edgesByInterval.get(window2.interval);
3133
3141
  const coverageKeys = coverageKeysByInterval.get(window2.interval);
3134
3142
  const backfillWindows = buildBackfillWindows({
@@ -3258,7 +3266,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3258
3266
  return null;
3259
3267
  }
3260
3268
  const normalizedSymbol = item.symbol.toUpperCase();
3261
- const coverageFromMs = resolveDerivativesContextMissingCoverageFetchFromMs({
3269
+ const coverageFromMs = mode === "signals" ? cursor : resolveDerivativesContextMissingCoverageFetchFromMs({
3262
3270
  ranges: coverageRangesBySymbol.get(normalizedSymbol),
3263
3271
  fromMs: cursor,
3264
3272
  toMs,
@@ -3268,16 +3276,20 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3268
3276
  return null;
3269
3277
  }
3270
3278
  const edges = edgesBySymbol.get(normalizedSymbol);
3271
- const edgesFromMs = resolveDerivativesContextMissingFetchFromMs({
3279
+ const edgesFromMs = resolveDerivativesContextFetchFromMs({
3272
3280
  edges,
3273
3281
  fromMs: cursor,
3274
3282
  toMs,
3275
- intervalMs: intervalMs2
3283
+ intervalMs: intervalMs2,
3284
+ refreshClosedTail: mode === "signals"
3276
3285
  });
3277
3286
  if (edgesFromMs == null) {
3278
3287
  return null;
3279
3288
  }
3280
- return { item, fromMs: Math.max(coverageFromMs, edgesFromMs) };
3289
+ return {
3290
+ item,
3291
+ fromMs: Math.max(coverageFromMs, edgesFromMs)
3292
+ };
3281
3293
  }).filter(
3282
3294
  (item) => item != null
3283
3295
  );
@@ -3291,85 +3303,113 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
3291
3303
  const marketSymbols = missingBatch.map(
3292
3304
  (item) => item.marketSymbol
3293
3305
  );
3294
- const oiMap = await fetchMetricBatch({
3295
- endpoint: oiPath,
3296
- metric: "oi",
3297
- marketSymbols,
3298
- apiKey,
3299
- interval: interval2,
3300
- fromMs: group.fromMs,
3301
- toMs
3302
- });
3303
- const fundingMap = await fetchMetricBatch({
3304
- endpoint: fundingPath,
3305
- metric: "funding",
3306
- marketSymbols,
3307
- apiKey,
3308
- interval: interval2,
3309
- fromMs: group.fromMs,
3310
- toMs
3311
- });
3312
- const liqMap = await fetchMetricBatch({
3313
- endpoint: liqPath,
3314
- metric: "liq",
3315
- marketSymbols,
3316
- apiKey,
3317
- interval: interval2,
3318
- fromMs: group.fromMs,
3319
- toMs
3320
- });
3321
- const rows = missingBatch.flatMap((item) => {
3322
- const marketSymbol = item.marketSymbol.toUpperCase();
3323
- const points = (0, import_indicators2.mergeCoinalyzeMetrics)({
3324
- symbol: item.symbol,
3325
- oiRaw: oiMap.get(marketSymbol) ?? [],
3326
- fundingRaw: fundingMap.get(marketSymbol) ?? [],
3327
- liqRaw: liqMap.get(marketSymbol) ?? []
3306
+ const maxClosedBarAttempts = mode === "signals" ? asInt2(
3307
+ process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_MAX_ATTEMPTS,
3308
+ 3
3309
+ ) : 1;
3310
+ const closedBarRetryDelayMs = asInt2(
3311
+ process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_RETRY_DELAY_MS,
3312
+ 2e3
3313
+ );
3314
+ let rows = [];
3315
+ let missingClosedSymbols = [];
3316
+ for (let attempt = 1; attempt <= maxClosedBarAttempts; attempt += 1) {
3317
+ const oiMap = await fetchMetricBatch({
3318
+ endpoint: oiPath,
3319
+ metric: "oi",
3320
+ marketSymbols,
3321
+ apiKey,
3322
+ interval: interval2,
3323
+ fromMs: group.fromMs,
3324
+ toMs
3325
+ });
3326
+ const fundingMap = await fetchMetricBatch({
3327
+ endpoint: fundingPath,
3328
+ metric: "funding",
3329
+ marketSymbols,
3330
+ apiKey,
3331
+ interval: interval2,
3332
+ fromMs: group.fromMs,
3333
+ toMs
3328
3334
  });
3329
- return (0, import_indicators2.coinalyzePointsToRows)(points, interval2, "coinalyze");
3330
- });
3335
+ const liqMap = await fetchMetricBatch({
3336
+ endpoint: liqPath,
3337
+ metric: "liq",
3338
+ marketSymbols,
3339
+ apiKey,
3340
+ interval: interval2,
3341
+ fromMs: group.fromMs,
3342
+ toMs
3343
+ });
3344
+ rows = missingBatch.flatMap((item) => {
3345
+ const marketSymbol = item.marketSymbol.toUpperCase();
3346
+ const points = (0, import_indicators2.mergeCoinalyzeMetrics)({
3347
+ symbol: item.symbol,
3348
+ oiRaw: oiMap.get(marketSymbol) ?? [],
3349
+ fundingRaw: fundingMap.get(marketSymbol) ?? [],
3350
+ liqRaw: liqMap.get(marketSymbol) ?? []
3351
+ });
3352
+ return (0, import_indicators2.coinalyzePointsToRows)(points, interval2, "coinalyze");
3353
+ });
3354
+ missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
3355
+ symbols: missingBatch.map((item) => item.symbol),
3356
+ rows,
3357
+ expectedTimestamp: toMs
3358
+ }) : [];
3359
+ if (!missingClosedSymbols.length) break;
3360
+ if (attempt < maxClosedBarAttempts) {
3361
+ await (0, import_async.delay)(closedBarRetryDelayMs);
3362
+ }
3363
+ }
3364
+ if (missingClosedSymbols.length) {
3365
+ throw new Error(
3366
+ `Coinalyze closed ${interval2} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
3367
+ );
3368
+ }
3331
3369
  if (rows.length) {
3332
3370
  await (0, import_timescale2.upsertDerivatives)(rows);
3333
3371
  totalRows += rows.length;
3334
3372
  }
3335
- const rowsCountBySymbol = /* @__PURE__ */ new Map();
3336
- for (const row of rows) {
3337
- const symbol = row.symbol.toUpperCase();
3338
- rowsCountBySymbol.set(
3339
- symbol,
3340
- (rowsCountBySymbol.get(symbol) ?? 0) + 1
3341
- );
3342
- }
3343
- const coverageRows = missingBatch.map((item) => {
3344
- const normalizedSymbol = item.symbol.toUpperCase();
3345
- const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
3346
- return {
3347
- source: "coinalyze",
3348
- symbol: item.symbol,
3349
- interval: interval2,
3350
- fromMs: cursor,
3351
- toMs,
3352
- rowsCount
3353
- };
3354
- });
3355
- await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
3356
- for (const coverageRow of coverageRows) {
3357
- const symbol = coverageRow.symbol.toUpperCase();
3358
- edgesBySymbol.set(
3359
- symbol,
3360
- extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
3361
- );
3362
- coverageKeys.add(
3363
- coverageKey({
3373
+ if (mode === "backtest") {
3374
+ const rowsCountBySymbol = /* @__PURE__ */ new Map();
3375
+ for (const row of rows) {
3376
+ const symbol = row.symbol.toUpperCase();
3377
+ rowsCountBySymbol.set(
3364
3378
  symbol,
3379
+ (rowsCountBySymbol.get(symbol) ?? 0) + 1
3380
+ );
3381
+ }
3382
+ const coverageRows = missingBatch.map((item) => {
3383
+ const normalizedSymbol = item.symbol.toUpperCase();
3384
+ const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
3385
+ return {
3386
+ source: "coinalyze",
3387
+ symbol: item.symbol,
3365
3388
  interval: interval2,
3366
3389
  fromMs: cursor,
3367
- toMs
3368
- })
3369
- );
3370
- const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
3371
- coverageRanges.push({ fromMs: cursor, toMs });
3372
- coverageRangesBySymbol.set(symbol, coverageRanges);
3390
+ toMs,
3391
+ rowsCount
3392
+ };
3393
+ });
3394
+ await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
3395
+ for (const coverageRow of coverageRows) {
3396
+ const symbol = coverageRow.symbol.toUpperCase();
3397
+ edgesBySymbol.set(
3398
+ symbol,
3399
+ extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
3400
+ );
3401
+ coverageKeys.add(
3402
+ coverageKey({
3403
+ symbol,
3404
+ interval: interval2,
3405
+ fromMs: cursor,
3406
+ toMs
3407
+ })
3408
+ );
3409
+ const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
3410
+ coverageRanges.push({ fromMs: cursor, toMs });
3411
+ coverageRangesBySymbol.set(symbol, coverageRanges);
3412
+ }
3373
3413
  }
3374
3414
  }
3375
3415
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tradejs/cli",
3
- "version": "1.0.12",
4
- "description": "Official CLI for the TradeJS open-source framework: infra setup, backtests, signals, bots, and ML workflows.",
3
+ "version": "2.0.1",
4
+ "description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
5
5
  "keywords": [
6
6
  "tradejs",
7
7
  "trading",
@@ -29,14 +29,14 @@
29
29
  "tradejs": "dist/cli.js"
30
30
  },
31
31
  "dependencies": {
32
- "@tradejs/base": "^1.0.12",
33
- "@tradejs/connectors": "^1.0.12",
34
- "@tradejs/core": "^1.0.12",
35
- "@tradejs/indicators": "^1.0.12",
36
- "@tradejs/infra": "^1.0.12",
37
- "@tradejs/node": "^1.0.12",
38
- "@tradejs/strategies": "^1.0.12",
39
- "@tradejs/types": "^1.0.12",
32
+ "@tradejs/base": "^2.0.1",
33
+ "@tradejs/connectors": "^2.0.1",
34
+ "@tradejs/core": "^2.0.1",
35
+ "@tradejs/indicators": "^2.0.1",
36
+ "@tradejs/infra": "^2.0.1",
37
+ "@tradejs/node": "^2.0.1",
38
+ "@tradejs/strategies": "^2.0.1",
39
+ "@tradejs/types": "^2.0.1",
40
40
  "args": "^5.0.3",
41
41
  "bcryptjs": "^2.4.3",
42
42
  "chalk": "4.1.2",
@@ -100,6 +100,6 @@
100
100
  "test-ml": "yarn run run:dist test-ml",
101
101
  "user-add": "yarn run run:dist user-add"
102
102
  },
103
- "license": "MIT",
103
+ "license": "BUSL-1.1",
104
104
  "author": "aleksnick (https://github.com/aleksnick)"
105
105
  }