@tradejs/node 3.1.27-beta.250 → 3.1.28-beta.251
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/ai.js +1 -0
- package/dist/ai.mjs +1 -1
- package/dist/backtest.d.mts +3 -1
- package/dist/backtest.d.ts +3 -1
- package/dist/backtest.js +287 -39
- package/dist/backtest.mjs +30 -16
- package/dist/{chunk-NQO2MFP6.mjs → chunk-K2YQ3MQC.mjs} +58 -10
- package/dist/{chunk-FB5NUEOQ.mjs → chunk-OFVUEYUR.mjs} +4 -1
- package/dist/{chunk-IKRSNRP6.mjs → chunk-UITD6LG6.mjs} +83 -4
- package/dist/{chunk-XHNJ757K.mjs → chunk-VQSGH7YA.mjs} +341 -22
- package/dist/cli.js +2 -1
- package/dist/cli.mjs +1 -1
- package/dist/{registry-DHTLjQcr.d.mts → registry-3TsO1Ff1.d.mts} +2 -2
- package/dist/{registry-DHTLjQcr.d.ts → registry-3TsO1Ff1.d.ts} +2 -2
- package/dist/registry.d.mts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/registry.js +260 -23
- package/dist/registry.mjs +2 -2
- package/dist/runtimeDashboard.js +378 -37
- package/dist/runtimeDashboard.mjs +54 -8
- package/dist/runtimeStrategies.d.mts +4 -1
- package/dist/runtimeStrategies.d.ts +4 -1
- package/dist/runtimeStrategies.js +327 -34
- package/dist/runtimeStrategies.mjs +3 -3
- package/dist/runtimeTrades.d.mts +2 -1
- package/dist/runtimeTrades.d.ts +2 -1
- package/dist/runtimeTrades.js +4 -1
- package/dist/runtimeTrades.mjs +1 -1
- package/dist/strategies.d.mts +14 -2
- package/dist/strategies.d.ts +14 -2
- package/dist/strategies.js +417 -24
- package/dist/strategies.mjs +4 -2
- package/package.json +5 -5
package/dist/strategies.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from '@tradejs/core/strategies';
|
|
2
2
|
export { AiChatMessage, DEFAULT_AI_MODEL, InvokeAiChatOptions, MAX_AI_SERIES_POINTS, askAI, buildAiHumanPrompt, buildAiPayload, buildAiPrompts, buildAiSystemPrompt, buildCompactAiIndicatorsSnapshot, getDeterministicAiGateContext, getOpenRouterModelKwargs, invokeAiChat, resetAiRuntimeCache, runAiPrompt, runAiPromptLocal, trimSeriesDeep } from './ai.js';
|
|
3
|
-
export { e as ensureIndicatorPluginsLoaded, a as ensureStrategyPluginsLoaded, g as getAvailableStrategyNames, b as getRegisteredManifests, c as getRegisteredStrategies, d as getStrategyCreator, f as getStrategyDefaults, h as getStrategyManifest, i as getStrategyPluginSource, j as isKnownStrategy, r as registerStrategyEntries, k as resetStrategyRegistryCache, s as strategies } from './registry-
|
|
3
|
+
export { e as ensureIndicatorPluginsLoaded, a as ensureStrategyPluginsLoaded, g as getAvailableStrategyNames, b as getRegisteredManifests, c as getRegisteredStrategies, d as getStrategyCreator, f as getStrategyDefaults, h as getStrategyManifest, i as getStrategyPluginSource, j as isKnownStrategy, r as registerStrategyEntries, k as resetStrategyRegistryCache, s as strategies } from './registry-3TsO1Ff1.js';
|
|
4
4
|
import { StrategyConfig, CreateStrategyCore, StrategyManifest, StrategyCreator, RuntimeStrategyConfigSnapshot, Signal, Direction, StrategyRuntimeMlOptions, StrategyRuntimeAiOptions, Connector, Tp, MarketFeatureInterval, StrategyEntrySignalContext } from '@tradejs/types';
|
|
5
5
|
import { TradejsConfigOnBarHook, TradejsConfigBeforeSignalsHook } from '@tradejs/core/config';
|
|
6
6
|
|
|
@@ -79,6 +79,18 @@ declare const validateEntryProtectionAtArrival: ({ direction, signalPrice, bid,
|
|
|
79
79
|
}) => void;
|
|
80
80
|
declare const executeEntryOrder: ({ connector, userName, symbol, direction, qty, currentPrice, timestamp, takeProfits, stopLossPrice, positionIntent, signal, beforePlaceOrder, recordRuntimeTrade, leverage, }: ExecuteEntryOrderParams) => Promise<number>;
|
|
81
81
|
|
|
82
|
+
declare const preloadBinanceMarketContextForWindow: (params: {
|
|
83
|
+
startMs: number;
|
|
84
|
+
endMs: number;
|
|
85
|
+
interval: MarketFeatureInterval;
|
|
86
|
+
maxAgeMs?: number;
|
|
87
|
+
timeoutMs?: number;
|
|
88
|
+
chunkMs?: number;
|
|
89
|
+
abortSignal?: AbortSignal;
|
|
90
|
+
}) => Promise<{
|
|
91
|
+
tradeFlowRows: number;
|
|
92
|
+
breadthRows: number;
|
|
93
|
+
}>;
|
|
82
94
|
declare const enrichSignalWithBinanceMarketContext: (params: {
|
|
83
95
|
signal: Signal;
|
|
84
96
|
env: string;
|
|
@@ -200,4 +212,4 @@ interface CreateCloseAllOnGlobalProfitBeforeSignalsHookParams {
|
|
|
200
212
|
}
|
|
201
213
|
declare const createCloseAllOnGlobalProfitBeforeSignalsHook: ({ getStrategyDefaultConfig, profitRiskMultiplier, }?: CreateCloseAllOnGlobalProfitBeforeSignalsHookParams) => TradejsConfigBeforeSignalsHook;
|
|
202
214
|
|
|
203
|
-
export { BINANCE_BREADTH_UNIVERSE_KEYS, type BinanceBreadthUniverseDefinition, type BinanceBreadthUniverseKey, type BinanceBreadthUniverseSnapshot, type HyperliquidPerpUniverseSnapshot, type HyperliquidWhaleRegistrySnapshot, buildBinanceBreadthUniverseSnapshot, closeOppositePositionsBeforeOpen, createCloseAllOnGlobalProfitBeforeSignalsHook, createCloseOppositeBeforePlaceOrderHook, createMoveStopToBreakEvenAfterCoreDecisionHook, createMoveStopToBreakEvenOnBarHook, createStrategyRuntime, enrichSignalWithAi, enrichSignalWithBinanceMarketContext, enrichSignalWithCoinMarketCapContext, enrichSignalWithHyperliquidWhaleContext, enrichSignalWithMl, enrichSignalWithMlAi, executeEntryOrder, getBinanceBreadthUniverseSnapshot, getBinanceBreadthUniverses, getHyperliquidPerpSymbols, getHyperliquidPerpUniverseSnapshot, getHyperliquidWhaleAddresses, getHyperliquidWhaleRegistrySnapshot, getOrderArrivalSnapshot, getPrimaryBinanceBreadthUniverse, isTrackedHyperliquidPerp, isTrackedHyperliquidWhale, resolveHyperliquidPerpFromSignalSymbol, resolveStrategyConfig, validateEntryProtectionAtArrival };
|
|
215
|
+
export { BINANCE_BREADTH_UNIVERSE_KEYS, type BinanceBreadthUniverseDefinition, type BinanceBreadthUniverseKey, type BinanceBreadthUniverseSnapshot, type HyperliquidPerpUniverseSnapshot, type HyperliquidWhaleRegistrySnapshot, buildBinanceBreadthUniverseSnapshot, closeOppositePositionsBeforeOpen, createCloseAllOnGlobalProfitBeforeSignalsHook, createCloseOppositeBeforePlaceOrderHook, createMoveStopToBreakEvenAfterCoreDecisionHook, createMoveStopToBreakEvenOnBarHook, createStrategyRuntime, enrichSignalWithAi, enrichSignalWithBinanceMarketContext, enrichSignalWithCoinMarketCapContext, enrichSignalWithHyperliquidWhaleContext, enrichSignalWithMl, enrichSignalWithMlAi, executeEntryOrder, getBinanceBreadthUniverseSnapshot, getBinanceBreadthUniverses, getHyperliquidPerpSymbols, getHyperliquidPerpUniverseSnapshot, getHyperliquidWhaleAddresses, getHyperliquidWhaleRegistrySnapshot, getOrderArrivalSnapshot, getPrimaryBinanceBreadthUniverse, isTrackedHyperliquidPerp, isTrackedHyperliquidWhale, preloadBinanceMarketContextForWindow, resolveHyperliquidPerpFromSignalSymbol, resolveStrategyConfig, validateEntryProtectionAtArrival };
|
package/dist/strategies.js
CHANGED
|
@@ -77,6 +77,7 @@ __export(strategies_exports, {
|
|
|
77
77
|
isKnownStrategy: () => isKnownStrategy,
|
|
78
78
|
isTrackedHyperliquidPerp: () => isTrackedHyperliquidPerp,
|
|
79
79
|
isTrackedHyperliquidWhale: () => isTrackedHyperliquidWhale,
|
|
80
|
+
preloadBinanceMarketContextForWindow: () => preloadBinanceMarketContextForWindow,
|
|
80
81
|
registerStrategyEntries: () => registerStrategyEntries,
|
|
81
82
|
resetAiRuntimeCache: () => resetAiRuntimeCache,
|
|
82
83
|
resetStrategyRegistryCache: () => resetStrategyRegistryCache,
|
|
@@ -968,6 +969,7 @@ var createStrategyRegistryState = () => ({
|
|
|
968
969
|
strategyManifestsMap: /* @__PURE__ */ new Map(),
|
|
969
970
|
strategyEntriesMap: /* @__PURE__ */ new Map(),
|
|
970
971
|
strategySourcesMap: /* @__PURE__ */ new Map(),
|
|
972
|
+
strategyModuleResolutions: /* @__PURE__ */ new Map(),
|
|
971
973
|
pluginsLoadPromise: null
|
|
972
974
|
});
|
|
973
975
|
var registryStateByProjectRoot = sharedStrategyRegistry.registryStateByProjectRoot;
|
|
@@ -1029,7 +1031,7 @@ var validateStrategyEntries = (moduleName, entries, state) => {
|
|
|
1029
1031
|
const strategyName = entry?.manifest?.name;
|
|
1030
1032
|
if (typeof strategyName !== "string" || !strategyName.trim()) {
|
|
1031
1033
|
issues.push(`${entryPath}: manifest.name is required`);
|
|
1032
|
-
} else if (names.has(strategyName) || state
|
|
1034
|
+
} else if (names.has(strategyName) || state?.strategyEntriesMap.has(strategyName)) {
|
|
1033
1035
|
issues.push(`${entryPath}: duplicate strategy ${strategyName}`);
|
|
1034
1036
|
} else {
|
|
1035
1037
|
names.add(strategyName);
|
|
@@ -1091,6 +1093,72 @@ var importStrategyPluginModule = async (moduleName, cwd = getTradejsProjectCwd()
|
|
|
1091
1093
|
moduleName
|
|
1092
1094
|
);
|
|
1093
1095
|
};
|
|
1096
|
+
var resolveStrategyModuleEntry = async ({
|
|
1097
|
+
strategyName,
|
|
1098
|
+
moduleName,
|
|
1099
|
+
cwd
|
|
1100
|
+
}) => {
|
|
1101
|
+
const { projectRoot, state } = getStrategyRegistryState(cwd);
|
|
1102
|
+
const source = moduleName.trim();
|
|
1103
|
+
const resolvedModuleName = resolvePluginModuleSpecifier(source, projectRoot);
|
|
1104
|
+
const cacheKey = `${resolvedModuleName}\0${strategyName}`;
|
|
1105
|
+
const cached = state.strategyModuleResolutions.get(cacheKey);
|
|
1106
|
+
if (cached) return cached;
|
|
1107
|
+
const resolution = (async () => {
|
|
1108
|
+
const moduleExport = await importStrategyPluginModule(
|
|
1109
|
+
resolvedModuleName,
|
|
1110
|
+
projectRoot
|
|
1111
|
+
);
|
|
1112
|
+
const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
|
|
1113
|
+
if (!pluginDefinition) {
|
|
1114
|
+
throw new Error(`${source}: export { strategyEntries } is missing`);
|
|
1115
|
+
}
|
|
1116
|
+
const issues = validateStrategyEntries(
|
|
1117
|
+
source,
|
|
1118
|
+
pluginDefinition.strategyEntries
|
|
1119
|
+
);
|
|
1120
|
+
if (issues.length > 0) {
|
|
1121
|
+
throw new Error(
|
|
1122
|
+
["Invalid TradeJS strategy module:", ...issues].join("\n")
|
|
1123
|
+
);
|
|
1124
|
+
}
|
|
1125
|
+
const entry = pluginDefinition.strategyEntries.find(
|
|
1126
|
+
(candidate) => candidate.manifest.name === strategyName
|
|
1127
|
+
);
|
|
1128
|
+
if (!entry) {
|
|
1129
|
+
throw new Error(`${source}: strategy ${strategyName} is missing`);
|
|
1130
|
+
}
|
|
1131
|
+
const factory = sharedStrategyRegistry.strategyRuntimeFactory;
|
|
1132
|
+
if (!factory) {
|
|
1133
|
+
throw new Error("Strategy runtime factory is not configured");
|
|
1134
|
+
}
|
|
1135
|
+
const manifestsByName = new Map(
|
|
1136
|
+
pluginDefinition.strategyEntries.map(
|
|
1137
|
+
(candidate) => [candidate.manifest.name, candidate.manifest]
|
|
1138
|
+
)
|
|
1139
|
+
);
|
|
1140
|
+
return {
|
|
1141
|
+
entry,
|
|
1142
|
+
creator: factory({
|
|
1143
|
+
strategyName,
|
|
1144
|
+
defaults: entry.defaults,
|
|
1145
|
+
createCore: entry.createCore,
|
|
1146
|
+
manifest: entry.manifest,
|
|
1147
|
+
detectorKey: entry.detectorKey,
|
|
1148
|
+
detectorNoSignalSkipReason: entry.detectorNoSignalSkipReason,
|
|
1149
|
+
resolveRegisteredManifest: (name) => manifestsByName.get(name) ?? state.strategyManifestsMap.get(name)
|
|
1150
|
+
}),
|
|
1151
|
+
source
|
|
1152
|
+
};
|
|
1153
|
+
})();
|
|
1154
|
+
state.strategyModuleResolutions.set(cacheKey, resolution);
|
|
1155
|
+
try {
|
|
1156
|
+
return await resolution;
|
|
1157
|
+
} catch (error) {
|
|
1158
|
+
state.strategyModuleResolutions.delete(cacheKey);
|
|
1159
|
+
throw error;
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1094
1162
|
var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
1095
1163
|
const { projectRoot, state } = getStrategyRegistryState(cwd);
|
|
1096
1164
|
if (!state.pluginsLoadPromise) {
|
|
@@ -1169,7 +1237,11 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
1169
1237
|
await state.pluginsLoadPromise;
|
|
1170
1238
|
};
|
|
1171
1239
|
var ensureIndicatorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => ensureStrategyPluginsLoaded(cwd);
|
|
1172
|
-
var getStrategyCreator = async (name, cwd = getTradejsProjectCwd()) => {
|
|
1240
|
+
var getStrategyCreator = async (name, cwd = getTradejsProjectCwd(), moduleName) => {
|
|
1241
|
+
if (moduleName?.trim()) {
|
|
1242
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
1243
|
+
return (await resolveStrategyModuleEntry({ strategyName: name, moduleName, cwd })).creator;
|
|
1244
|
+
}
|
|
1173
1245
|
await ensureStrategyPluginsLoaded(cwd);
|
|
1174
1246
|
const { state } = getStrategyRegistryState(cwd);
|
|
1175
1247
|
return state.strategyCreators.get(name);
|
|
@@ -1179,7 +1251,11 @@ var getStrategyDefaults = async (name, cwd = getTradejsProjectCwd()) => {
|
|
|
1179
1251
|
const { state } = getStrategyRegistryState(cwd);
|
|
1180
1252
|
return state.strategyEntriesMap.get(name)?.defaults;
|
|
1181
1253
|
};
|
|
1182
|
-
var getStrategyPluginSource = async (name, cwd = getTradejsProjectCwd()) => {
|
|
1254
|
+
var getStrategyPluginSource = async (name, cwd = getTradejsProjectCwd(), moduleName) => {
|
|
1255
|
+
if (moduleName?.trim()) {
|
|
1256
|
+
await ensureStrategyPluginsLoaded(cwd);
|
|
1257
|
+
return (await resolveStrategyModuleEntry({ strategyName: name, moduleName, cwd })).source;
|
|
1258
|
+
}
|
|
1183
1259
|
await ensureStrategyPluginsLoaded(cwd);
|
|
1184
1260
|
const { state } = getStrategyRegistryState(cwd);
|
|
1185
1261
|
return state.strategySourcesMap.get(name);
|
|
@@ -2462,9 +2538,50 @@ var DEFAULT_MAX_AGE_BY_INTERVAL = {
|
|
|
2462
2538
|
"15m": 30 * 6e4,
|
|
2463
2539
|
"1h": 2 * 60 * 6e4
|
|
2464
2540
|
};
|
|
2541
|
+
var MARKET_CONTEXT_PRELOAD_CHUNK_MS = 7 * 24 * 60 * 6e4;
|
|
2465
2542
|
var binanceMarketContextUnavailable = false;
|
|
2466
2543
|
var referenceRowsCache = /* @__PURE__ */ new Map();
|
|
2467
2544
|
var breadthCache = /* @__PURE__ */ new Map();
|
|
2545
|
+
var TRADE_FLOW_NUMERIC_FIELDS = [
|
|
2546
|
+
"trades",
|
|
2547
|
+
"buyBaseVolume",
|
|
2548
|
+
"sellBaseVolume",
|
|
2549
|
+
"buyQuoteVolume",
|
|
2550
|
+
"sellQuoteVolume",
|
|
2551
|
+
"netBaseDelta",
|
|
2552
|
+
"netQuoteDelta",
|
|
2553
|
+
"buyPressurePct"
|
|
2554
|
+
];
|
|
2555
|
+
var BREADTH_COMMON_NUMERIC_FIELDS = [
|
|
2556
|
+
"symbolsCount",
|
|
2557
|
+
"advancers",
|
|
2558
|
+
"decliners",
|
|
2559
|
+
"unchanged",
|
|
2560
|
+
"advanceDeclineRatio",
|
|
2561
|
+
"pctAboveMa20",
|
|
2562
|
+
"pctAboveMa50",
|
|
2563
|
+
"equalWeightedReturn",
|
|
2564
|
+
"volumeWeightedReturn",
|
|
2565
|
+
"dispersion"
|
|
2566
|
+
];
|
|
2567
|
+
var BREADTH_REGIME_NUMERIC_FIELDS = [
|
|
2568
|
+
"btcReturn1h",
|
|
2569
|
+
"btcReturn4h",
|
|
2570
|
+
"btcReturn24h",
|
|
2571
|
+
"altBasketReturn1h",
|
|
2572
|
+
"altBasketReturn4h",
|
|
2573
|
+
"altBasketReturn24h",
|
|
2574
|
+
"btcVsAltReturn1h",
|
|
2575
|
+
"btcVsAltReturn4h",
|
|
2576
|
+
"btcVsAltReturn24h",
|
|
2577
|
+
"btcTurnoverShare1h",
|
|
2578
|
+
"btcTurnoverShare24h",
|
|
2579
|
+
"btcTurnoverShareChange24h",
|
|
2580
|
+
"altVolToBtcVol24h",
|
|
2581
|
+
"altDispersion24h"
|
|
2582
|
+
];
|
|
2583
|
+
var preloadedTradeFlowBySymbol = null;
|
|
2584
|
+
var preloadedBreadthByUniverse = null;
|
|
2468
2585
|
var parseEnabledFlag = (value, env) => {
|
|
2469
2586
|
const normalized = String(value ?? "").trim().toLowerCase();
|
|
2470
2587
|
if (!normalized)
|
|
@@ -2500,6 +2617,240 @@ var hasBaseContext = (signal) => Boolean(
|
|
|
2500
2617
|
signal.additionalIndicators?.baseContext && typeof signal.additionalIndicators.baseContext === "object" && !Array.isArray(signal.additionalIndicators.baseContext)
|
|
2501
2618
|
);
|
|
2502
2619
|
var isBinanceMarketContextEnabled = (env) => parseEnabledFlag(process.env.BINANCE_MARKET_CONTEXT_ENABLED, env);
|
|
2620
|
+
var latestIndexAtOrBefore = (timestamps, timestamp) => {
|
|
2621
|
+
if (!timestamps?.length) return -1;
|
|
2622
|
+
let low = 0;
|
|
2623
|
+
let high = timestamps.length - 1;
|
|
2624
|
+
let match = -1;
|
|
2625
|
+
while (low <= high) {
|
|
2626
|
+
const middle = Math.floor((low + high) / 2);
|
|
2627
|
+
const rowTimestamp = timestamps[middle];
|
|
2628
|
+
if (rowTimestamp == null) break;
|
|
2629
|
+
if (rowTimestamp <= timestamp) {
|
|
2630
|
+
match = middle;
|
|
2631
|
+
low = middle + 1;
|
|
2632
|
+
} else {
|
|
2633
|
+
high = middle - 1;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
return match;
|
|
2637
|
+
};
|
|
2638
|
+
var latestChunkAtOrBefore = (chunks, timestamp) => {
|
|
2639
|
+
if (!chunks?.length) return null;
|
|
2640
|
+
let low = 0;
|
|
2641
|
+
let high = chunks.length - 1;
|
|
2642
|
+
let match = null;
|
|
2643
|
+
while (low <= high) {
|
|
2644
|
+
const middle = Math.floor((low + high) / 2);
|
|
2645
|
+
const chunk = chunks[middle];
|
|
2646
|
+
const firstTimestamp = chunk?.timestamps[0];
|
|
2647
|
+
if (!chunk || firstTimestamp == null) break;
|
|
2648
|
+
if (firstTimestamp <= timestamp) {
|
|
2649
|
+
match = chunk;
|
|
2650
|
+
low = middle + 1;
|
|
2651
|
+
} else {
|
|
2652
|
+
high = middle - 1;
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
return match;
|
|
2656
|
+
};
|
|
2657
|
+
var createNumericColumns = (fields, length) => Object.fromEntries(
|
|
2658
|
+
fields.map((field) => [field, new Float64Array(length)])
|
|
2659
|
+
);
|
|
2660
|
+
var packedNumber = (value) => {
|
|
2661
|
+
const numeric = typeof value === "number" ? value : Number(value);
|
|
2662
|
+
return Number.isFinite(numeric) ? numeric : Number.NaN;
|
|
2663
|
+
};
|
|
2664
|
+
var unpackedNumber = (value) => value == null || Number.isNaN(value) ? null : value;
|
|
2665
|
+
var packTradeFlowRows = (rows) => {
|
|
2666
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2667
|
+
for (const row of rows) {
|
|
2668
|
+
counts.set(row.symbol, (counts.get(row.symbol) ?? 0) + 1);
|
|
2669
|
+
}
|
|
2670
|
+
const packed = /* @__PURE__ */ new Map();
|
|
2671
|
+
for (const [symbol, length] of counts) {
|
|
2672
|
+
packed.set(symbol, {
|
|
2673
|
+
symbol,
|
|
2674
|
+
interval: rows.find((row) => row.symbol === symbol)?.interval ?? "15m",
|
|
2675
|
+
timestamps: new Float64Array(length),
|
|
2676
|
+
columns: createNumericColumns(TRADE_FLOW_NUMERIC_FIELDS, length)
|
|
2677
|
+
});
|
|
2678
|
+
}
|
|
2679
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
2680
|
+
for (const row of rows) {
|
|
2681
|
+
const target = packed.get(row.symbol);
|
|
2682
|
+
if (!target) continue;
|
|
2683
|
+
const index = offsets.get(row.symbol) ?? 0;
|
|
2684
|
+
target.timestamps[index] = row.ts.getTime();
|
|
2685
|
+
for (const field of TRADE_FLOW_NUMERIC_FIELDS) {
|
|
2686
|
+
target.columns[field][index] = packedNumber(row[field]);
|
|
2687
|
+
}
|
|
2688
|
+
offsets.set(row.symbol, index + 1);
|
|
2689
|
+
}
|
|
2690
|
+
return packed;
|
|
2691
|
+
};
|
|
2692
|
+
var packBreadthRows = (rows, primaryUniverse) => {
|
|
2693
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2694
|
+
for (const row of rows) {
|
|
2695
|
+
counts.set(row.universe, (counts.get(row.universe) ?? 0) + 1);
|
|
2696
|
+
}
|
|
2697
|
+
const packed = /* @__PURE__ */ new Map();
|
|
2698
|
+
for (const [universe, length] of counts) {
|
|
2699
|
+
packed.set(universe, {
|
|
2700
|
+
universe,
|
|
2701
|
+
interval: rows.find((row) => row.universe === universe)?.interval ?? "15m",
|
|
2702
|
+
timestamps: new Float64Array(length),
|
|
2703
|
+
commonColumns: createNumericColumns(
|
|
2704
|
+
BREADTH_COMMON_NUMERIC_FIELDS,
|
|
2705
|
+
length
|
|
2706
|
+
),
|
|
2707
|
+
...universe === primaryUniverse ? {
|
|
2708
|
+
regimeColumns: createNumericColumns(
|
|
2709
|
+
BREADTH_REGIME_NUMERIC_FIELDS,
|
|
2710
|
+
length
|
|
2711
|
+
),
|
|
2712
|
+
regimes: new Array(length)
|
|
2713
|
+
} : {}
|
|
2714
|
+
});
|
|
2715
|
+
}
|
|
2716
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
2717
|
+
for (const row of rows) {
|
|
2718
|
+
const target = packed.get(row.universe);
|
|
2719
|
+
if (!target) continue;
|
|
2720
|
+
const index = offsets.get(row.universe) ?? 0;
|
|
2721
|
+
target.timestamps[index] = row.ts.getTime();
|
|
2722
|
+
for (const field of BREADTH_COMMON_NUMERIC_FIELDS) {
|
|
2723
|
+
target.commonColumns[field][index] = packedNumber(row[field]);
|
|
2724
|
+
}
|
|
2725
|
+
if (target.regimeColumns) {
|
|
2726
|
+
for (const field of BREADTH_REGIME_NUMERIC_FIELDS) {
|
|
2727
|
+
target.regimeColumns[field][index] = packedNumber(row[field]);
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
if (target.regimes) target.regimes[index] = row.btcAltRegime;
|
|
2731
|
+
offsets.set(row.universe, index + 1);
|
|
2732
|
+
}
|
|
2733
|
+
return packed;
|
|
2734
|
+
};
|
|
2735
|
+
var appendPackedChunks = (target, source) => {
|
|
2736
|
+
for (const [key, rows] of source) {
|
|
2737
|
+
const chunks = target.get(key) ?? [];
|
|
2738
|
+
chunks.push(rows);
|
|
2739
|
+
target.set(key, chunks);
|
|
2740
|
+
}
|
|
2741
|
+
};
|
|
2742
|
+
var unpackTradeFlowRow = (chunks, timestamp) => {
|
|
2743
|
+
const rows = latestChunkAtOrBefore(chunks, timestamp);
|
|
2744
|
+
const index = latestIndexAtOrBefore(rows?.timestamps, timestamp);
|
|
2745
|
+
if (!rows || index < 0) return null;
|
|
2746
|
+
return {
|
|
2747
|
+
symbol: rows.symbol,
|
|
2748
|
+
interval: rows.interval,
|
|
2749
|
+
ts: new Date(rows.timestamps[index]),
|
|
2750
|
+
trades: unpackedNumber(rows.columns.trades[index]) ?? 0,
|
|
2751
|
+
buyBaseVolume: unpackedNumber(rows.columns.buyBaseVolume[index]),
|
|
2752
|
+
sellBaseVolume: unpackedNumber(rows.columns.sellBaseVolume[index]),
|
|
2753
|
+
buyQuoteVolume: unpackedNumber(rows.columns.buyQuoteVolume[index]),
|
|
2754
|
+
sellQuoteVolume: unpackedNumber(rows.columns.sellQuoteVolume[index]),
|
|
2755
|
+
netBaseDelta: unpackedNumber(rows.columns.netBaseDelta[index]),
|
|
2756
|
+
netQuoteDelta: unpackedNumber(rows.columns.netQuoteDelta[index]),
|
|
2757
|
+
buyPressurePct: unpackedNumber(rows.columns.buyPressurePct[index])
|
|
2758
|
+
};
|
|
2759
|
+
};
|
|
2760
|
+
var unpackBreadthRow = (chunks, timestamp) => {
|
|
2761
|
+
const rows = latestChunkAtOrBefore(chunks, timestamp);
|
|
2762
|
+
const index = latestIndexAtOrBefore(rows?.timestamps, timestamp);
|
|
2763
|
+
if (!rows || index < 0) return null;
|
|
2764
|
+
const commonNumeric = Object.fromEntries(
|
|
2765
|
+
BREADTH_COMMON_NUMERIC_FIELDS.map((field) => [
|
|
2766
|
+
field,
|
|
2767
|
+
unpackedNumber(rows.commonColumns[field][index])
|
|
2768
|
+
])
|
|
2769
|
+
);
|
|
2770
|
+
const regimeNumeric = Object.fromEntries(
|
|
2771
|
+
BREADTH_REGIME_NUMERIC_FIELDS.map((field) => [
|
|
2772
|
+
field,
|
|
2773
|
+
unpackedNumber(rows.regimeColumns?.[field][index])
|
|
2774
|
+
])
|
|
2775
|
+
);
|
|
2776
|
+
return {
|
|
2777
|
+
universe: rows.universe,
|
|
2778
|
+
interval: rows.interval,
|
|
2779
|
+
ts: new Date(rows.timestamps[index]),
|
|
2780
|
+
...commonNumeric,
|
|
2781
|
+
...regimeNumeric,
|
|
2782
|
+
symbolsCount: commonNumeric.symbolsCount ?? 0,
|
|
2783
|
+
advancers: commonNumeric.advancers ?? 0,
|
|
2784
|
+
decliners: commonNumeric.decliners ?? 0,
|
|
2785
|
+
unchanged: commonNumeric.unchanged ?? 0,
|
|
2786
|
+
btcAltRegime: rows.regimes?.[index] ?? null
|
|
2787
|
+
};
|
|
2788
|
+
};
|
|
2789
|
+
var toAsOfRow = (row, timestamp, maxAgeMs) => {
|
|
2790
|
+
if (!row) return null;
|
|
2791
|
+
const ageMs = timestamp - row.ts.getTime();
|
|
2792
|
+
return {
|
|
2793
|
+
...row,
|
|
2794
|
+
ageMs: Number.isFinite(ageMs) ? ageMs : null,
|
|
2795
|
+
stale: !Number.isFinite(ageMs) || ageMs < 0 || ageMs > maxAgeMs
|
|
2796
|
+
};
|
|
2797
|
+
};
|
|
2798
|
+
var preloadBinanceMarketContextForWindow = async (params) => {
|
|
2799
|
+
const maxAgeMs = params.maxAgeMs ?? DEFAULT_MAX_AGE_BY_INTERVAL[params.interval];
|
|
2800
|
+
const referenceSymbols = getReferenceSymbols();
|
|
2801
|
+
const breadthDefinitions = getBinanceBreadthUniverses();
|
|
2802
|
+
const breadthUniverses = breadthDefinitions.map(({ universe }) => universe);
|
|
2803
|
+
const primaryBreadthUniverse = breadthDefinitions.find(
|
|
2804
|
+
({ key }) => key === "top30"
|
|
2805
|
+
).universe;
|
|
2806
|
+
const timeoutMs = params.timeoutMs ?? 5 * 6e4;
|
|
2807
|
+
const chunkMs = params.chunkMs ?? MARKET_CONTEXT_PRELOAD_CHUNK_MS;
|
|
2808
|
+
if (!Number.isSafeInteger(chunkMs) || chunkMs <= 0) {
|
|
2809
|
+
throw new Error(`Invalid market context preload chunk: ${chunkMs}`);
|
|
2810
|
+
}
|
|
2811
|
+
const packedTradeFlow = /* @__PURE__ */ new Map();
|
|
2812
|
+
const packedBreadth = /* @__PURE__ */ new Map();
|
|
2813
|
+
let tradeFlowRowsCount = 0;
|
|
2814
|
+
let breadthRowsCount = 0;
|
|
2815
|
+
let fromMs = params.startMs - maxAgeMs;
|
|
2816
|
+
while (fromMs <= params.endMs) {
|
|
2817
|
+
const toMs = Math.min(params.endMs, fromMs + chunkMs - 1);
|
|
2818
|
+
const [tradeFlowRows, breadthRows] = await Promise.all([
|
|
2819
|
+
(0, import_marketContext.getMarketTradeFlowRows)({
|
|
2820
|
+
symbols: referenceSymbols,
|
|
2821
|
+
interval: params.interval,
|
|
2822
|
+
fromMs,
|
|
2823
|
+
toMs,
|
|
2824
|
+
timeoutMs,
|
|
2825
|
+
...params.abortSignal ? { signal: params.abortSignal } : {}
|
|
2826
|
+
}),
|
|
2827
|
+
(0, import_marketContext.getMarketBreadthRows)({
|
|
2828
|
+
universes: breadthUniverses,
|
|
2829
|
+
interval: params.interval,
|
|
2830
|
+
fromMs,
|
|
2831
|
+
toMs,
|
|
2832
|
+
timeoutMs,
|
|
2833
|
+
...params.abortSignal ? { signal: params.abortSignal } : {}
|
|
2834
|
+
})
|
|
2835
|
+
]);
|
|
2836
|
+
tradeFlowRowsCount += tradeFlowRows.length;
|
|
2837
|
+
breadthRowsCount += breadthRows.length;
|
|
2838
|
+
appendPackedChunks(packedTradeFlow, packTradeFlowRows(tradeFlowRows));
|
|
2839
|
+
appendPackedChunks(
|
|
2840
|
+
packedBreadth,
|
|
2841
|
+
packBreadthRows(breadthRows, primaryBreadthUniverse)
|
|
2842
|
+
);
|
|
2843
|
+
fromMs = toMs + 1;
|
|
2844
|
+
}
|
|
2845
|
+
preloadedTradeFlowBySymbol = packedTradeFlow;
|
|
2846
|
+
preloadedBreadthByUniverse = packedBreadth;
|
|
2847
|
+
referenceRowsCache.clear();
|
|
2848
|
+
breadthCache.clear();
|
|
2849
|
+
return {
|
|
2850
|
+
tradeFlowRows: tradeFlowRowsCount,
|
|
2851
|
+
breadthRows: breadthRowsCount
|
|
2852
|
+
};
|
|
2853
|
+
};
|
|
2503
2854
|
var toTradeFlowContext = (row, interval) => row ? {
|
|
2504
2855
|
source: "binance_agg_trades",
|
|
2505
2856
|
interval,
|
|
@@ -2522,6 +2873,24 @@ var getCachedReferenceRows = ({
|
|
|
2522
2873
|
maxAgeMs,
|
|
2523
2874
|
abortSignal
|
|
2524
2875
|
}) => {
|
|
2876
|
+
if (preloadedTradeFlowBySymbol) {
|
|
2877
|
+
return Promise.resolve(
|
|
2878
|
+
referenceSymbols.map((symbol) => ({
|
|
2879
|
+
symbol,
|
|
2880
|
+
tradeFlow: toTradeFlowContext(
|
|
2881
|
+
toAsOfRow(
|
|
2882
|
+
unpackTradeFlowRow(
|
|
2883
|
+
preloadedTradeFlowBySymbol?.get(symbol),
|
|
2884
|
+
timestamp
|
|
2885
|
+
),
|
|
2886
|
+
timestamp,
|
|
2887
|
+
maxAgeMs
|
|
2888
|
+
),
|
|
2889
|
+
interval
|
|
2890
|
+
)
|
|
2891
|
+
}))
|
|
2892
|
+
);
|
|
2893
|
+
}
|
|
2525
2894
|
const key = `${referenceSymbols.join(",")}:${interval}:${timestamp}:${maxAgeMs}`;
|
|
2526
2895
|
const cached = referenceRowsCache.get(key);
|
|
2527
2896
|
if (cached) return cached;
|
|
@@ -2551,6 +2920,18 @@ var getCachedBreadth = ({
|
|
|
2551
2920
|
maxAgeMs,
|
|
2552
2921
|
abortSignal
|
|
2553
2922
|
}) => {
|
|
2923
|
+
if (preloadedBreadthByUniverse) {
|
|
2924
|
+
return Promise.resolve(
|
|
2925
|
+
toAsOfRow(
|
|
2926
|
+
unpackBreadthRow(
|
|
2927
|
+
preloadedBreadthByUniverse.get(breadthUniverse),
|
|
2928
|
+
timestamp
|
|
2929
|
+
),
|
|
2930
|
+
timestamp,
|
|
2931
|
+
maxAgeMs
|
|
2932
|
+
)
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2554
2935
|
const key = `${breadthUniverse}:${interval}:${timestamp}:${maxAgeMs}`;
|
|
2555
2936
|
const cached = breadthCache.get(key);
|
|
2556
2937
|
if (cached) return cached;
|
|
@@ -2757,12 +3138,20 @@ var SOURCE_EXCHANGE_LIQUIDITY = "coinmarketcap_exchange_liquidity";
|
|
|
2757
3138
|
var SOURCE_FEAR_GREED = "coinmarketcap_fear_greed";
|
|
2758
3139
|
var SOURCE_INDEX = "coinmarketcap_index";
|
|
2759
3140
|
var DAY_MS = 864e5;
|
|
3141
|
+
var MAX_TIMESTAMP_CACHE_ENTRIES = 512;
|
|
2760
3142
|
var coinMarketCapContextUnavailable = false;
|
|
2761
3143
|
var globalContextCache = /* @__PURE__ */ new Map();
|
|
2762
3144
|
var referenceContextCache = /* @__PURE__ */ new Map();
|
|
2763
3145
|
var exchangeLiquidityContextCache = /* @__PURE__ */ new Map();
|
|
2764
3146
|
var fearGreedContextCache = /* @__PURE__ */ new Map();
|
|
2765
3147
|
var indexContextCache = /* @__PURE__ */ new Map();
|
|
3148
|
+
var setBoundedCache = (cache, key, value) => {
|
|
3149
|
+
if (cache.size >= MAX_TIMESTAMP_CACHE_ENTRIES) {
|
|
3150
|
+
const oldestKey = cache.keys().next().value;
|
|
3151
|
+
if (oldestKey != null) cache.delete(oldestKey);
|
|
3152
|
+
}
|
|
3153
|
+
cache.set(key, value);
|
|
3154
|
+
};
|
|
2766
3155
|
var parseEnabledFlag2 = (value, env) => {
|
|
2767
3156
|
const normalized = String(value ?? "").trim().toLowerCase();
|
|
2768
3157
|
if (!normalized) {
|
|
@@ -2869,7 +3258,7 @@ var getCachedGlobalContext = ({
|
|
|
2869
3258
|
maxAgeMs,
|
|
2870
3259
|
...abortSignal ? { signal: abortSignal } : {}
|
|
2871
3260
|
});
|
|
2872
|
-
globalContextCache
|
|
3261
|
+
setBoundedCache(globalContextCache, key, promise);
|
|
2873
3262
|
void promise.catch(() => globalContextCache.delete(key));
|
|
2874
3263
|
return promise;
|
|
2875
3264
|
};
|
|
@@ -2889,7 +3278,7 @@ var getCachedReferenceContexts = ({
|
|
|
2889
3278
|
maxAgeMs,
|
|
2890
3279
|
...abortSignal ? { signal: abortSignal } : {}
|
|
2891
3280
|
});
|
|
2892
|
-
referenceContextCache
|
|
3281
|
+
setBoundedCache(referenceContextCache, key, promise);
|
|
2893
3282
|
void promise.catch(() => referenceContextCache.delete(key));
|
|
2894
3283
|
return promise;
|
|
2895
3284
|
};
|
|
@@ -2908,7 +3297,7 @@ var getCachedExchangeLiquidityContext = ({
|
|
|
2908
3297
|
maxAgeMs,
|
|
2909
3298
|
...abortSignal ? { signal: abortSignal } : {}
|
|
2910
3299
|
});
|
|
2911
|
-
exchangeLiquidityContextCache
|
|
3300
|
+
setBoundedCache(exchangeLiquidityContextCache, key, promise);
|
|
2912
3301
|
void promise.catch(() => exchangeLiquidityContextCache.delete(key));
|
|
2913
3302
|
return promise;
|
|
2914
3303
|
};
|
|
@@ -2927,7 +3316,7 @@ var getCachedFearGreedContext = ({
|
|
|
2927
3316
|
maxAgeMs,
|
|
2928
3317
|
...abortSignal ? { signal: abortSignal } : {}
|
|
2929
3318
|
});
|
|
2930
|
-
fearGreedContextCache
|
|
3319
|
+
setBoundedCache(fearGreedContextCache, key, promise);
|
|
2931
3320
|
void promise.catch(() => fearGreedContextCache.delete(key));
|
|
2932
3321
|
return promise;
|
|
2933
3322
|
};
|
|
@@ -2947,7 +3336,7 @@ var getCachedIndexContexts = ({
|
|
|
2947
3336
|
maxAgeMs,
|
|
2948
3337
|
...abortSignal ? { signal: abortSignal } : {}
|
|
2949
3338
|
});
|
|
2950
|
-
indexContextCache
|
|
3339
|
+
setBoundedCache(indexContextCache, key, promise);
|
|
2951
3340
|
void promise.catch(() => indexContextCache.delete(key));
|
|
2952
3341
|
return promise;
|
|
2953
3342
|
};
|
|
@@ -3761,7 +4150,7 @@ var signalIntervalToMarketInterval2 = (value) => {
|
|
|
3761
4150
|
var hasBaseContext3 = (signal) => Boolean(
|
|
3762
4151
|
signal.additionalIndicators?.baseContext && typeof signal.additionalIndicators.baseContext === "object" && !Array.isArray(signal.additionalIndicators.baseContext)
|
|
3763
4152
|
);
|
|
3764
|
-
var
|
|
4153
|
+
var setBoundedCache2 = (key, value) => {
|
|
3765
4154
|
if (contextCache.size >= MAX_CACHE_ENTRIES) {
|
|
3766
4155
|
const oldestKey = contextCache.keys().next().value;
|
|
3767
4156
|
if (oldestKey != null) contextCache.delete(oldestKey);
|
|
@@ -4008,7 +4397,7 @@ var loadHyperliquidWhaleFlowContext = async (params) => {
|
|
|
4008
4397
|
whaleRegistryFingerprint: whales.fingerprint,
|
|
4009
4398
|
...params.abortSignal ? { signal: params.abortSignal } : {}
|
|
4010
4399
|
});
|
|
4011
|
-
|
|
4400
|
+
setBoundedCache2(cacheKey, pending);
|
|
4012
4401
|
}
|
|
4013
4402
|
row = await pending;
|
|
4014
4403
|
}
|
|
@@ -5156,20 +5545,23 @@ var buildHookCtx = ({
|
|
|
5156
5545
|
strategyConfig,
|
|
5157
5546
|
env,
|
|
5158
5547
|
isConfigFromBacktest
|
|
5159
|
-
}) =>
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5548
|
+
}) => {
|
|
5549
|
+
const context = {
|
|
5550
|
+
connector,
|
|
5551
|
+
strategyName,
|
|
5552
|
+
userName,
|
|
5553
|
+
symbol
|
|
5554
|
+
};
|
|
5555
|
+
if (universe) context.universe = universe;
|
|
5556
|
+
if (assetClass) context.assetClass = assetClass;
|
|
5557
|
+
if (accountId) context.accountId = accountId;
|
|
5558
|
+
if (deploymentId) context.deploymentId = deploymentId;
|
|
5559
|
+
if (policyProfileId) context.policyProfileId = policyProfileId;
|
|
5560
|
+
context.strategyConfig = strategyConfig;
|
|
5561
|
+
context.env = env;
|
|
5562
|
+
context.isConfigFromBacktest = isConfigFromBacktest;
|
|
5563
|
+
return context;
|
|
5564
|
+
};
|
|
5173
5565
|
var shouldRecordRuntimeJournal = ({
|
|
5174
5566
|
env,
|
|
5175
5567
|
config
|
|
@@ -6900,6 +7292,7 @@ var createCloseAllOnGlobalProfitBeforeSignalsHook = ({
|
|
|
6900
7292
|
isKnownStrategy,
|
|
6901
7293
|
isTrackedHyperliquidPerp,
|
|
6902
7294
|
isTrackedHyperliquidWhale,
|
|
7295
|
+
preloadBinanceMarketContextForWindow,
|
|
6903
7296
|
registerStrategyEntries,
|
|
6904
7297
|
resetAiRuntimeCache,
|
|
6905
7298
|
resetStrategyRegistryCache,
|
package/dist/strategies.mjs
CHANGED
|
@@ -19,10 +19,11 @@ import {
|
|
|
19
19
|
getPrimaryBinanceBreadthUniverse,
|
|
20
20
|
isTrackedHyperliquidPerp,
|
|
21
21
|
isTrackedHyperliquidWhale,
|
|
22
|
+
preloadBinanceMarketContextForWindow,
|
|
22
23
|
resolveHyperliquidPerpFromSignalSymbol,
|
|
23
24
|
resolveStrategyConfig,
|
|
24
25
|
validateEntryProtectionAtArrival
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-VQSGH7YA.mjs";
|
|
26
27
|
import {
|
|
27
28
|
DEFAULT_AI_MODEL,
|
|
28
29
|
MAX_AI_SERIES_POINTS,
|
|
@@ -52,7 +53,7 @@ import {
|
|
|
52
53
|
runAiPromptLocal,
|
|
53
54
|
strategies,
|
|
54
55
|
trimSeriesDeep
|
|
55
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-UITD6LG6.mjs";
|
|
56
57
|
import "./chunk-LZDXRXIU.mjs";
|
|
57
58
|
import "./chunk-Y6FXYEAI.mjs";
|
|
58
59
|
|
|
@@ -472,6 +473,7 @@ export {
|
|
|
472
473
|
isKnownStrategy,
|
|
473
474
|
isTrackedHyperliquidPerp,
|
|
474
475
|
isTrackedHyperliquidWhale,
|
|
476
|
+
preloadBinanceMarketContextForWindow,
|
|
475
477
|
registerStrategyEntries,
|
|
476
478
|
resetAiRuntimeCache,
|
|
477
479
|
resetStrategyRegistryCache,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/node",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.28-beta.251",
|
|
4
4
|
"description": "Node-only runtime for the TradeJS TypeScript framework: strategies, backtests, Pine strategy loading, and plugin registries.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -89,9 +89,9 @@
|
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@langchain/core": "^1.2.3",
|
|
91
91
|
"@langchain/openai": "^1.5.5",
|
|
92
|
-
"@tradejs/core": "^3.1.
|
|
93
|
-
"@tradejs/infra": "^3.1.
|
|
94
|
-
"@tradejs/types": "^3.1.
|
|
92
|
+
"@tradejs/core": "^3.1.28-beta.251",
|
|
93
|
+
"@tradejs/infra": "^3.1.28-beta.251",
|
|
94
|
+
"@tradejs/types": "^3.1.28-beta.251",
|
|
95
95
|
"@types/node": "^24",
|
|
96
96
|
"chalk": "4.1.2",
|
|
97
97
|
"ioredis": "5.11.1",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"typescript": "^5.9"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
|
-
"@tradejs/indicators": "^3.1.
|
|
107
|
+
"@tradejs/indicators": "^3.1.28-beta.251",
|
|
108
108
|
"@tradejs/strategy-adaptive-momentum-ribbon": "3.0.2",
|
|
109
109
|
"@tradejs/strategy-hyperliquid-consensus": "3.0.2",
|
|
110
110
|
"@tradejs/strategy-kit": "3.0.4",
|