@tradejs/node 2.0.12 → 2.0.14
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 -1
- package/dist/ai.mjs +1 -1
- package/dist/backtest.js +580 -14
- package/dist/backtest.mjs +18 -3
- package/dist/{chunk-PD25CABK.mjs → chunk-DPHKRDD5.mjs} +1 -1
- package/dist/{chunk-76TEMQKX.mjs → chunk-FEQR4XGR.mjs} +576 -9
- package/dist/cli.js +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/strategies.d.mts +50 -1
- package/dist/strategies.d.ts +50 -1
- package/dist/strategies.js +633 -37
- package/dist/strategies.mjs +45 -4
- package/package.json +4 -4
package/dist/backtest.js
CHANGED
|
@@ -46,11 +46,11 @@ __reExport(backtest_exports, require("@tradejs/core/backtest"), module.exports);
|
|
|
46
46
|
var import_types = require("@tradejs/types");
|
|
47
47
|
var import_indicators3 = require("@tradejs/core/indicators");
|
|
48
48
|
var import_constants4 = require("@tradejs/core/constants");
|
|
49
|
-
var
|
|
49
|
+
var import_strategies5 = require("@tradejs/core/strategies");
|
|
50
50
|
var import_time = require("@tradejs/core/time");
|
|
51
51
|
var import_ai2 = require("@tradejs/infra/ai");
|
|
52
52
|
var import_ml2 = require("@tradejs/infra/ml");
|
|
53
|
-
var
|
|
53
|
+
var import_logger8 = require("@tradejs/infra/logger");
|
|
54
54
|
|
|
55
55
|
// src/ai.ts
|
|
56
56
|
var import_aiLanguages = require("@tradejs/infra/aiLanguages");
|
|
@@ -2457,6 +2457,558 @@ var enrichSignalWithDerivativesContext = async (params) => {
|
|
|
2457
2457
|
}
|
|
2458
2458
|
};
|
|
2459
2459
|
|
|
2460
|
+
// src/strategyHelpers/hyperliquidWhaleContext.ts
|
|
2461
|
+
var import_data2 = require("@tradejs/core/data");
|
|
2462
|
+
var import_strategies4 = require("@tradejs/core/strategies");
|
|
2463
|
+
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
2464
|
+
var import_logger6 = require("@tradejs/infra/logger");
|
|
2465
|
+
|
|
2466
|
+
// src/hyperliquidWhaleUniverse.ts
|
|
2467
|
+
var import_node_crypto2 = require("crypto");
|
|
2468
|
+
|
|
2469
|
+
// src/config/hyperliquidPerpUniverse.json
|
|
2470
|
+
var hyperliquidPerpUniverse_default = {
|
|
2471
|
+
schemaVersion: 1,
|
|
2472
|
+
updatedAt: "2026-08-04T11:46:43.476Z",
|
|
2473
|
+
source: "hyperliquid_main_perp_day_notional_volume",
|
|
2474
|
+
fingerprint: "58f7e024b19158dc",
|
|
2475
|
+
size: 30,
|
|
2476
|
+
symbols: [
|
|
2477
|
+
"BTC",
|
|
2478
|
+
"ETH",
|
|
2479
|
+
"HYPE",
|
|
2480
|
+
"SOL",
|
|
2481
|
+
"ZEC",
|
|
2482
|
+
"PUMP",
|
|
2483
|
+
"XRP",
|
|
2484
|
+
"CASHCAT",
|
|
2485
|
+
"WLD",
|
|
2486
|
+
"GRAM",
|
|
2487
|
+
"UNI",
|
|
2488
|
+
"ADA",
|
|
2489
|
+
"LIT",
|
|
2490
|
+
"ENA",
|
|
2491
|
+
"NEAR",
|
|
2492
|
+
"kPEPE",
|
|
2493
|
+
"FARTCOIN",
|
|
2494
|
+
"KAITO",
|
|
2495
|
+
"AAVE",
|
|
2496
|
+
"SUI",
|
|
2497
|
+
"ONDO",
|
|
2498
|
+
"AVAX",
|
|
2499
|
+
"DOGE",
|
|
2500
|
+
"VVV",
|
|
2501
|
+
"BNB",
|
|
2502
|
+
"ALGO",
|
|
2503
|
+
"XMR",
|
|
2504
|
+
"MEGA",
|
|
2505
|
+
"LINK",
|
|
2506
|
+
"TAO"
|
|
2507
|
+
]
|
|
2508
|
+
};
|
|
2509
|
+
|
|
2510
|
+
// src/config/hyperliquidWhales.json
|
|
2511
|
+
var hyperliquidWhales_default = {
|
|
2512
|
+
schemaVersion: 2,
|
|
2513
|
+
updatedAt: "2026-08-04T15:10:21.316Z",
|
|
2514
|
+
source: "hyperliquid_structural_fills_snapshot",
|
|
2515
|
+
selection: {
|
|
2516
|
+
calibrationFrom: "2026-07-28T00:00:00.000Z",
|
|
2517
|
+
calibrationTo: "2026-08-04T00:00:00.000Z",
|
|
2518
|
+
effectiveFrom: "2026-08-04T00:00:00.000Z",
|
|
2519
|
+
candidateLimit: 400,
|
|
2520
|
+
minimumAccountValueUsd: 5e5,
|
|
2521
|
+
minimumActiveDays: 1,
|
|
2522
|
+
maximumRawFillsPerDay: 20,
|
|
2523
|
+
maximumDirectionalExecutionsPerDay: 10,
|
|
2524
|
+
minimumMedianNotionalUsd: 0,
|
|
2525
|
+
minimumMedianInterExecutionMinutes: 0,
|
|
2526
|
+
minimumTop30NotionalShare: 1e-3,
|
|
2527
|
+
minimumTurnoverToEquity: 0.05,
|
|
2528
|
+
maximumTurnoverToEquity: 5,
|
|
2529
|
+
score: "log1p(accountValue)*log1p(medianExecutionNotional)*log1p(max(1,medianInterExecutionMinutes))*sqrt(activeDays)*top30Share/sqrt(1+rawFillsPerDay)",
|
|
2530
|
+
forbiddenSelectionMetrics: ["pnl", "roi", "winRate", "closedPnl"]
|
|
2531
|
+
},
|
|
2532
|
+
fingerprint: "77a6e9d41222efdb",
|
|
2533
|
+
size: 100,
|
|
2534
|
+
addresses: [
|
|
2535
|
+
"0xacb66d1996501bcc82a0e7819c9e041599f5efbd",
|
|
2536
|
+
"0x90dbb196cacf24bd212b377a0dd62eaad5e8151b",
|
|
2537
|
+
"0xde5b8c8e713f7c29ec72c22a326d61e5ac76e402",
|
|
2538
|
+
"0x22edc38749b59c31c9319eae7fc62143ac2fcc6c",
|
|
2539
|
+
"0x4bc9a771cd2c96cb2a4501f2c049402b4e7e11b3",
|
|
2540
|
+
"0x9a0825ca6c4c577a1202a8fae3b8f044c1d5711d",
|
|
2541
|
+
"0xb6ca5d1ed0ca4bf8444c9dee2d068a9f4c5e2e92",
|
|
2542
|
+
"0xc3610d02548cdb1a30ede87c5dc0d2ffe5b9b99f",
|
|
2543
|
+
"0x48c6aaa647ad5197e85797f8eb95d7b9ce1ec5b6",
|
|
2544
|
+
"0x8c1ab015da7e5319649afca4a551924f89eff883",
|
|
2545
|
+
"0x64bddab5f13a99576fca6747f0aa205422c5f708",
|
|
2546
|
+
"0x98785f2a43fe32f972476b86ed5a5cfaf5240f00",
|
|
2547
|
+
"0x9836e286fbf4f71998827d4bd6ea3b470c26457e",
|
|
2548
|
+
"0x8f8d2d2565bfb10608a7ce64b48e2aea7875a344",
|
|
2549
|
+
"0xe6df4ed7a6ccb8426cbc87bdcdd3cc6d0e6c0690",
|
|
2550
|
+
"0xab04d040dec929a204298d44701476968b238b69",
|
|
2551
|
+
"0x870f718a84843abc3e22412a9b4dc2924466d448",
|
|
2552
|
+
"0x12c206d3e2f0d0059420c54d33fe604ebbecc230",
|
|
2553
|
+
"0x7d9e91a8a47eb553cbfd323e7633c0c213327124",
|
|
2554
|
+
"0x2057d4f2b6ea957b63371980775b0a5505a438f0",
|
|
2555
|
+
"0xead5b7d86c681c036c59cd00a0390541061c69f2",
|
|
2556
|
+
"0x3005fade4c0df5e1cd187d7062da359416f0eb8e",
|
|
2557
|
+
"0xe83b5e3644b50e802a25b34b38b91a061a0d3ca8",
|
|
2558
|
+
"0x525232cb6ed5030d2b052b36bfc0baec96986ee3",
|
|
2559
|
+
"0xa251520154ca342f0b1d702bf5a56f78c982405b",
|
|
2560
|
+
"0xa9184bb57fd75c7c63e4c074d6319eceac6be53b",
|
|
2561
|
+
"0xa20fb0c9e04063eec5be286e9269028d966646fa",
|
|
2562
|
+
"0x169ba96d963e77a87dbe58922ecdcdd0f0cf3315",
|
|
2563
|
+
"0x115849ce84370f25cadcf0d348510d73837e1aa5",
|
|
2564
|
+
"0x37b81ab9e3ab04b9e3738e4891621205aaa31fd5",
|
|
2565
|
+
"0x90f57d90a7dd3114312d4c31803ad5732baf5935",
|
|
2566
|
+
"0xad227f63d34e7251c1d0ab65e64eeea07aee4e44",
|
|
2567
|
+
"0xd38e2b0b3c85ae138532f9fe1a1d5f5455866b82",
|
|
2568
|
+
"0xf5f4c3aa62a0f903a8529905031b1536d1cf16f8",
|
|
2569
|
+
"0x75632aaf83120eae9b0618f8f50773ce347de2ad",
|
|
2570
|
+
"0x3927af597c09774f91ef84bf765ded4109e9f8ea",
|
|
2571
|
+
"0xf1863bd6d60a8f4b5f583ec54009af6a044877bf",
|
|
2572
|
+
"0xe7b34f28c54f85533896f8827edc92edac28b17f",
|
|
2573
|
+
"0x1cda20f9f6a23c209d54940af3ef63b96c9b2c31",
|
|
2574
|
+
"0x9e55b0e43b7f7f3909af841d326b2dadfda9392e",
|
|
2575
|
+
"0x610b8dd6b392d010c2b6ad8d121dfc09524cb613",
|
|
2576
|
+
"0x1d639a688b78f3d7e57166e59d9a8886b1bfb5a5",
|
|
2577
|
+
"0x34d3a17095ef7def39a489d63c7c916e673c9ca2",
|
|
2578
|
+
"0x5d0bde4017530ed43370e332a5d30194941f73c6",
|
|
2579
|
+
"0xaa7afc250041e2c56a06d3b7a5295bd01929e11b",
|
|
2580
|
+
"0x325edd95bb016c36027ce3b9f7595af7094a9564",
|
|
2581
|
+
"0x47f5a6397b79deaaca5c456503e7c1a49357b942",
|
|
2582
|
+
"0xf5e7ffe523d0491709958490b4877e1d9de6c6f7",
|
|
2583
|
+
"0x64702807a1f0f9888ea22b858099d7f481227b55",
|
|
2584
|
+
"0xd08a4557671ca465e7bba41110a93148c90f9931",
|
|
2585
|
+
"0x0423b4b2acb4f219ae4a270abd5dde2360e455bb",
|
|
2586
|
+
"0x7b29f8c0ea709b96b72214b3de5d85c3d9570794",
|
|
2587
|
+
"0xeb8ebad162a9ce4cb7e2325c92b960b9df63365c",
|
|
2588
|
+
"0x939f95036d2e7b6d7419ec072bf9d967352204d2",
|
|
2589
|
+
"0x2490aa2b48022e857d44e738911787c8e2296aed",
|
|
2590
|
+
"0x7622f628135378f1b8d1876952de9bab80245f1c",
|
|
2591
|
+
"0x9d677028e0e592d48fc8a8ddc910693301a4a450",
|
|
2592
|
+
"0x85e410e4c535cb1709dbd36468f132037a5b2087",
|
|
2593
|
+
"0xd6f52e2ab58a678eced4a4d1693757b0677631c8",
|
|
2594
|
+
"0x24d8969e2bd6aabb6c4dfe042ef8b2cd8085217e",
|
|
2595
|
+
"0xda51323fe9800c8365646ad5c7ade0dd17fdc167",
|
|
2596
|
+
"0x53f8f390fd4f70941c5d160a964f6893c8dbceff",
|
|
2597
|
+
"0x72dae3560e7f4c59a305e2e739d6bd6777f738b5",
|
|
2598
|
+
"0x36f5e448c9cf0032551e58919cf4eabefcd742c1",
|
|
2599
|
+
"0x5b43b7162694de766c164202df0f0c716e4292ab",
|
|
2600
|
+
"0xae551d73161bac3315c5ade0e2d499a44ebe2236",
|
|
2601
|
+
"0x4eca8d62e07b3f3e78a8ae8725d4666da324c5a8",
|
|
2602
|
+
"0x40a632026febd007b0e4431a29170507f7aa3896",
|
|
2603
|
+
"0xd453e91f692eb5437cf345e09545827576e3225d",
|
|
2604
|
+
"0xbe2c69eb3d7b8ee35cbe3a28293472be31179d75",
|
|
2605
|
+
"0xfdf891f2b214a4c9374d26595ec6d4080262e381",
|
|
2606
|
+
"0xfd97600ac44b3c4e20ac1a5f23e3b18d10fa5912",
|
|
2607
|
+
"0x98e073b579fd483eac8f10d5bd0b32c8c3bbd7e0",
|
|
2608
|
+
"0xb56f19e917546a60d658110a611cf62a6877b517",
|
|
2609
|
+
"0xbd334a55db91617545e8d1b09941e036ad8e4200",
|
|
2610
|
+
"0x9f1920d0cbb63ed03376a1e09fd2851d601234c8",
|
|
2611
|
+
"0xe9cef9fd872a03cedf9d3e6e90309782b3724ea6",
|
|
2612
|
+
"0xa43682a1f129e4faf0152175cc03c44e4957e8cf",
|
|
2613
|
+
"0x6fbb33de5f39c690d2decb95b9ab46ed0c83e3bc",
|
|
2614
|
+
"0x81d4163289cf61a0eaaac4862cb88ef0f4215c29",
|
|
2615
|
+
"0xd248d2f09bfbe04e67fc7fea08828d6ad6d95b6d",
|
|
2616
|
+
"0x01ffcc7285866e5cee14c8e807cb2e8d5f61079f",
|
|
2617
|
+
"0xc69ae428f6049e78d445f053d2c1df879c59b34c",
|
|
2618
|
+
"0xaab4dfe6d735c4ac46217216fe883a39fbfe8284",
|
|
2619
|
+
"0xe912cac1a6641004a8803687ee7699227fdb0550",
|
|
2620
|
+
"0x5fdbf83c3d95d525704f61401db68cbec1b2a775",
|
|
2621
|
+
"0xebd7c4b3677a4480fb5f69ac2f51c51d66a19990",
|
|
2622
|
+
"0xe4d1fa7e6141f9131345117bdb8b5701bca67662",
|
|
2623
|
+
"0x685feceec46dd4e5c9b5b726f5d7550fd0eda526",
|
|
2624
|
+
"0x3ea8b09da72972e953541500721803a187526da6",
|
|
2625
|
+
"0xdbe0780a5c5a0e3b345101bbc01ac2218196d6d5",
|
|
2626
|
+
"0x18cd4597e06b7fe0a8cd33dda499121b3a145a8b",
|
|
2627
|
+
"0xb8243756956e722bff5c763971b562ac551bfbd2",
|
|
2628
|
+
"0xe0bf8c96795d2df0b61b3b17e7cfd7d3ba13d4be",
|
|
2629
|
+
"0x218a65e21eddeece7a9df38c6bbdd89f692b7da2",
|
|
2630
|
+
"0x53b63a30a688beb53b5dc7bd731c661d678c555c",
|
|
2631
|
+
"0xfce053a5e461683454bf37ad66d20344c0e3f4c0",
|
|
2632
|
+
"0x3e516cf3c9d4f29fae6c1324c2414dc872fc9c09",
|
|
2633
|
+
"0xe5f1486dc84706d2509885fe6bbc46d21ba81286",
|
|
2634
|
+
"0x38042d713af713f0275b00640a83654db91ea543"
|
|
2635
|
+
]
|
|
2636
|
+
};
|
|
2637
|
+
|
|
2638
|
+
// src/hyperliquidWhaleUniverse.ts
|
|
2639
|
+
var fingerprint2 = (value) => (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 16);
|
|
2640
|
+
var validateUnique = (values, label) => {
|
|
2641
|
+
if (new Set(values).size !== values.length) {
|
|
2642
|
+
throw new Error(`Hyperliquid ${label} snapshot contains duplicates`);
|
|
2643
|
+
}
|
|
2644
|
+
};
|
|
2645
|
+
var validatePerpSnapshot = (value) => {
|
|
2646
|
+
const symbols = value.symbols.map((symbol) => symbol.trim()).filter(Boolean);
|
|
2647
|
+
validateUnique(symbols, "perp universe");
|
|
2648
|
+
if (value.schemaVersion !== 1 || value.source !== "hyperliquid_main_perp_day_notional_volume" || value.size !== 30 || symbols.length !== 30 || value.fingerprint !== fingerprint2(symbols)) {
|
|
2649
|
+
throw new Error("Invalid Hyperliquid perp universe snapshot");
|
|
2650
|
+
}
|
|
2651
|
+
return value;
|
|
2652
|
+
};
|
|
2653
|
+
var validateWhaleSnapshot = (value) => {
|
|
2654
|
+
const addresses = value.addresses.map((address) => address.toLowerCase());
|
|
2655
|
+
validateUnique(addresses, "whale registry");
|
|
2656
|
+
if (value.schemaVersion !== 2 || value.source !== "hyperliquid_structural_fills_snapshot" || value.size !== 100 || addresses.length !== 100 || addresses.some((address) => !/^0x[0-9a-f]{40}$/.test(address)) || value.fingerprint !== fingerprint2(addresses)) {
|
|
2657
|
+
throw new Error("Invalid Hyperliquid whale registry snapshot");
|
|
2658
|
+
}
|
|
2659
|
+
return value;
|
|
2660
|
+
};
|
|
2661
|
+
var perpSnapshot = validatePerpSnapshot(hyperliquidPerpUniverse_default);
|
|
2662
|
+
var whaleSnapshot = validateWhaleSnapshot(hyperliquidWhales_default);
|
|
2663
|
+
var perpSymbolSet = new Set(perpSnapshot.symbols);
|
|
2664
|
+
var whaleAddressSet = new Set(whaleSnapshot.addresses);
|
|
2665
|
+
var getHyperliquidPerpUniverseSnapshot = () => perpSnapshot;
|
|
2666
|
+
var getHyperliquidWhaleRegistrySnapshot = () => whaleSnapshot;
|
|
2667
|
+
var SIGNAL_TO_HYPERLIQUID_ALIASES = {
|
|
2668
|
+
PEPE: "kPEPE",
|
|
2669
|
+
"1000PEPE": "kPEPE",
|
|
2670
|
+
PUMPFUN: "PUMP",
|
|
2671
|
+
SHIB: "kSHIB",
|
|
2672
|
+
BONK: "kBONK"
|
|
2673
|
+
};
|
|
2674
|
+
var resolveHyperliquidPerpFromSignalSymbol = (symbol) => {
|
|
2675
|
+
const normalized = symbol.trim().toUpperCase().replace(/(?:USDT|USDC)$/, "");
|
|
2676
|
+
const candidate = SIGNAL_TO_HYPERLIQUID_ALIASES[normalized] ?? normalized;
|
|
2677
|
+
return perpSymbolSet.has(candidate) ? candidate : null;
|
|
2678
|
+
};
|
|
2679
|
+
|
|
2680
|
+
// src/strategyHelpers/hyperliquidWhaleContext.ts
|
|
2681
|
+
var MAX_CACHE_ENTRIES = 2048;
|
|
2682
|
+
var MAX_COVERAGE_SERIES_CACHE_ENTRIES = 20;
|
|
2683
|
+
var MAX_FLOW_SERIES_CACHE_ENTRIES = 64;
|
|
2684
|
+
var SERIES_CHUNK_MS = 30 * 24 * 60 * 6e4;
|
|
2685
|
+
var MAX_SERIES_LOOKBACK_MS = 60 * 6e4;
|
|
2686
|
+
var DEFAULT_MIN_COVERAGE_PCT = 0.8;
|
|
2687
|
+
var INTERVAL_MS = {
|
|
2688
|
+
"1m": 6e4,
|
|
2689
|
+
"5m": 5 * 6e4,
|
|
2690
|
+
"15m": 15 * 6e4,
|
|
2691
|
+
"1h": 60 * 6e4
|
|
2692
|
+
};
|
|
2693
|
+
var DEFAULT_MAX_AGE_BY_INTERVAL2 = {
|
|
2694
|
+
"1m": 2 * 6e4,
|
|
2695
|
+
"5m": 10 * 6e4,
|
|
2696
|
+
"15m": 30 * 6e4,
|
|
2697
|
+
"1h": 2 * 60 * 6e4
|
|
2698
|
+
};
|
|
2699
|
+
var hyperliquidWhaleContextUnavailable = false;
|
|
2700
|
+
var contextCache = /* @__PURE__ */ new Map();
|
|
2701
|
+
var coverageSeriesCache = /* @__PURE__ */ new Map();
|
|
2702
|
+
var flowSeriesCache = /* @__PURE__ */ new Map();
|
|
2703
|
+
var parseEnabledFlag4 = (value, env) => {
|
|
2704
|
+
const normalized = String(value ?? "").trim().toLowerCase();
|
|
2705
|
+
if (!normalized) return env !== "TEST";
|
|
2706
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
2707
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
2708
|
+
if (normalized === "backtest") return env === "BACKTEST";
|
|
2709
|
+
if (normalized === "live") return env !== "BACKTEST";
|
|
2710
|
+
return false;
|
|
2711
|
+
};
|
|
2712
|
+
var getMinimumCoveragePct = () => {
|
|
2713
|
+
const parsed = Number(process.env.HYPERLIQUID_WHALE_MIN_COVERAGE_PCT);
|
|
2714
|
+
return Number.isFinite(parsed) ? Math.max(0, Math.min(1, parsed)) : DEFAULT_MIN_COVERAGE_PCT;
|
|
2715
|
+
};
|
|
2716
|
+
var signalIntervalToMarketInterval2 = (value) => {
|
|
2717
|
+
const normalized = String(value).trim().toLowerCase();
|
|
2718
|
+
if (normalized === "1" || normalized === "1m") return "1m";
|
|
2719
|
+
if (normalized === "5" || normalized === "5m") return "5m";
|
|
2720
|
+
if (normalized === "60" || normalized === "1h") return "1h";
|
|
2721
|
+
return "15m";
|
|
2722
|
+
};
|
|
2723
|
+
var hasBaseContext3 = (signal) => Boolean(
|
|
2724
|
+
signal.additionalIndicators?.baseContext && typeof signal.additionalIndicators.baseContext === "object" && !Array.isArray(signal.additionalIndicators.baseContext)
|
|
2725
|
+
);
|
|
2726
|
+
var setBoundedCache = (key, value) => {
|
|
2727
|
+
if (contextCache.size >= MAX_CACHE_ENTRIES) {
|
|
2728
|
+
const oldestKey = contextCache.keys().next().value;
|
|
2729
|
+
if (oldestKey != null) contextCache.delete(oldestKey);
|
|
2730
|
+
}
|
|
2731
|
+
contextCache.set(key, value);
|
|
2732
|
+
};
|
|
2733
|
+
var setBoundedSeriesCache = (cache, maxEntries, key, value) => {
|
|
2734
|
+
if (cache.size >= maxEntries) {
|
|
2735
|
+
const oldestKey = cache.keys().next().value;
|
|
2736
|
+
if (oldestKey != null) cache.delete(oldestKey);
|
|
2737
|
+
}
|
|
2738
|
+
cache.set(key, value);
|
|
2739
|
+
};
|
|
2740
|
+
var uniqueAddressCount = (rows, field) => {
|
|
2741
|
+
const addresses = /* @__PURE__ */ new Set();
|
|
2742
|
+
for (const row of rows) {
|
|
2743
|
+
for (const address of row[field]) addresses.add(address);
|
|
2744
|
+
}
|
|
2745
|
+
return addresses.size;
|
|
2746
|
+
};
|
|
2747
|
+
var sumFlowField = (rows, field) => rows.reduce((sum, row) => sum + row[field], 0);
|
|
2748
|
+
var sliceSeriesWindow = (rows, fromMs, toMs) => {
|
|
2749
|
+
const lowerBound = (timestamp) => {
|
|
2750
|
+
let low = 0;
|
|
2751
|
+
let high = rows.length;
|
|
2752
|
+
while (low < high) {
|
|
2753
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
2754
|
+
if (rows[middle].ts.getTime() < timestamp) low = middle + 1;
|
|
2755
|
+
else high = middle;
|
|
2756
|
+
}
|
|
2757
|
+
return low;
|
|
2758
|
+
};
|
|
2759
|
+
return rows.slice(lowerBound(fromMs), lowerBound(toMs));
|
|
2760
|
+
};
|
|
2761
|
+
var aggregateHyperliquidWhaleFlowSeries = (params) => {
|
|
2762
|
+
const intervalMs = INTERVAL_MS[params.interval];
|
|
2763
|
+
const windowStartMs = params.decisionTimeMs - intervalMs;
|
|
2764
|
+
const coverageRows = sliceSeriesWindow(
|
|
2765
|
+
params.coverageRows,
|
|
2766
|
+
windowStartMs,
|
|
2767
|
+
params.decisionTimeMs
|
|
2768
|
+
);
|
|
2769
|
+
const expectedBuckets = Math.ceil(intervalMs / 6e4);
|
|
2770
|
+
if (coverageRows.length !== expectedBuckets || coverageRows.some((row) => row.coveredWhales <= 0)) {
|
|
2771
|
+
return null;
|
|
2772
|
+
}
|
|
2773
|
+
const flowRows = sliceSeriesWindow(
|
|
2774
|
+
params.flowRows,
|
|
2775
|
+
windowStartMs,
|
|
2776
|
+
params.decisionTimeMs
|
|
2777
|
+
);
|
|
2778
|
+
const asOfTs = new Date(
|
|
2779
|
+
Math.max(...coverageRows.map((row) => row.ts.getTime()))
|
|
2780
|
+
);
|
|
2781
|
+
const coveredWhales = Math.min(
|
|
2782
|
+
...coverageRows.map((row) => row.coveredWhales)
|
|
2783
|
+
);
|
|
2784
|
+
const expectedWhales = Math.max(
|
|
2785
|
+
...coverageRows.map((row) => row.expectedWhales)
|
|
2786
|
+
);
|
|
2787
|
+
const coveragePct = Math.min(...coverageRows.map((row) => row.coveragePct));
|
|
2788
|
+
const trades = sumFlowField(flowRows, "trades");
|
|
2789
|
+
const whaleSides = sumFlowField(flowRows, "whaleSides");
|
|
2790
|
+
const buyNotionalUsd = sumFlowField(flowRows, "buyNotionalUsd");
|
|
2791
|
+
const sellNotionalUsd = sumFlowField(flowRows, "sellNotionalUsd");
|
|
2792
|
+
const positionAwareWhaleSides = sumFlowField(
|
|
2793
|
+
flowRows,
|
|
2794
|
+
"positionAwareWhaleSides"
|
|
2795
|
+
);
|
|
2796
|
+
const longEntryNotionalUsd = sumFlowField(flowRows, "longEntryNotionalUsd");
|
|
2797
|
+
const shortEntryNotionalUsd = sumFlowField(flowRows, "shortEntryNotionalUsd");
|
|
2798
|
+
const longExitNotionalUsd = sumFlowField(flowRows, "longExitNotionalUsd");
|
|
2799
|
+
const shortExitNotionalUsd = sumFlowField(flowRows, "shortExitNotionalUsd");
|
|
2800
|
+
const totalNotionalUsd = buyNotionalUsd + sellNotionalUsd;
|
|
2801
|
+
const totalEntryNotionalUsd = longEntryNotionalUsd + shortEntryNotionalUsd;
|
|
2802
|
+
const ageMs = params.decisionTimeMs - (asOfTs.getTime() + 6e4);
|
|
2803
|
+
return {
|
|
2804
|
+
symbol: params.symbol,
|
|
2805
|
+
interval: params.interval,
|
|
2806
|
+
asOfTs,
|
|
2807
|
+
windowEndTs: new Date(params.decisionTimeMs),
|
|
2808
|
+
trades,
|
|
2809
|
+
whaleSides,
|
|
2810
|
+
uniqueWhales: uniqueAddressCount(flowRows, "whaleAddresses"),
|
|
2811
|
+
coveredWhales,
|
|
2812
|
+
expectedWhales,
|
|
2813
|
+
coveragePct,
|
|
2814
|
+
buyNotionalUsd,
|
|
2815
|
+
sellNotionalUsd,
|
|
2816
|
+
netNotionalUsd: buyNotionalUsd - sellNotionalUsd,
|
|
2817
|
+
buySharePct: totalNotionalUsd > 0 ? buyNotionalUsd / totalNotionalUsd : null,
|
|
2818
|
+
positionAwareWhaleSides,
|
|
2819
|
+
positionAwarePct: whaleSides > 0 ? positionAwareWhaleSides / whaleSides : 0,
|
|
2820
|
+
longEntryWhales: uniqueAddressCount(flowRows, "longEntryWhaleAddresses"),
|
|
2821
|
+
shortEntryWhales: uniqueAddressCount(flowRows, "shortEntryWhaleAddresses"),
|
|
2822
|
+
longExitWhales: uniqueAddressCount(flowRows, "longExitWhaleAddresses"),
|
|
2823
|
+
shortExitWhales: uniqueAddressCount(flowRows, "shortExitWhaleAddresses"),
|
|
2824
|
+
longEntryNotionalUsd,
|
|
2825
|
+
shortEntryNotionalUsd,
|
|
2826
|
+
longExitNotionalUsd,
|
|
2827
|
+
shortExitNotionalUsd,
|
|
2828
|
+
entryNetNotionalUsd: longEntryNotionalUsd - shortEntryNotionalUsd,
|
|
2829
|
+
entryLongSharePct: totalEntryNotionalUsd > 0 ? longEntryNotionalUsd / totalEntryNotionalUsd : null,
|
|
2830
|
+
universeFingerprint: params.universeFingerprint,
|
|
2831
|
+
whaleRegistryFingerprint: params.whaleRegistryFingerprint,
|
|
2832
|
+
source: positionAwareWhaleSides > 0 ? "hyperliquid_user_fills" : null,
|
|
2833
|
+
ageMs,
|
|
2834
|
+
stale: ageMs < 0 || (params.maxAgeMs != null && Number.isFinite(params.maxAgeMs) ? ageMs > params.maxAgeMs : false)
|
|
2835
|
+
};
|
|
2836
|
+
};
|
|
2837
|
+
var loadHyperliquidWhaleFlowAggregateFromSeries = async (params) => {
|
|
2838
|
+
const chunkStartMs = Math.floor(params.decisionTimeMs / SERIES_CHUNK_MS) * SERIES_CHUNK_MS;
|
|
2839
|
+
const fromMs = chunkStartMs - MAX_SERIES_LOOKBACK_MS;
|
|
2840
|
+
const toMs = chunkStartMs + SERIES_CHUNK_MS;
|
|
2841
|
+
const sharedKey = [
|
|
2842
|
+
fromMs,
|
|
2843
|
+
toMs,
|
|
2844
|
+
params.universeFingerprint,
|
|
2845
|
+
params.whaleRegistryFingerprint
|
|
2846
|
+
].join(":");
|
|
2847
|
+
let pendingCoverage = coverageSeriesCache.get(sharedKey);
|
|
2848
|
+
if (!pendingCoverage) {
|
|
2849
|
+
pendingCoverage = (0, import_timescale4.getHyperliquidWhaleCoverageSeriesRows)({
|
|
2850
|
+
fromMs,
|
|
2851
|
+
toMs,
|
|
2852
|
+
universeFingerprint: params.universeFingerprint,
|
|
2853
|
+
whaleRegistryFingerprint: params.whaleRegistryFingerprint
|
|
2854
|
+
});
|
|
2855
|
+
setBoundedSeriesCache(
|
|
2856
|
+
coverageSeriesCache,
|
|
2857
|
+
MAX_COVERAGE_SERIES_CACHE_ENTRIES,
|
|
2858
|
+
sharedKey,
|
|
2859
|
+
pendingCoverage
|
|
2860
|
+
);
|
|
2861
|
+
}
|
|
2862
|
+
const flowKey = `${params.symbol}:${sharedKey}`;
|
|
2863
|
+
let pendingFlow = flowSeriesCache.get(flowKey);
|
|
2864
|
+
if (!pendingFlow) {
|
|
2865
|
+
pendingFlow = (0, import_timescale4.getHyperliquidWhaleFlowSeriesRows)({
|
|
2866
|
+
symbol: params.symbol,
|
|
2867
|
+
fromMs,
|
|
2868
|
+
toMs,
|
|
2869
|
+
universeFingerprint: params.universeFingerprint,
|
|
2870
|
+
whaleRegistryFingerprint: params.whaleRegistryFingerprint
|
|
2871
|
+
});
|
|
2872
|
+
setBoundedSeriesCache(
|
|
2873
|
+
flowSeriesCache,
|
|
2874
|
+
MAX_FLOW_SERIES_CACHE_ENTRIES,
|
|
2875
|
+
flowKey,
|
|
2876
|
+
pendingFlow
|
|
2877
|
+
);
|
|
2878
|
+
}
|
|
2879
|
+
const [coverageRows, flowRows] = await Promise.all([
|
|
2880
|
+
pendingCoverage,
|
|
2881
|
+
pendingFlow
|
|
2882
|
+
]);
|
|
2883
|
+
return aggregateHyperliquidWhaleFlowSeries({
|
|
2884
|
+
...params,
|
|
2885
|
+
coverageRows,
|
|
2886
|
+
flowRows
|
|
2887
|
+
});
|
|
2888
|
+
};
|
|
2889
|
+
var toBaseHyperliquidWhaleFlowContext = (row, minimumCoveragePct) => ({
|
|
2890
|
+
source: row.positionAwareWhaleSides > 0 ? "hyperliquid_user_fills" : "hyperliquid_trades",
|
|
2891
|
+
interval: row.interval,
|
|
2892
|
+
asOfTs: row.asOfTs.getTime(),
|
|
2893
|
+
windowEndTs: row.windowEndTs.getTime(),
|
|
2894
|
+
ageMs: row.ageMs,
|
|
2895
|
+
stale: row.stale,
|
|
2896
|
+
symbol: row.symbol,
|
|
2897
|
+
trades: row.trades,
|
|
2898
|
+
whaleSides: row.whaleSides,
|
|
2899
|
+
uniqueWhales: row.uniqueWhales,
|
|
2900
|
+
coveredWhales: row.coveredWhales,
|
|
2901
|
+
expectedWhales: row.expectedWhales,
|
|
2902
|
+
coveragePct: row.coveragePct,
|
|
2903
|
+
coverageSufficient: row.coveragePct >= minimumCoveragePct,
|
|
2904
|
+
buyNotionalUsd: row.buyNotionalUsd,
|
|
2905
|
+
sellNotionalUsd: row.sellNotionalUsd,
|
|
2906
|
+
netNotionalUsd: row.netNotionalUsd,
|
|
2907
|
+
buySharePct: row.buySharePct,
|
|
2908
|
+
positionAwareWhaleSides: row.positionAwareWhaleSides,
|
|
2909
|
+
positionAwarePct: row.positionAwarePct,
|
|
2910
|
+
longEntryWhales: row.longEntryWhales,
|
|
2911
|
+
shortEntryWhales: row.shortEntryWhales,
|
|
2912
|
+
longExitWhales: row.longExitWhales,
|
|
2913
|
+
shortExitWhales: row.shortExitWhales,
|
|
2914
|
+
longEntryNotionalUsd: row.longEntryNotionalUsd,
|
|
2915
|
+
shortEntryNotionalUsd: row.shortEntryNotionalUsd,
|
|
2916
|
+
longExitNotionalUsd: row.longExitNotionalUsd,
|
|
2917
|
+
shortExitNotionalUsd: row.shortExitNotionalUsd,
|
|
2918
|
+
entryNetNotionalUsd: row.entryNetNotionalUsd,
|
|
2919
|
+
entryLongSharePct: row.entryLongSharePct,
|
|
2920
|
+
universeFingerprint: row.universeFingerprint,
|
|
2921
|
+
whaleRegistryFingerprint: row.whaleRegistryFingerprint
|
|
2922
|
+
});
|
|
2923
|
+
var isHyperliquidWhaleContextEnabled = (env) => parseEnabledFlag4(process.env.HYPERLIQUID_WHALE_CONTEXT_ENABLED, env);
|
|
2924
|
+
var loadHyperliquidWhaleFlowContext = async (params) => {
|
|
2925
|
+
if (!(params.enabled ?? isHyperliquidWhaleContextEnabled(params.env)) || hyperliquidWhaleContextUnavailable || params.interval == null) {
|
|
2926
|
+
return null;
|
|
2927
|
+
}
|
|
2928
|
+
const symbol = resolveHyperliquidPerpFromSignalSymbol(params.symbol);
|
|
2929
|
+
if (!symbol) return null;
|
|
2930
|
+
const interval = params.marketInterval ?? signalIntervalToMarketInterval2(params.interval);
|
|
2931
|
+
const decisionTimeMs = params.timestamp + (0, import_data2.intervalToMs)(params.interval);
|
|
2932
|
+
const maxAgeMs = params.maxAgeMs ?? DEFAULT_MAX_AGE_BY_INTERVAL2[interval];
|
|
2933
|
+
const universe = getHyperliquidPerpUniverseSnapshot();
|
|
2934
|
+
const whales = getHyperliquidWhaleRegistrySnapshot();
|
|
2935
|
+
const minimumCoveragePct = getMinimumCoveragePct();
|
|
2936
|
+
const cacheKey = [
|
|
2937
|
+
symbol,
|
|
2938
|
+
interval,
|
|
2939
|
+
decisionTimeMs,
|
|
2940
|
+
maxAgeMs,
|
|
2941
|
+
universe.fingerprint,
|
|
2942
|
+
whales.fingerprint,
|
|
2943
|
+
minimumCoveragePct
|
|
2944
|
+
].join(":");
|
|
2945
|
+
try {
|
|
2946
|
+
let row;
|
|
2947
|
+
if (params.useSeriesCache) {
|
|
2948
|
+
row = await loadHyperliquidWhaleFlowAggregateFromSeries({
|
|
2949
|
+
symbol,
|
|
2950
|
+
interval,
|
|
2951
|
+
decisionTimeMs,
|
|
2952
|
+
maxAgeMs,
|
|
2953
|
+
universeFingerprint: universe.fingerprint,
|
|
2954
|
+
whaleRegistryFingerprint: whales.fingerprint
|
|
2955
|
+
});
|
|
2956
|
+
} else {
|
|
2957
|
+
let pending = contextCache.get(cacheKey);
|
|
2958
|
+
if (!pending) {
|
|
2959
|
+
pending = (0, import_timescale4.getHyperliquidWhaleFlowAggregate)({
|
|
2960
|
+
symbol,
|
|
2961
|
+
interval,
|
|
2962
|
+
decisionTimeMs,
|
|
2963
|
+
maxAgeMs,
|
|
2964
|
+
universeFingerprint: universe.fingerprint,
|
|
2965
|
+
whaleRegistryFingerprint: whales.fingerprint
|
|
2966
|
+
});
|
|
2967
|
+
setBoundedCache(cacheKey, pending);
|
|
2968
|
+
}
|
|
2969
|
+
row = await pending;
|
|
2970
|
+
}
|
|
2971
|
+
if (!row) return null;
|
|
2972
|
+
return toBaseHyperliquidWhaleFlowContext(row, minimumCoveragePct);
|
|
2973
|
+
} catch (error) {
|
|
2974
|
+
hyperliquidWhaleContextUnavailable = true;
|
|
2975
|
+
import_logger6.logger.warn(
|
|
2976
|
+
"Hyperliquid whale context disabled after Timescale read failure: %s",
|
|
2977
|
+
String(error)
|
|
2978
|
+
);
|
|
2979
|
+
return null;
|
|
2980
|
+
}
|
|
2981
|
+
};
|
|
2982
|
+
var enrichSignalWithHyperliquidWhaleContext = async (params) => {
|
|
2983
|
+
const { signal, env } = params;
|
|
2984
|
+
if (signal.universe === "tradfi" || signal.interval == null || !hasBaseContext3(signal)) {
|
|
2985
|
+
return false;
|
|
2986
|
+
}
|
|
2987
|
+
const hyperliquidWhales = await loadHyperliquidWhaleFlowContext({
|
|
2988
|
+
symbol: signal.symbol,
|
|
2989
|
+
interval: signal.interval,
|
|
2990
|
+
timestamp: signal.timestamp,
|
|
2991
|
+
env,
|
|
2992
|
+
enabled: params.enabled,
|
|
2993
|
+
marketInterval: params.interval,
|
|
2994
|
+
maxAgeMs: params.maxAgeMs
|
|
2995
|
+
});
|
|
2996
|
+
if (!hyperliquidWhales) return false;
|
|
2997
|
+
const baseContext = signal.additionalIndicators.baseContext;
|
|
2998
|
+
signal.additionalIndicators = {
|
|
2999
|
+
...signal.additionalIndicators,
|
|
3000
|
+
baseContext: {
|
|
3001
|
+
...baseContext,
|
|
3002
|
+
participation: {
|
|
3003
|
+
...baseContext.participation,
|
|
3004
|
+
hyperliquidWhales
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
};
|
|
3008
|
+
(0, import_strategies4.refreshSignalBaseContextGateFeatures)(signal);
|
|
3009
|
+
return true;
|
|
3010
|
+
};
|
|
3011
|
+
|
|
2460
3012
|
// src/strategyAdapters/ml.ts
|
|
2461
3013
|
var defaultMlAdapter = {
|
|
2462
3014
|
normalizeStrategyConfig: (strategyConfig) => strategyConfig
|
|
@@ -2506,7 +3058,7 @@ var buildMlPayload = (payload) => {
|
|
|
2506
3058
|
};
|
|
2507
3059
|
|
|
2508
3060
|
// src/connectorsRegistry.ts
|
|
2509
|
-
var
|
|
3061
|
+
var import_logger7 = require("@tradejs/infra/logger");
|
|
2510
3062
|
var createConnectorRegistryState = () => ({
|
|
2511
3063
|
connectorCreators: /* @__PURE__ */ new Map(),
|
|
2512
3064
|
providerToConnectorName: /* @__PURE__ */ new Map(),
|
|
@@ -2558,7 +3110,7 @@ var normalizeProviders = (providers, connectorName) => {
|
|
|
2558
3110
|
var registerProvider = (provider, connectorName, source, providerToConnectorName) => {
|
|
2559
3111
|
const existing = providerToConnectorName.get(provider);
|
|
2560
3112
|
if (existing && existing !== connectorName) {
|
|
2561
|
-
|
|
3113
|
+
import_logger7.logger.warn(
|
|
2562
3114
|
'Skip duplicate connector provider "%s" from %s: already mapped to %s',
|
|
2563
3115
|
provider,
|
|
2564
3116
|
source,
|
|
@@ -2571,11 +3123,11 @@ var registerProvider = (provider, connectorName, source, providerToConnectorName
|
|
|
2571
3123
|
var registerEntry = (entry, source, state) => {
|
|
2572
3124
|
const connectorName = String(entry?.name ?? "").trim();
|
|
2573
3125
|
if (!connectorName) {
|
|
2574
|
-
|
|
3126
|
+
import_logger7.logger.warn("Skip connector entry without name from %s", source);
|
|
2575
3127
|
return;
|
|
2576
3128
|
}
|
|
2577
3129
|
if (typeof entry.creator !== "function") {
|
|
2578
|
-
|
|
3130
|
+
import_logger7.logger.warn(
|
|
2579
3131
|
'Skip connector entry "%s" from %s: creator must be a function',
|
|
2580
3132
|
connectorName,
|
|
2581
3133
|
source
|
|
@@ -2587,7 +3139,7 @@ var registerEntry = (entry, source, state) => {
|
|
|
2587
3139
|
state.connectorCreators
|
|
2588
3140
|
);
|
|
2589
3141
|
if (existingByName) {
|
|
2590
|
-
|
|
3142
|
+
import_logger7.logger.warn(
|
|
2591
3143
|
'Skip duplicate connector "%s" from %s: already registered as %s',
|
|
2592
3144
|
connectorName,
|
|
2593
3145
|
source,
|
|
@@ -2659,7 +3211,7 @@ var ensureConnectorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
2659
3211
|
);
|
|
2660
3212
|
const pluginDefinition = extractConnectorPluginDefinition(moduleExport);
|
|
2661
3213
|
if (!pluginDefinition) {
|
|
2662
|
-
|
|
3214
|
+
import_logger7.logger.warn(
|
|
2663
3215
|
'Skip connector plugin "%s": export { connectorEntries } is missing',
|
|
2664
3216
|
moduleName
|
|
2665
3217
|
);
|
|
@@ -2667,7 +3219,7 @@ var ensureConnectorPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
|
|
|
2667
3219
|
}
|
|
2668
3220
|
registerEntries2(pluginDefinition.connectorEntries, moduleName, state);
|
|
2669
3221
|
} catch (error) {
|
|
2670
|
-
|
|
3222
|
+
import_logger7.logger.warn(
|
|
2671
3223
|
'Failed to load connector plugin "%s": %s',
|
|
2672
3224
|
moduleName,
|
|
2673
3225
|
String(error)
|
|
@@ -2698,7 +3250,7 @@ var getConnectorCreatorByName = async (connectorName, cwd = getTradejsProjectCwd
|
|
|
2698
3250
|
var DEFAULT_CONNECTOR_NAME = BUILTIN_CONNECTOR_NAMES.ByBit;
|
|
2699
3251
|
|
|
2700
3252
|
// src/testConnector.ts
|
|
2701
|
-
var
|
|
3253
|
+
var import_node_crypto3 = require("crypto");
|
|
2702
3254
|
var import_constants2 = require("@tradejs/core/constants");
|
|
2703
3255
|
var import_backtest = require("@tradejs/core/backtest");
|
|
2704
3256
|
var import_trade = require("@tradejs/core/trade");
|
|
@@ -3166,7 +3718,7 @@ var createTestConnector = (connector, context) => {
|
|
|
3166
3718
|
},
|
|
3167
3719
|
kline: async (options) => connector.kline(options),
|
|
3168
3720
|
getResult: async () => {
|
|
3169
|
-
const orderLogId = (0,
|
|
3721
|
+
const orderLogId = (0, import_node_crypto3.randomUUID)().slice(-12);
|
|
3170
3722
|
const fullStat = fastMode ? (0, import_backtest.calculateStatsFull)(positionLog) : null;
|
|
3171
3723
|
return {
|
|
3172
3724
|
stat: fullStat ? {
|
|
@@ -4140,7 +4692,7 @@ var prepareTestingData = async (params) => {
|
|
|
4140
4692
|
throw new Error(`Unknown connector: ${connectorName}`);
|
|
4141
4693
|
}
|
|
4142
4694
|
if (!binanceConnector || !coinbaseConnector) {
|
|
4143
|
-
|
|
4695
|
+
import_logger8.logger.warn(
|
|
4144
4696
|
"Binance/Coinbase connectors are unavailable. Reusing %s for BTC references.",
|
|
4145
4697
|
connectorName
|
|
4146
4698
|
);
|
|
@@ -4727,6 +5279,13 @@ var testing = async ({
|
|
|
4727
5279
|
env: "BACKTEST"
|
|
4728
5280
|
})
|
|
4729
5281
|
);
|
|
5282
|
+
await withTimeout(
|
|
5283
|
+
"hyperliquid whale context",
|
|
5284
|
+
enrichSignalWithHyperliquidWhaleContext({
|
|
5285
|
+
signal,
|
|
5286
|
+
env: "BACKTEST"
|
|
5287
|
+
})
|
|
5288
|
+
);
|
|
4730
5289
|
}
|
|
4731
5290
|
if (ml && signal && typeof signal !== "string" && signal.signalId) {
|
|
4732
5291
|
const payload = buildMlPayload({
|
|
@@ -5152,6 +5711,13 @@ var testingGroupInSharedCandleLoop = async (tests) => {
|
|
|
5152
5711
|
env: "BACKTEST"
|
|
5153
5712
|
})
|
|
5154
5713
|
);
|
|
5714
|
+
await withTimeout(
|
|
5715
|
+
"hyperliquid whale context",
|
|
5716
|
+
enrichSignalWithHyperliquidWhaleContext({
|
|
5717
|
+
signal,
|
|
5718
|
+
env: "BACKTEST"
|
|
5719
|
+
})
|
|
5720
|
+
);
|
|
5155
5721
|
}
|
|
5156
5722
|
if (test.ml && signal && typeof signal !== "string" && signal.signalId) {
|
|
5157
5723
|
const payload = buildMlPayload({
|
|
@@ -5262,8 +5828,8 @@ var testingGroupInSharedCandleLoop = async (tests) => {
|
|
|
5262
5828
|
}
|
|
5263
5829
|
return results;
|
|
5264
5830
|
} finally {
|
|
5265
|
-
(0,
|
|
5266
|
-
(0,
|
|
5831
|
+
(0, import_strategies5.releaseStrategyIndicatorsReplayCache)(sharedIndicatorsReplayKey);
|
|
5832
|
+
(0, import_strategies5.releaseStrategyReplayCache)(sharedIndicatorsReplayKey);
|
|
5267
5833
|
}
|
|
5268
5834
|
};
|
|
5269
5835
|
// Annotate the CommonJS export names for ESM import in node:
|