@tradejs/cli 2.0.0 → 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.
- package/dist/cli.js +143 -93
- package/dist/lib/aiTrainResearch.js +0 -1
- package/dist/lib/derivativesContextBackfill.js +127 -83
- package/dist/lib/marketContextPrepare.js +123 -83
- package/dist/scripts/aiTrain.js +0 -1
- package/dist/scripts/backtest.js +123 -83
- package/dist/scripts/derivativesIngest.js +11 -4
- package/dist/scripts/derivativesIngestCoinalyzeAll.js +8 -4
- package/dist/scripts/replay.js +123 -83
- package/dist/scripts/replayRunner.js +123 -83
- package/dist/scripts/runtimeParity.js +123 -83
- package/dist/scripts/signals.js +123 -83
- package/dist/scripts/signalsDaemon.js +123 -83
- package/package.json +9 -9
|
@@ -3109,7 +3109,7 @@ var import_userSettings = require("@tradejs/infra/userSettings");
|
|
|
3109
3109
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
3110
3110
|
var DAY_MS2 = 24 * HOUR_MS;
|
|
3111
3111
|
var DEFAULT_LOOKBACK_HOURS = 48;
|
|
3112
|
-
var
|
|
3112
|
+
var SOURCE_INTERVALS = ["15m"];
|
|
3113
3113
|
var coinalyzeIntervalMap = {
|
|
3114
3114
|
"15m": "15min",
|
|
3115
3115
|
"1h": "1hour"
|
|
@@ -3170,10 +3170,7 @@ var isDerivativesContextBackfillEnabled = (env) => {
|
|
|
3170
3170
|
var shouldBackfillDerivativesContextForBacktest = (params) => !params.cacheOnly && (params.aiEnabled || params.mlEnabled) && isBacktestDerivativesContextEnabled();
|
|
3171
3171
|
var shouldBackfillDerivativesContextForSignals = (params) => !params.cacheOnly && isSignalsDerivativesContextEnabled();
|
|
3172
3172
|
var resolveDerivativesContextIntervals = () => {
|
|
3173
|
-
|
|
3174
|
-
process.env.DERIVATIVES_CONTEXT_INTERVALS
|
|
3175
|
-
);
|
|
3176
|
-
return intervals.length ? intervals : DEFAULT_INTERVALS;
|
|
3173
|
+
return [...SOURCE_INTERVALS];
|
|
3177
3174
|
};
|
|
3178
3175
|
var resolveDerivativesContextLookbackMs = () => {
|
|
3179
3176
|
const hours = Number(process.env.DERIVATIVES_CONTEXT_LOOKBACK_HOURS);
|
|
@@ -3208,9 +3205,10 @@ var resolveDerivativesContextBackfillWindow = (params) => {
|
|
|
3208
3205
|
};
|
|
3209
3206
|
var resolveDerivativesContextIntervalBackfillWindow = (params) => {
|
|
3210
3207
|
const intervalMs = derivativesIntervalMs(params.interval);
|
|
3208
|
+
const alignedToMs = params.closedOnly ? (0, import_indicators.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs) * intervalMs;
|
|
3211
3209
|
return {
|
|
3212
3210
|
fromMs: Math.floor(params.fromMs / intervalMs) * intervalMs,
|
|
3213
|
-
toMs:
|
|
3211
|
+
toMs: alignedToMs,
|
|
3214
3212
|
intervalMs
|
|
3215
3213
|
};
|
|
3216
3214
|
};
|
|
@@ -3228,6 +3226,7 @@ var resolveDerivativesContextMissingFetchFromMs = (params) => {
|
|
|
3228
3226
|
}
|
|
3229
3227
|
return null;
|
|
3230
3228
|
};
|
|
3229
|
+
var resolveDerivativesContextFetchFromMs = (params) => resolveDerivativesContextMissingFetchFromMs(params) ?? (params.refreshClosedTail ? params.toMs : null);
|
|
3231
3230
|
var countBackfillWindows = (params) => {
|
|
3232
3231
|
let count = 0;
|
|
3233
3232
|
let cursor = params.fromMs;
|
|
@@ -3291,6 +3290,14 @@ var groupDerivativesContextMissingFetchRanges = (ranges) => {
|
|
|
3291
3290
|
}
|
|
3292
3291
|
return [...groups.entries()].sort(([a], [b]) => a - b).map(([fromMs, items]) => ({ fromMs, items }));
|
|
3293
3292
|
};
|
|
3293
|
+
var getMissingClosedDerivativesSymbols = (params) => {
|
|
3294
|
+
const availableSymbols = new Set(
|
|
3295
|
+
params.rows.filter((row) => row.ts.getTime() === params.expectedTimestamp).map((row) => row.symbol.trim().toUpperCase())
|
|
3296
|
+
);
|
|
3297
|
+
return params.symbols.filter(
|
|
3298
|
+
(symbol) => !availableSymbols.has(symbol.trim().toUpperCase())
|
|
3299
|
+
);
|
|
3300
|
+
};
|
|
3294
3301
|
var coverageKey = (params) => [
|
|
3295
3302
|
params.symbol.trim().toUpperCase(),
|
|
3296
3303
|
params.interval,
|
|
@@ -3570,7 +3577,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3570
3577
|
...resolveDerivativesContextIntervalBackfillWindow({
|
|
3571
3578
|
fromMs,
|
|
3572
3579
|
toMs: safeEndMs,
|
|
3573
|
-
interval
|
|
3580
|
+
interval,
|
|
3581
|
+
closedOnly: mode === "signals"
|
|
3574
3582
|
})
|
|
3575
3583
|
})).filter((item) => item.toMs > item.fromMs);
|
|
3576
3584
|
if (!intervalWindows.length) {
|
|
@@ -3629,7 +3637,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3629
3637
|
}),
|
|
3630
3638
|
0
|
|
3631
3639
|
);
|
|
3632
|
-
const allBackfillWindowsCached = intervalWindows.every((window2) => {
|
|
3640
|
+
const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window2) => {
|
|
3633
3641
|
const edgesBySymbol = edgesByInterval.get(window2.interval);
|
|
3634
3642
|
const coverageKeys = coverageKeysByInterval.get(window2.interval);
|
|
3635
3643
|
const backfillWindows = buildBackfillWindows({
|
|
@@ -3759,7 +3767,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3759
3767
|
return null;
|
|
3760
3768
|
}
|
|
3761
3769
|
const normalizedSymbol = item.symbol.toUpperCase();
|
|
3762
|
-
const coverageFromMs = resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
3770
|
+
const coverageFromMs = mode === "signals" ? cursor : resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
3763
3771
|
ranges: coverageRangesBySymbol.get(normalizedSymbol),
|
|
3764
3772
|
fromMs: cursor,
|
|
3765
3773
|
toMs,
|
|
@@ -3769,16 +3777,20 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3769
3777
|
return null;
|
|
3770
3778
|
}
|
|
3771
3779
|
const edges = edgesBySymbol.get(normalizedSymbol);
|
|
3772
|
-
const edgesFromMs =
|
|
3780
|
+
const edgesFromMs = resolveDerivativesContextFetchFromMs({
|
|
3773
3781
|
edges,
|
|
3774
3782
|
fromMs: cursor,
|
|
3775
3783
|
toMs,
|
|
3776
|
-
intervalMs
|
|
3784
|
+
intervalMs,
|
|
3785
|
+
refreshClosedTail: mode === "signals"
|
|
3777
3786
|
});
|
|
3778
3787
|
if (edgesFromMs == null) {
|
|
3779
3788
|
return null;
|
|
3780
3789
|
}
|
|
3781
|
-
return {
|
|
3790
|
+
return {
|
|
3791
|
+
item,
|
|
3792
|
+
fromMs: Math.max(coverageFromMs, edgesFromMs)
|
|
3793
|
+
};
|
|
3782
3794
|
}).filter(
|
|
3783
3795
|
(item) => item != null
|
|
3784
3796
|
);
|
|
@@ -3792,85 +3804,113 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3792
3804
|
const marketSymbols = missingBatch.map(
|
|
3793
3805
|
(item) => item.marketSymbol
|
|
3794
3806
|
);
|
|
3795
|
-
const
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
3824
|
-
const points = (0, import_indicators.mergeCoinalyzeMetrics)({
|
|
3825
|
-
symbol: item.symbol,
|
|
3826
|
-
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
3827
|
-
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
3828
|
-
liqRaw: liqMap.get(marketSymbol) ?? []
|
|
3807
|
+
const maxClosedBarAttempts = mode === "signals" ? asInt2(
|
|
3808
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_MAX_ATTEMPTS,
|
|
3809
|
+
3
|
|
3810
|
+
) : 1;
|
|
3811
|
+
const closedBarRetryDelayMs = asInt2(
|
|
3812
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_RETRY_DELAY_MS,
|
|
3813
|
+
2e3
|
|
3814
|
+
);
|
|
3815
|
+
let rows = [];
|
|
3816
|
+
let missingClosedSymbols = [];
|
|
3817
|
+
for (let attempt = 1; attempt <= maxClosedBarAttempts; attempt += 1) {
|
|
3818
|
+
const oiMap = await fetchMetricBatch({
|
|
3819
|
+
endpoint: oiPath,
|
|
3820
|
+
metric: "oi",
|
|
3821
|
+
marketSymbols,
|
|
3822
|
+
apiKey,
|
|
3823
|
+
interval,
|
|
3824
|
+
fromMs: group.fromMs,
|
|
3825
|
+
toMs
|
|
3826
|
+
});
|
|
3827
|
+
const fundingMap = await fetchMetricBatch({
|
|
3828
|
+
endpoint: fundingPath,
|
|
3829
|
+
metric: "funding",
|
|
3830
|
+
marketSymbols,
|
|
3831
|
+
apiKey,
|
|
3832
|
+
interval,
|
|
3833
|
+
fromMs: group.fromMs,
|
|
3834
|
+
toMs
|
|
3829
3835
|
});
|
|
3830
|
-
|
|
3831
|
-
|
|
3836
|
+
const liqMap = await fetchMetricBatch({
|
|
3837
|
+
endpoint: liqPath,
|
|
3838
|
+
metric: "liq",
|
|
3839
|
+
marketSymbols,
|
|
3840
|
+
apiKey,
|
|
3841
|
+
interval,
|
|
3842
|
+
fromMs: group.fromMs,
|
|
3843
|
+
toMs
|
|
3844
|
+
});
|
|
3845
|
+
rows = missingBatch.flatMap((item) => {
|
|
3846
|
+
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
3847
|
+
const points = (0, import_indicators.mergeCoinalyzeMetrics)({
|
|
3848
|
+
symbol: item.symbol,
|
|
3849
|
+
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
3850
|
+
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
3851
|
+
liqRaw: liqMap.get(marketSymbol) ?? []
|
|
3852
|
+
});
|
|
3853
|
+
return (0, import_indicators.coinalyzePointsToRows)(points, interval, "coinalyze");
|
|
3854
|
+
});
|
|
3855
|
+
missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
|
|
3856
|
+
symbols: missingBatch.map((item) => item.symbol),
|
|
3857
|
+
rows,
|
|
3858
|
+
expectedTimestamp: toMs
|
|
3859
|
+
}) : [];
|
|
3860
|
+
if (!missingClosedSymbols.length) break;
|
|
3861
|
+
if (attempt < maxClosedBarAttempts) {
|
|
3862
|
+
await (0, import_async.delay)(closedBarRetryDelayMs);
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
if (missingClosedSymbols.length) {
|
|
3866
|
+
throw new Error(
|
|
3867
|
+
`Coinalyze closed ${interval} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
|
|
3868
|
+
);
|
|
3869
|
+
}
|
|
3832
3870
|
if (rows.length) {
|
|
3833
3871
|
await (0, import_timescale2.upsertDerivatives)(rows);
|
|
3834
3872
|
totalRows += rows.length;
|
|
3835
3873
|
}
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
const
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
3842
|
-
);
|
|
3843
|
-
}
|
|
3844
|
-
const coverageRows = missingBatch.map((item) => {
|
|
3845
|
-
const normalizedSymbol = item.symbol.toUpperCase();
|
|
3846
|
-
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
3847
|
-
return {
|
|
3848
|
-
source: "coinalyze",
|
|
3849
|
-
symbol: item.symbol,
|
|
3850
|
-
interval,
|
|
3851
|
-
fromMs: cursor,
|
|
3852
|
-
toMs,
|
|
3853
|
-
rowsCount
|
|
3854
|
-
};
|
|
3855
|
-
});
|
|
3856
|
-
await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
|
|
3857
|
-
for (const coverageRow of coverageRows) {
|
|
3858
|
-
const symbol = coverageRow.symbol.toUpperCase();
|
|
3859
|
-
edgesBySymbol.set(
|
|
3860
|
-
symbol,
|
|
3861
|
-
extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
|
|
3862
|
-
);
|
|
3863
|
-
coverageKeys.add(
|
|
3864
|
-
coverageKey({
|
|
3874
|
+
if (mode === "backtest") {
|
|
3875
|
+
const rowsCountBySymbol = /* @__PURE__ */ new Map();
|
|
3876
|
+
for (const row of rows) {
|
|
3877
|
+
const symbol = row.symbol.toUpperCase();
|
|
3878
|
+
rowsCountBySymbol.set(
|
|
3865
3879
|
symbol,
|
|
3880
|
+
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
3881
|
+
);
|
|
3882
|
+
}
|
|
3883
|
+
const coverageRows = missingBatch.map((item) => {
|
|
3884
|
+
const normalizedSymbol = item.symbol.toUpperCase();
|
|
3885
|
+
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
3886
|
+
return {
|
|
3887
|
+
source: "coinalyze",
|
|
3888
|
+
symbol: item.symbol,
|
|
3866
3889
|
interval,
|
|
3867
3890
|
fromMs: cursor,
|
|
3868
|
-
toMs
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3891
|
+
toMs,
|
|
3892
|
+
rowsCount
|
|
3893
|
+
};
|
|
3894
|
+
});
|
|
3895
|
+
await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
|
|
3896
|
+
for (const coverageRow of coverageRows) {
|
|
3897
|
+
const symbol = coverageRow.symbol.toUpperCase();
|
|
3898
|
+
edgesBySymbol.set(
|
|
3899
|
+
symbol,
|
|
3900
|
+
extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
|
|
3901
|
+
);
|
|
3902
|
+
coverageKeys.add(
|
|
3903
|
+
coverageKey({
|
|
3904
|
+
symbol,
|
|
3905
|
+
interval,
|
|
3906
|
+
fromMs: cursor,
|
|
3907
|
+
toMs
|
|
3908
|
+
})
|
|
3909
|
+
);
|
|
3910
|
+
const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
|
|
3911
|
+
coverageRanges.push({ fromMs: cursor, toMs });
|
|
3912
|
+
coverageRangesBySymbol.set(symbol, coverageRanges);
|
|
3913
|
+
}
|
|
3874
3914
|
}
|
|
3875
3915
|
}
|
|
3876
3916
|
}
|
|
@@ -3114,7 +3114,7 @@ var import_userSettings = require("@tradejs/infra/userSettings");
|
|
|
3114
3114
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
3115
3115
|
var DAY_MS2 = 24 * HOUR_MS;
|
|
3116
3116
|
var DEFAULT_LOOKBACK_HOURS = 48;
|
|
3117
|
-
var
|
|
3117
|
+
var SOURCE_INTERVALS = ["15m"];
|
|
3118
3118
|
var coinalyzeIntervalMap = {
|
|
3119
3119
|
"15m": "15min",
|
|
3120
3120
|
"1h": "1hour"
|
|
@@ -3175,10 +3175,7 @@ var isDerivativesContextBackfillEnabled = (env) => {
|
|
|
3175
3175
|
var shouldBackfillDerivativesContextForBacktest = (params) => !params.cacheOnly && (params.aiEnabled || params.mlEnabled) && isBacktestDerivativesContextEnabled();
|
|
3176
3176
|
var shouldBackfillDerivativesContextForSignals = (params) => !params.cacheOnly && isSignalsDerivativesContextEnabled();
|
|
3177
3177
|
var resolveDerivativesContextIntervals = () => {
|
|
3178
|
-
|
|
3179
|
-
process.env.DERIVATIVES_CONTEXT_INTERVALS
|
|
3180
|
-
);
|
|
3181
|
-
return intervals.length ? intervals : DEFAULT_INTERVALS;
|
|
3178
|
+
return [...SOURCE_INTERVALS];
|
|
3182
3179
|
};
|
|
3183
3180
|
var resolveDerivativesContextLookbackMs = () => {
|
|
3184
3181
|
const hours = Number(process.env.DERIVATIVES_CONTEXT_LOOKBACK_HOURS);
|
|
@@ -3213,9 +3210,10 @@ var resolveDerivativesContextBackfillWindow = (params) => {
|
|
|
3213
3210
|
};
|
|
3214
3211
|
var resolveDerivativesContextIntervalBackfillWindow = (params) => {
|
|
3215
3212
|
const intervalMs = derivativesIntervalMs(params.interval);
|
|
3213
|
+
const alignedToMs = params.closedOnly ? (0, import_indicators.getLastClosedDerivativesBarStartMs)(params.toMs, params.interval) : Math.floor(params.toMs / intervalMs) * intervalMs;
|
|
3216
3214
|
return {
|
|
3217
3215
|
fromMs: Math.floor(params.fromMs / intervalMs) * intervalMs,
|
|
3218
|
-
toMs:
|
|
3216
|
+
toMs: alignedToMs,
|
|
3219
3217
|
intervalMs
|
|
3220
3218
|
};
|
|
3221
3219
|
};
|
|
@@ -3233,6 +3231,7 @@ var resolveDerivativesContextMissingFetchFromMs = (params) => {
|
|
|
3233
3231
|
}
|
|
3234
3232
|
return null;
|
|
3235
3233
|
};
|
|
3234
|
+
var resolveDerivativesContextFetchFromMs = (params) => resolveDerivativesContextMissingFetchFromMs(params) ?? (params.refreshClosedTail ? params.toMs : null);
|
|
3236
3235
|
var countBackfillWindows = (params) => {
|
|
3237
3236
|
let count = 0;
|
|
3238
3237
|
let cursor = params.fromMs;
|
|
@@ -3296,6 +3295,14 @@ var groupDerivativesContextMissingFetchRanges = (ranges) => {
|
|
|
3296
3295
|
}
|
|
3297
3296
|
return [...groups.entries()].sort(([a], [b]) => a - b).map(([fromMs, items]) => ({ fromMs, items }));
|
|
3298
3297
|
};
|
|
3298
|
+
var getMissingClosedDerivativesSymbols = (params) => {
|
|
3299
|
+
const availableSymbols = new Set(
|
|
3300
|
+
params.rows.filter((row) => row.ts.getTime() === params.expectedTimestamp).map((row) => row.symbol.trim().toUpperCase())
|
|
3301
|
+
);
|
|
3302
|
+
return params.symbols.filter(
|
|
3303
|
+
(symbol) => !availableSymbols.has(symbol.trim().toUpperCase())
|
|
3304
|
+
);
|
|
3305
|
+
};
|
|
3299
3306
|
var coverageKey = (params) => [
|
|
3300
3307
|
params.symbol.trim().toUpperCase(),
|
|
3301
3308
|
params.interval,
|
|
@@ -3575,7 +3582,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3575
3582
|
...resolveDerivativesContextIntervalBackfillWindow({
|
|
3576
3583
|
fromMs,
|
|
3577
3584
|
toMs: safeEndMs,
|
|
3578
|
-
interval: interval2
|
|
3585
|
+
interval: interval2,
|
|
3586
|
+
closedOnly: mode === "signals"
|
|
3579
3587
|
})
|
|
3580
3588
|
})).filter((item) => item.toMs > item.fromMs);
|
|
3581
3589
|
if (!intervalWindows.length) {
|
|
@@ -3634,7 +3642,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3634
3642
|
}),
|
|
3635
3643
|
0
|
|
3636
3644
|
);
|
|
3637
|
-
const allBackfillWindowsCached = intervalWindows.every((window2) => {
|
|
3645
|
+
const allBackfillWindowsCached = mode !== "signals" && intervalWindows.every((window2) => {
|
|
3638
3646
|
const edgesBySymbol = edgesByInterval.get(window2.interval);
|
|
3639
3647
|
const coverageKeys = coverageKeysByInterval.get(window2.interval);
|
|
3640
3648
|
const backfillWindows = buildBackfillWindows({
|
|
@@ -3764,7 +3772,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3764
3772
|
return null;
|
|
3765
3773
|
}
|
|
3766
3774
|
const normalizedSymbol = item.symbol.toUpperCase();
|
|
3767
|
-
const coverageFromMs = resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
3775
|
+
const coverageFromMs = mode === "signals" ? cursor : resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
3768
3776
|
ranges: coverageRangesBySymbol.get(normalizedSymbol),
|
|
3769
3777
|
fromMs: cursor,
|
|
3770
3778
|
toMs,
|
|
@@ -3774,16 +3782,20 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3774
3782
|
return null;
|
|
3775
3783
|
}
|
|
3776
3784
|
const edges = edgesBySymbol.get(normalizedSymbol);
|
|
3777
|
-
const edgesFromMs =
|
|
3785
|
+
const edgesFromMs = resolveDerivativesContextFetchFromMs({
|
|
3778
3786
|
edges,
|
|
3779
3787
|
fromMs: cursor,
|
|
3780
3788
|
toMs,
|
|
3781
|
-
intervalMs
|
|
3789
|
+
intervalMs,
|
|
3790
|
+
refreshClosedTail: mode === "signals"
|
|
3782
3791
|
});
|
|
3783
3792
|
if (edgesFromMs == null) {
|
|
3784
3793
|
return null;
|
|
3785
3794
|
}
|
|
3786
|
-
return {
|
|
3795
|
+
return {
|
|
3796
|
+
item,
|
|
3797
|
+
fromMs: Math.max(coverageFromMs, edgesFromMs)
|
|
3798
|
+
};
|
|
3787
3799
|
}).filter(
|
|
3788
3800
|
(item) => item != null
|
|
3789
3801
|
);
|
|
@@ -3797,85 +3809,113 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3797
3809
|
const marketSymbols = missingBatch.map(
|
|
3798
3810
|
(item) => item.marketSymbol
|
|
3799
3811
|
);
|
|
3800
|
-
const
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
endpoint: liqPath,
|
|
3820
|
-
metric: "liq",
|
|
3821
|
-
marketSymbols,
|
|
3822
|
-
apiKey,
|
|
3823
|
-
interval: interval2,
|
|
3824
|
-
fromMs: group.fromMs,
|
|
3825
|
-
toMs
|
|
3826
|
-
});
|
|
3827
|
-
const rows = missingBatch.flatMap((item) => {
|
|
3828
|
-
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
3829
|
-
const points = (0, import_indicators.mergeCoinalyzeMetrics)({
|
|
3830
|
-
symbol: item.symbol,
|
|
3831
|
-
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
3832
|
-
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
3833
|
-
liqRaw: liqMap.get(marketSymbol) ?? []
|
|
3812
|
+
const maxClosedBarAttempts = mode === "signals" ? asInt2(
|
|
3813
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_MAX_ATTEMPTS,
|
|
3814
|
+
3
|
|
3815
|
+
) : 1;
|
|
3816
|
+
const closedBarRetryDelayMs = asInt2(
|
|
3817
|
+
process.env.DERIVATIVES_CONTEXT_CLOSED_BAR_RETRY_DELAY_MS,
|
|
3818
|
+
2e3
|
|
3819
|
+
);
|
|
3820
|
+
let rows = [];
|
|
3821
|
+
let missingClosedSymbols = [];
|
|
3822
|
+
for (let attempt = 1; attempt <= maxClosedBarAttempts; attempt += 1) {
|
|
3823
|
+
const oiMap = await fetchMetricBatch({
|
|
3824
|
+
endpoint: oiPath,
|
|
3825
|
+
metric: "oi",
|
|
3826
|
+
marketSymbols,
|
|
3827
|
+
apiKey,
|
|
3828
|
+
interval: interval2,
|
|
3829
|
+
fromMs: group.fromMs,
|
|
3830
|
+
toMs
|
|
3834
3831
|
});
|
|
3835
|
-
|
|
3836
|
-
|
|
3832
|
+
const fundingMap = await fetchMetricBatch({
|
|
3833
|
+
endpoint: fundingPath,
|
|
3834
|
+
metric: "funding",
|
|
3835
|
+
marketSymbols,
|
|
3836
|
+
apiKey,
|
|
3837
|
+
interval: interval2,
|
|
3838
|
+
fromMs: group.fromMs,
|
|
3839
|
+
toMs
|
|
3840
|
+
});
|
|
3841
|
+
const liqMap = await fetchMetricBatch({
|
|
3842
|
+
endpoint: liqPath,
|
|
3843
|
+
metric: "liq",
|
|
3844
|
+
marketSymbols,
|
|
3845
|
+
apiKey,
|
|
3846
|
+
interval: interval2,
|
|
3847
|
+
fromMs: group.fromMs,
|
|
3848
|
+
toMs
|
|
3849
|
+
});
|
|
3850
|
+
rows = missingBatch.flatMap((item) => {
|
|
3851
|
+
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
3852
|
+
const points = (0, import_indicators.mergeCoinalyzeMetrics)({
|
|
3853
|
+
symbol: item.symbol,
|
|
3854
|
+
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
3855
|
+
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
3856
|
+
liqRaw: liqMap.get(marketSymbol) ?? []
|
|
3857
|
+
});
|
|
3858
|
+
return (0, import_indicators.coinalyzePointsToRows)(points, interval2, "coinalyze");
|
|
3859
|
+
});
|
|
3860
|
+
missingClosedSymbols = mode === "signals" ? getMissingClosedDerivativesSymbols({
|
|
3861
|
+
symbols: missingBatch.map((item) => item.symbol),
|
|
3862
|
+
rows,
|
|
3863
|
+
expectedTimestamp: toMs
|
|
3864
|
+
}) : [];
|
|
3865
|
+
if (!missingClosedSymbols.length) break;
|
|
3866
|
+
if (attempt < maxClosedBarAttempts) {
|
|
3867
|
+
await (0, import_async.delay)(closedBarRetryDelayMs);
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3870
|
+
if (missingClosedSymbols.length) {
|
|
3871
|
+
throw new Error(
|
|
3872
|
+
`Coinalyze closed ${interval2} bar ${new Date(toMs).toISOString()} unavailable for ${missingClosedSymbols.join(",")}`
|
|
3873
|
+
);
|
|
3874
|
+
}
|
|
3837
3875
|
if (rows.length) {
|
|
3838
3876
|
await (0, import_timescale2.upsertDerivatives)(rows);
|
|
3839
3877
|
totalRows += rows.length;
|
|
3840
3878
|
}
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
const
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
3847
|
-
);
|
|
3848
|
-
}
|
|
3849
|
-
const coverageRows = missingBatch.map((item) => {
|
|
3850
|
-
const normalizedSymbol = item.symbol.toUpperCase();
|
|
3851
|
-
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
3852
|
-
return {
|
|
3853
|
-
source: "coinalyze",
|
|
3854
|
-
symbol: item.symbol,
|
|
3855
|
-
interval: interval2,
|
|
3856
|
-
fromMs: cursor,
|
|
3857
|
-
toMs,
|
|
3858
|
-
rowsCount
|
|
3859
|
-
};
|
|
3860
|
-
});
|
|
3861
|
-
await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
|
|
3862
|
-
for (const coverageRow of coverageRows) {
|
|
3863
|
-
const symbol = coverageRow.symbol.toUpperCase();
|
|
3864
|
-
edgesBySymbol.set(
|
|
3865
|
-
symbol,
|
|
3866
|
-
extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
|
|
3867
|
-
);
|
|
3868
|
-
coverageKeys.add(
|
|
3869
|
-
coverageKey({
|
|
3879
|
+
if (mode === "backtest") {
|
|
3880
|
+
const rowsCountBySymbol = /* @__PURE__ */ new Map();
|
|
3881
|
+
for (const row of rows) {
|
|
3882
|
+
const symbol = row.symbol.toUpperCase();
|
|
3883
|
+
rowsCountBySymbol.set(
|
|
3870
3884
|
symbol,
|
|
3885
|
+
(rowsCountBySymbol.get(symbol) ?? 0) + 1
|
|
3886
|
+
);
|
|
3887
|
+
}
|
|
3888
|
+
const coverageRows = missingBatch.map((item) => {
|
|
3889
|
+
const normalizedSymbol = item.symbol.toUpperCase();
|
|
3890
|
+
const rowsCount = rowsCountBySymbol.get(normalizedSymbol) ?? 0;
|
|
3891
|
+
return {
|
|
3892
|
+
source: "coinalyze",
|
|
3893
|
+
symbol: item.symbol,
|
|
3871
3894
|
interval: interval2,
|
|
3872
3895
|
fromMs: cursor,
|
|
3873
|
-
toMs
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3896
|
+
toMs,
|
|
3897
|
+
rowsCount
|
|
3898
|
+
};
|
|
3899
|
+
});
|
|
3900
|
+
await (0, import_timescale2.upsertDerivativesBackfillCoverage)(coverageRows);
|
|
3901
|
+
for (const coverageRow of coverageRows) {
|
|
3902
|
+
const symbol = coverageRow.symbol.toUpperCase();
|
|
3903
|
+
edgesBySymbol.set(
|
|
3904
|
+
symbol,
|
|
3905
|
+
extendEdges(edgesBySymbol.get(symbol), cursor, toMs)
|
|
3906
|
+
);
|
|
3907
|
+
coverageKeys.add(
|
|
3908
|
+
coverageKey({
|
|
3909
|
+
symbol,
|
|
3910
|
+
interval: interval2,
|
|
3911
|
+
fromMs: cursor,
|
|
3912
|
+
toMs
|
|
3913
|
+
})
|
|
3914
|
+
);
|
|
3915
|
+
const coverageRanges = coverageRangesBySymbol.get(symbol) ?? [];
|
|
3916
|
+
coverageRanges.push({ fromMs: cursor, toMs });
|
|
3917
|
+
coverageRangesBySymbol.set(symbol, coverageRanges);
|
|
3918
|
+
}
|
|
3879
3919
|
}
|
|
3880
3920
|
}
|
|
3881
3921
|
}
|