@tradejs/cli 2.0.1 → 2.0.3
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 +293 -58
- package/dist/lib/aiPocketSearch.js +18 -0
- package/dist/lib/aiTrainCharts.js +49 -2
- package/dist/lib/aiTrainMetrics.js +49 -2
- package/dist/lib/aiTrainResearch.js +58 -3
- package/dist/lib/derivativesContextBackfill.js +143 -32
- package/dist/lib/marketContextPrepare.js +141 -32
- package/dist/lib/runtimeTradeSync.js +22 -15
- package/dist/scripts/aiExport.js +2 -1
- package/dist/scripts/aiExportSelect.js +2 -1
- package/dist/scripts/aiPocketSearch.js +67 -2
- package/dist/scripts/aiTrain.js +76 -3
- package/dist/scripts/backtest.js +141 -32
- package/dist/scripts/derivativesIngestCoinalyzeAll.js +30 -0
- package/dist/scripts/mlExport.js +2 -1
- package/dist/scripts/mlExportSelect.js +2 -1
- package/dist/scripts/mlTrainLatestSelect.js +2 -1
- package/dist/scripts/replay.js +161 -47
- package/dist/scripts/replayRunner.js +161 -47
- package/dist/scripts/resolveExportStrategy.js +2 -1
- package/dist/scripts/runtimeParity.js +141 -32
- package/dist/scripts/selectStrategy.js +2 -1
- package/dist/scripts/signals.js +141 -32
- package/dist/scripts/signalsDaemon.js +141 -32
- package/dist/scripts/signalsSummary.js +21 -17
- package/package.json +9 -9
package/dist/scripts/aiTrain.js
CHANGED
|
@@ -1653,6 +1653,7 @@ var divideOrNull = (num, denom) => {
|
|
|
1653
1653
|
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
1654
1654
|
var DAYS_PER_WEEK = 7;
|
|
1655
1655
|
var DAYS_PER_MONTH = 30.4375;
|
|
1656
|
+
var DAYS_PER_YEAR = 365;
|
|
1656
1657
|
var getEvaluationPeriodDays = (evaluations) => {
|
|
1657
1658
|
let minTimestamp = null;
|
|
1658
1659
|
let maxTimestamp = null;
|
|
@@ -1674,6 +1675,40 @@ var getEvaluationPeriodDays = (evaluations) => {
|
|
|
1674
1675
|
return Math.max((maxTimestamp - minTimestamp) / DAY_MS, 1);
|
|
1675
1676
|
};
|
|
1676
1677
|
var qualitySortKey = (quality) => quality == null ? Number.POSITIVE_INFINITY : quality;
|
|
1678
|
+
var calculateTradePnlRiskRatios = ({
|
|
1679
|
+
profits,
|
|
1680
|
+
totalProfit,
|
|
1681
|
+
maxDrawdown,
|
|
1682
|
+
periodDays
|
|
1683
|
+
}) => {
|
|
1684
|
+
if (!profits.length || periodDays == null || periodDays <= 0) {
|
|
1685
|
+
return {
|
|
1686
|
+
sharpeRatio: null,
|
|
1687
|
+
sortinoRatio: null,
|
|
1688
|
+
calmarRatio: null
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1691
|
+
const meanProfit = totalProfit / profits.length;
|
|
1692
|
+
const variance = profits.reduce((sum, profit) => {
|
|
1693
|
+
const diff = profit - meanProfit;
|
|
1694
|
+
return sum + diff * diff;
|
|
1695
|
+
}, 0) / profits.length;
|
|
1696
|
+
const stdDev = Math.sqrt(variance);
|
|
1697
|
+
const downsideDeviation = Math.sqrt(
|
|
1698
|
+
profits.reduce(
|
|
1699
|
+
(sum, profit) => profit < 0 ? sum + profit * profit : sum,
|
|
1700
|
+
0
|
|
1701
|
+
) / profits.length
|
|
1702
|
+
);
|
|
1703
|
+
const annualizationScale = Math.sqrt(
|
|
1704
|
+
profits.length / periodDays * DAYS_PER_YEAR
|
|
1705
|
+
);
|
|
1706
|
+
return {
|
|
1707
|
+
sharpeRatio: stdDev > 0 && annualizationScale > 0 ? meanProfit / stdDev * annualizationScale : null,
|
|
1708
|
+
sortinoRatio: downsideDeviation > 0 && annualizationScale > 0 ? meanProfit / downsideDeviation * annualizationScale : null,
|
|
1709
|
+
calmarRatio: maxDrawdown > 0 ? totalProfit / periodDays * DAYS_PER_YEAR / maxDrawdown : null
|
|
1710
|
+
};
|
|
1711
|
+
};
|
|
1677
1712
|
var emptyRiskSummary = () => ({
|
|
1678
1713
|
trades: 0,
|
|
1679
1714
|
totalProfit: 0,
|
|
@@ -1689,12 +1724,15 @@ var emptyRiskSummary = () => ({
|
|
|
1689
1724
|
maxDrawdown: 0,
|
|
1690
1725
|
maxDrawdownPctOfGrossProfit: null,
|
|
1691
1726
|
maxDrawdownPctOfTotalProfit: null,
|
|
1727
|
+
sharpeRatio: null,
|
|
1728
|
+
sortinoRatio: null,
|
|
1729
|
+
calmarRatio: null,
|
|
1692
1730
|
recoveryFactor: null,
|
|
1693
1731
|
ulcerIndex: null,
|
|
1694
1732
|
maxConsecutiveWins: 0,
|
|
1695
1733
|
maxConsecutiveLosses: 0
|
|
1696
1734
|
});
|
|
1697
|
-
var summarizeApprovedRisk = (evaluations) => {
|
|
1735
|
+
var summarizeApprovedRisk = (evaluations, periodDays = getEvaluationPeriodDays(evaluations)) => {
|
|
1698
1736
|
const approvedEvaluations = evaluations.filter((evaluation) => evaluation.aiApproved).sort((left, right) => {
|
|
1699
1737
|
const leftTimestamp = typeof left.timestamp === "number" && Number.isFinite(left.timestamp) ? left.timestamp : Number.POSITIVE_INFINITY;
|
|
1700
1738
|
const rightTimestamp = typeof right.timestamp === "number" && Number.isFinite(right.timestamp) ? right.timestamp : Number.POSITIVE_INFINITY;
|
|
@@ -1717,8 +1755,10 @@ var summarizeApprovedRisk = (evaluations) => {
|
|
|
1717
1755
|
let currentLossStreak = 0;
|
|
1718
1756
|
let maxConsecutiveWins = 0;
|
|
1719
1757
|
let maxConsecutiveLosses = 0;
|
|
1758
|
+
const approvedProfits = [];
|
|
1720
1759
|
for (const evaluation of approvedEvaluations) {
|
|
1721
1760
|
const profit = evaluation.profit;
|
|
1761
|
+
approvedProfits.push(profit);
|
|
1722
1762
|
if (profit > 0) {
|
|
1723
1763
|
grossProfit += profit;
|
|
1724
1764
|
wins += 1;
|
|
@@ -1746,6 +1786,12 @@ var summarizeApprovedRisk = (evaluations) => {
|
|
|
1746
1786
|
const totalProfit = grossProfit - grossLoss;
|
|
1747
1787
|
const avgWin = divideOrNull(grossProfit, wins);
|
|
1748
1788
|
const avgLoss = divideOrNull(grossLoss, losses);
|
|
1789
|
+
const riskRatios = calculateTradePnlRiskRatios({
|
|
1790
|
+
profits: approvedProfits,
|
|
1791
|
+
totalProfit,
|
|
1792
|
+
maxDrawdown,
|
|
1793
|
+
periodDays
|
|
1794
|
+
});
|
|
1749
1795
|
return {
|
|
1750
1796
|
trades: approvedEvaluations.length,
|
|
1751
1797
|
totalProfit,
|
|
@@ -1761,6 +1807,7 @@ var summarizeApprovedRisk = (evaluations) => {
|
|
|
1761
1807
|
maxDrawdown,
|
|
1762
1808
|
maxDrawdownPctOfGrossProfit: grossProfit > 0 ? maxDrawdown / grossProfit : null,
|
|
1763
1809
|
maxDrawdownPctOfTotalProfit: totalProfit > 0 ? maxDrawdown / totalProfit : null,
|
|
1810
|
+
...riskRatios,
|
|
1764
1811
|
recoveryFactor: maxDrawdown > 0 ? totalProfit / maxDrawdown : null,
|
|
1765
1812
|
ulcerIndex: Math.sqrt(drawdownSquares / approvedEvaluations.length),
|
|
1766
1813
|
maxConsecutiveWins,
|
|
@@ -1859,7 +1906,7 @@ var summarizeAiTrainEvaluations = (evaluations) => {
|
|
|
1859
1906
|
avgApprovedTradesPerDay,
|
|
1860
1907
|
avgApprovedTradesPerWeek,
|
|
1861
1908
|
expectancyDelta,
|
|
1862
|
-
approvedRisk: summarizeApprovedRisk(evaluations),
|
|
1909
|
+
approvedRisk: summarizeApprovedRisk(evaluations, periodDays),
|
|
1863
1910
|
qualityBuckets: [...bucketMap.values()].sort(
|
|
1864
1911
|
(a, b) => qualitySortKey(a.quality) - qualitySortKey(b.quality)
|
|
1865
1912
|
)
|
|
@@ -2523,6 +2570,12 @@ var RESEARCH_CONTEXT_ENV_KEYS = [
|
|
|
2523
2570
|
"COINMARKETCAP_CONTEXT_BACKFILL_MAX_DAYS",
|
|
2524
2571
|
"COINMARKETCAP_CONTEXT_BACKFILL_WARMUP_DAYS"
|
|
2525
2572
|
];
|
|
2573
|
+
var DERIVATIVES_CONTEXT_DATA_MODEL = {
|
|
2574
|
+
derivativesSourceIntervals: "15m",
|
|
2575
|
+
derivativesDerivedIntervals: "1h",
|
|
2576
|
+
derivativesHourlyFallback: "stored-1h",
|
|
2577
|
+
derivativesDataModelVersion: 2
|
|
2578
|
+
};
|
|
2526
2579
|
var normalizeForStableJson = (value) => {
|
|
2527
2580
|
if (Array.isArray(value)) {
|
|
2528
2581
|
return value.map(normalizeForStableJson);
|
|
@@ -2635,6 +2688,7 @@ var resolveGateFingerprint = async (projectRoot, strategyName, gitSha) => {
|
|
|
2635
2688
|
const relativeCandidates = [
|
|
2636
2689
|
`packages/strategies/src/${strategyName}/adapters/ai.ts`,
|
|
2637
2690
|
`packages/strategies/src/${strategyName}/guardrails.ts`,
|
|
2691
|
+
`packages/strategies/src/${strategyName}/pockets.ts`,
|
|
2638
2692
|
`packages/strategies/src/${strategyName}/config.ts`,
|
|
2639
2693
|
"packages/node/src/ai.ts"
|
|
2640
2694
|
];
|
|
@@ -2681,7 +2735,8 @@ var buildAiTrainLineage = async ({
|
|
|
2681
2735
|
...Object.fromEntries(
|
|
2682
2736
|
RESEARCH_CONTEXT_ENV_KEYS.map((key) => [key, env[key] ?? null])
|
|
2683
2737
|
),
|
|
2684
|
-
...runContext
|
|
2738
|
+
...runContext,
|
|
2739
|
+
...DERIVATIVES_CONTEXT_DATA_MODEL
|
|
2685
2740
|
};
|
|
2686
2741
|
return {
|
|
2687
2742
|
gitSha,
|
|
@@ -3741,6 +3796,9 @@ var main = async () => {
|
|
|
3741
3796
|
import_chalk.default.gray("CALENDAR/D"),
|
|
3742
3797
|
import_chalk.default.gray("WR"),
|
|
3743
3798
|
import_chalk.default.gray("PF"),
|
|
3799
|
+
import_chalk.default.gray("SHARPE"),
|
|
3800
|
+
import_chalk.default.gray("SORTINO"),
|
|
3801
|
+
import_chalk.default.gray("CALMAR"),
|
|
3744
3802
|
import_chalk.default.gray("PNL"),
|
|
3745
3803
|
import_chalk.default.gray("MAX_DD"),
|
|
3746
3804
|
import_chalk.default.gray("TOP REJECT")
|
|
@@ -3755,6 +3813,9 @@ var main = async () => {
|
|
|
3755
3813
|
colorizeMetricNumber(window2.approvedPerCalendarDay),
|
|
3756
3814
|
colorizeRatio(window2.outcome.approvedRisk.winRate),
|
|
3757
3815
|
colorizeMetricNumber(window2.outcome.approvedRisk.profitFactor),
|
|
3816
|
+
colorizeMetricNumber(window2.outcome.approvedRisk.sharpeRatio),
|
|
3817
|
+
colorizeMetricNumber(window2.outcome.approvedRisk.sortinoRatio),
|
|
3818
|
+
colorizeMetricNumber(window2.outcome.approvedRisk.calmarRatio),
|
|
3758
3819
|
colorizeProfit(window2.outcome.approvedRisk.totalProfit),
|
|
3759
3820
|
colorizeProfit(-window2.outcome.approvedRisk.maxDrawdown),
|
|
3760
3821
|
import_chalk.default.gray(
|
|
@@ -3803,6 +3864,18 @@ var main = async () => {
|
|
|
3803
3864
|
"profit_factor",
|
|
3804
3865
|
colorizeMetricNumber(summary.approvedRisk.profitFactor)
|
|
3805
3866
|
],
|
|
3867
|
+
[
|
|
3868
|
+
"sharpe_ratio",
|
|
3869
|
+
colorizeMetricNumber(summary.approvedRisk.sharpeRatio)
|
|
3870
|
+
],
|
|
3871
|
+
[
|
|
3872
|
+
"sortino_ratio",
|
|
3873
|
+
colorizeMetricNumber(summary.approvedRisk.sortinoRatio)
|
|
3874
|
+
],
|
|
3875
|
+
[
|
|
3876
|
+
"calmar_ratio",
|
|
3877
|
+
colorizeMetricNumber(summary.approvedRisk.calmarRatio)
|
|
3878
|
+
],
|
|
3806
3879
|
[
|
|
3807
3880
|
"payoff_ratio",
|
|
3808
3881
|
colorizeMetricNumber(summary.approvedRisk.payoffRatio)
|
package/dist/scripts/backtest.js
CHANGED
|
@@ -2613,6 +2613,38 @@ var resolveDerivativesContextMissingFetchFromMs = (params) => {
|
|
|
2613
2613
|
return null;
|
|
2614
2614
|
};
|
|
2615
2615
|
var resolveDerivativesContextFetchFromMs = (params) => resolveDerivativesContextMissingFetchFromMs(params) ?? (params.refreshClosedTail ? params.toMs : null);
|
|
2616
|
+
var resolveDerivativesContextRequiredFetchFromMs = (params) => {
|
|
2617
|
+
const dataCoverageFromMs = params.dataCoverageKeyExists ? null : params.mode === "signals" ? params.fromMs : resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
2618
|
+
ranges: params.dataCoverageRanges,
|
|
2619
|
+
fromMs: params.fromMs,
|
|
2620
|
+
toMs: params.toMs,
|
|
2621
|
+
intervalMs: params.intervalMs
|
|
2622
|
+
});
|
|
2623
|
+
const edgesFromMs = dataCoverageFromMs == null ? null : resolveDerivativesContextFetchFromMs({
|
|
2624
|
+
edges: params.edges,
|
|
2625
|
+
fromMs: params.fromMs,
|
|
2626
|
+
toMs: params.toMs,
|
|
2627
|
+
intervalMs: params.intervalMs,
|
|
2628
|
+
refreshClosedTail: params.mode === "signals"
|
|
2629
|
+
});
|
|
2630
|
+
const dataFetchFromMs = dataCoverageFromMs != null && edgesFromMs != null ? Math.max(dataCoverageFromMs, edgesFromMs) : null;
|
|
2631
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
2632
|
+
interval: params.interval,
|
|
2633
|
+
fromMs: params.fromMs,
|
|
2634
|
+
toMs: params.toMs,
|
|
2635
|
+
nowMs: params.nowMs
|
|
2636
|
+
});
|
|
2637
|
+
const liquidationFetchFromMs = confirmedLiquidationWindow ? resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
2638
|
+
ranges: params.liquidationCoverageRanges,
|
|
2639
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
2640
|
+
toMs: confirmedLiquidationWindow.toMs,
|
|
2641
|
+
intervalMs: params.intervalMs
|
|
2642
|
+
}) : null;
|
|
2643
|
+
const fetchStarts = [dataFetchFromMs, liquidationFetchFromMs].filter(
|
|
2644
|
+
(value) => value != null
|
|
2645
|
+
);
|
|
2646
|
+
return fetchStarts.length ? Math.min(...fetchStarts) : null;
|
|
2647
|
+
};
|
|
2616
2648
|
var countBackfillWindows = (params) => {
|
|
2617
2649
|
let count = 0;
|
|
2618
2650
|
let cursor = params.fromMs;
|
|
@@ -2948,7 +2980,8 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
2948
2980
|
mode,
|
|
2949
2981
|
startMs,
|
|
2950
2982
|
endMs,
|
|
2951
|
-
preloadStartMs: params.preloadStartMs
|
|
2983
|
+
preloadStartMs: params.preloadStartMs,
|
|
2984
|
+
nowMs: Date.now()
|
|
2952
2985
|
});
|
|
2953
2986
|
if (safeEndMs <= fromMs) {
|
|
2954
2987
|
return skippedBackfillResult2();
|
|
@@ -2982,15 +3015,33 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
2982
3015
|
);
|
|
2983
3016
|
const coverageKeysByInterval = /* @__PURE__ */ new Map();
|
|
2984
3017
|
const coverageRangesByInterval = /* @__PURE__ */ new Map();
|
|
3018
|
+
const liquidationCoverageRangesByInterval = /* @__PURE__ */ new Map();
|
|
3019
|
+
const coverageNowMs = Date.now();
|
|
2985
3020
|
await Promise.all(
|
|
2986
3021
|
intervalWindows.map(async (window2) => {
|
|
2987
|
-
const
|
|
2988
|
-
source: "coinalyze",
|
|
2989
|
-
symbols,
|
|
3022
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
2990
3023
|
interval: window2.interval,
|
|
2991
3024
|
fromMs: window2.fromMs,
|
|
2992
|
-
toMs: window2.toMs
|
|
3025
|
+
toMs: window2.toMs,
|
|
3026
|
+
nowMs: coverageNowMs
|
|
2993
3027
|
});
|
|
3028
|
+
const [coverageRows, liquidationCoverageRows] = await Promise.all([
|
|
3029
|
+
(0, import_timescale2.getDerivativesBackfillCoverage)({
|
|
3030
|
+
source: "coinalyze",
|
|
3031
|
+
symbols,
|
|
3032
|
+
interval: window2.interval,
|
|
3033
|
+
fromMs: window2.fromMs,
|
|
3034
|
+
toMs: window2.toMs
|
|
3035
|
+
}),
|
|
3036
|
+
confirmedLiquidationWindow ? (0, import_timescale2.getDerivativesMetricCoverage)({
|
|
3037
|
+
source: "coinalyze",
|
|
3038
|
+
metric: "liquidation",
|
|
3039
|
+
symbols,
|
|
3040
|
+
interval: window2.interval,
|
|
3041
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
3042
|
+
toMs: confirmedLiquidationWindow.toMs
|
|
3043
|
+
}) : Promise.resolve([])
|
|
3044
|
+
]);
|
|
2994
3045
|
coverageKeysByInterval.set(
|
|
2995
3046
|
window2.interval,
|
|
2996
3047
|
new Set(
|
|
@@ -3012,6 +3063,17 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3012
3063
|
rangesBySymbol.set(symbol, ranges);
|
|
3013
3064
|
}
|
|
3014
3065
|
coverageRangesByInterval.set(window2.interval, rangesBySymbol);
|
|
3066
|
+
const liquidationRangesBySymbol = /* @__PURE__ */ new Map();
|
|
3067
|
+
for (const row of liquidationCoverageRows) {
|
|
3068
|
+
const symbol = row.symbol.toUpperCase();
|
|
3069
|
+
const ranges = liquidationRangesBySymbol.get(symbol) ?? [];
|
|
3070
|
+
ranges.push({ fromMs: row.fromMs, toMs: row.toMs });
|
|
3071
|
+
liquidationRangesBySymbol.set(symbol, ranges);
|
|
3072
|
+
}
|
|
3073
|
+
liquidationCoverageRangesByInterval.set(
|
|
3074
|
+
window2.interval,
|
|
3075
|
+
liquidationRangesBySymbol
|
|
3076
|
+
);
|
|
3015
3077
|
})
|
|
3016
3078
|
);
|
|
3017
3079
|
const cachedWindows = intervalWindows.reduce(
|
|
@@ -3036,7 +3098,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3036
3098
|
(symbol) => backfillWindows.every((backfillWindow) => {
|
|
3037
3099
|
const normalizedSymbol = symbol.toUpperCase();
|
|
3038
3100
|
const coverageRanges = coverageRangesByInterval.get(window2.interval)?.get(normalizedSymbol) ?? [];
|
|
3039
|
-
|
|
3101
|
+
const dataCovered = hasDerivativesWindowCoverage({
|
|
3040
3102
|
edges: edgesBySymbol?.get(normalizedSymbol),
|
|
3041
3103
|
fromMs: backfillWindow.fromMs,
|
|
3042
3104
|
toMs: backfillWindow.toMs
|
|
@@ -3053,6 +3115,19 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3053
3115
|
toMs: backfillWindow.toMs
|
|
3054
3116
|
})
|
|
3055
3117
|
);
|
|
3118
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
3119
|
+
interval: window2.interval,
|
|
3120
|
+
fromMs: backfillWindow.fromMs,
|
|
3121
|
+
toMs: backfillWindow.toMs,
|
|
3122
|
+
nowMs: coverageNowMs
|
|
3123
|
+
});
|
|
3124
|
+
const liquidationCovered = confirmedLiquidationWindow == null || resolveDerivativesContextMissingCoverageFetchFromMs({
|
|
3125
|
+
ranges: liquidationCoverageRangesByInterval.get(window2.interval)?.get(normalizedSymbol) ?? [],
|
|
3126
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
3127
|
+
toMs: confirmedLiquidationWindow.toMs,
|
|
3128
|
+
intervalMs: window2.intervalMs
|
|
3129
|
+
}) == null;
|
|
3130
|
+
return dataCovered && liquidationCovered;
|
|
3056
3131
|
})
|
|
3057
3132
|
);
|
|
3058
3133
|
});
|
|
@@ -3137,6 +3212,11 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3137
3212
|
coverageKeysByInterval.set(interval2, coverageKeys);
|
|
3138
3213
|
const coverageRangesBySymbol = coverageRangesByInterval.get(interval2) ?? /* @__PURE__ */ new Map();
|
|
3139
3214
|
coverageRangesByInterval.set(interval2, coverageRangesBySymbol);
|
|
3215
|
+
const liquidationCoverageRangesBySymbol = liquidationCoverageRangesByInterval.get(interval2) ?? /* @__PURE__ */ new Map();
|
|
3216
|
+
liquidationCoverageRangesByInterval.set(
|
|
3217
|
+
interval2,
|
|
3218
|
+
liquidationCoverageRangesBySymbol
|
|
3219
|
+
);
|
|
3140
3220
|
for (let batchIdx = 0; batchIdx < symbolBatches.length; batchIdx += 1) {
|
|
3141
3221
|
const batch = symbolBatches[batchIdx];
|
|
3142
3222
|
let cursor = window2.fromMs;
|
|
@@ -3149,33 +3229,25 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3149
3229
|
fromMs: cursor,
|
|
3150
3230
|
toMs
|
|
3151
3231
|
});
|
|
3152
|
-
if (coverageKeys.has(key)) {
|
|
3153
|
-
return null;
|
|
3154
|
-
}
|
|
3155
3232
|
const normalizedSymbol = item.symbol.toUpperCase();
|
|
3156
|
-
const
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
refreshClosedTail: mode === "signals"
|
|
3172
|
-
});
|
|
3173
|
-
if (edgesFromMs == null) {
|
|
3174
|
-
return null;
|
|
3175
|
-
}
|
|
3233
|
+
const requiredFromMs = resolveDerivativesContextRequiredFetchFromMs(
|
|
3234
|
+
{
|
|
3235
|
+
mode,
|
|
3236
|
+
interval: interval2,
|
|
3237
|
+
intervalMs,
|
|
3238
|
+
fromMs: cursor,
|
|
3239
|
+
toMs,
|
|
3240
|
+
nowMs: coverageNowMs,
|
|
3241
|
+
dataCoverageKeyExists: coverageKeys.has(key),
|
|
3242
|
+
dataCoverageRanges: coverageRangesBySymbol.get(normalizedSymbol),
|
|
3243
|
+
liquidationCoverageRanges: liquidationCoverageRangesBySymbol.get(normalizedSymbol),
|
|
3244
|
+
edges: edgesBySymbol.get(normalizedSymbol)
|
|
3245
|
+
}
|
|
3246
|
+
);
|
|
3247
|
+
if (requiredFromMs == null) return null;
|
|
3176
3248
|
return {
|
|
3177
3249
|
item,
|
|
3178
|
-
fromMs:
|
|
3250
|
+
fromMs: requiredFromMs
|
|
3179
3251
|
};
|
|
3180
3252
|
}).filter(
|
|
3181
3253
|
(item) => item != null
|
|
@@ -3200,6 +3272,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3200
3272
|
);
|
|
3201
3273
|
let rows = [];
|
|
3202
3274
|
let missingClosedSymbols = [];
|
|
3275
|
+
let liquidationRowsByMarket = /* @__PURE__ */ new Map();
|
|
3203
3276
|
for (let attempt = 1; attempt <= maxClosedBarAttempts; attempt += 1) {
|
|
3204
3277
|
const oiMap = await fetchMetricBatch({
|
|
3205
3278
|
endpoint: oiPath,
|
|
@@ -3219,7 +3292,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3219
3292
|
fromMs: group.fromMs,
|
|
3220
3293
|
toMs
|
|
3221
3294
|
});
|
|
3222
|
-
|
|
3295
|
+
liquidationRowsByMarket = await fetchMetricBatch({
|
|
3223
3296
|
endpoint: liqPath,
|
|
3224
3297
|
metric: "liq",
|
|
3225
3298
|
marketSymbols,
|
|
@@ -3234,7 +3307,7 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3234
3307
|
symbol: item.symbol,
|
|
3235
3308
|
oiRaw: oiMap.get(marketSymbol) ?? [],
|
|
3236
3309
|
fundingRaw: fundingMap.get(marketSymbol) ?? [],
|
|
3237
|
-
liqRaw:
|
|
3310
|
+
liqRaw: liquidationRowsByMarket.get(marketSymbol) ?? []
|
|
3238
3311
|
});
|
|
3239
3312
|
return (0, import_indicators.coinalyzePointsToRows)(points, interval2, "coinalyze");
|
|
3240
3313
|
});
|
|
@@ -3257,6 +3330,42 @@ var backfillDerivativesContext = async (params, enabled, mode) => {
|
|
|
3257
3330
|
await (0, import_timescale2.upsertDerivatives)(rows);
|
|
3258
3331
|
totalRows += rows.length;
|
|
3259
3332
|
}
|
|
3333
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
3334
|
+
interval: interval2,
|
|
3335
|
+
fromMs: group.fromMs,
|
|
3336
|
+
toMs,
|
|
3337
|
+
nowMs: coverageNowMs
|
|
3338
|
+
});
|
|
3339
|
+
if (confirmedLiquidationWindow) {
|
|
3340
|
+
const metricCoverageRows = missingBatch.map((item) => {
|
|
3341
|
+
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
3342
|
+
const eventRowsCount = (liquidationRowsByMarket.get(marketSymbol) ?? []).filter((point) => {
|
|
3343
|
+
const timestamp = (0, import_indicators.toCoinalyzeTimestampMs)(
|
|
3344
|
+
point.t ?? point.ts ?? point.time ?? point.timestamp
|
|
3345
|
+
);
|
|
3346
|
+
return timestamp != null && timestamp >= confirmedLiquidationWindow.fromMs && timestamp <= confirmedLiquidationWindow.toMs;
|
|
3347
|
+
}).length;
|
|
3348
|
+
return {
|
|
3349
|
+
source: "coinalyze",
|
|
3350
|
+
metric: "liquidation",
|
|
3351
|
+
symbol: item.symbol,
|
|
3352
|
+
interval: interval2,
|
|
3353
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
3354
|
+
toMs: confirmedLiquidationWindow.toMs,
|
|
3355
|
+
eventRowsCount
|
|
3356
|
+
};
|
|
3357
|
+
});
|
|
3358
|
+
await (0, import_timescale2.applyDerivativesMetricCoverage)(metricCoverageRows);
|
|
3359
|
+
for (const coverageRow of metricCoverageRows) {
|
|
3360
|
+
const symbol = coverageRow.symbol.toUpperCase();
|
|
3361
|
+
const ranges = liquidationCoverageRangesBySymbol.get(symbol) ?? [];
|
|
3362
|
+
ranges.push({
|
|
3363
|
+
fromMs: coverageRow.fromMs,
|
|
3364
|
+
toMs: coverageRow.toMs
|
|
3365
|
+
});
|
|
3366
|
+
liquidationCoverageRangesBySymbol.set(symbol, ranges);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3260
3369
|
if (mode === "backtest") {
|
|
3261
3370
|
const rowsCountBySymbol = /* @__PURE__ */ new Map();
|
|
3262
3371
|
for (const row of rows) {
|
|
@@ -378,6 +378,36 @@ var main = async () => {
|
|
|
378
378
|
await (0, import_timescale.upsertDerivatives)(rows);
|
|
379
379
|
totalRows += rows.length;
|
|
380
380
|
}
|
|
381
|
+
const confirmedLiquidationWindow = (0, import_indicators.resolveCoinalyzeConfirmedIntradayCoverage)({
|
|
382
|
+
interval,
|
|
383
|
+
fromMs: cursor,
|
|
384
|
+
toMs,
|
|
385
|
+
nowMs: now
|
|
386
|
+
});
|
|
387
|
+
if (confirmedLiquidationWindow) {
|
|
388
|
+
await (0, import_timescale.applyDerivativesMetricCoverage)(
|
|
389
|
+
batch.map((item) => {
|
|
390
|
+
const marketSymbol = item.marketSymbol.toUpperCase();
|
|
391
|
+
const eventRowsCount = (liqMap.get(marketSymbol) ?? []).filter(
|
|
392
|
+
(point) => {
|
|
393
|
+
const timestamp = (0, import_indicators.toCoinalyzeTimestampMs)(
|
|
394
|
+
point.t ?? point.ts ?? point.time ?? point.timestamp
|
|
395
|
+
);
|
|
396
|
+
return timestamp != null && timestamp >= confirmedLiquidationWindow.fromMs && timestamp <= confirmedLiquidationWindow.toMs;
|
|
397
|
+
}
|
|
398
|
+
).length;
|
|
399
|
+
return {
|
|
400
|
+
source: "coinalyze",
|
|
401
|
+
metric: "liquidation",
|
|
402
|
+
symbol: item.symbol,
|
|
403
|
+
interval,
|
|
404
|
+
fromMs: confirmedLiquidationWindow.fromMs,
|
|
405
|
+
toMs: confirmedLiquidationWindow.toMs,
|
|
406
|
+
eventRowsCount
|
|
407
|
+
};
|
|
408
|
+
})
|
|
409
|
+
);
|
|
410
|
+
}
|
|
381
411
|
} catch (error) {
|
|
382
412
|
failedWindows += 1;
|
|
383
413
|
console.error(
|
package/dist/scripts/mlExport.js
CHANGED
|
@@ -1697,7 +1697,8 @@ var getStrategyChoices = async () => {
|
|
|
1697
1697
|
"MaStrategy",
|
|
1698
1698
|
"AdaptiveMomentumRibbon",
|
|
1699
1699
|
"TrendLine",
|
|
1700
|
-
"VolumeDivergence"
|
|
1700
|
+
"VolumeDivergence",
|
|
1701
|
+
"Grid"
|
|
1701
1702
|
];
|
|
1702
1703
|
};
|
|
1703
1704
|
var selectStrategy = async (promptLabel = "Select strategy", options) => {
|