@tradejs/node 2.0.13 → 2.0.15
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/strategies.js
CHANGED
|
@@ -5556,6 +5556,7 @@ __export(strategies_exports, {
|
|
|
5556
5556
|
enrichSignalWithAi: () => enrichSignalWithAi,
|
|
5557
5557
|
enrichSignalWithBinanceMarketContext: () => enrichSignalWithBinanceMarketContext,
|
|
5558
5558
|
enrichSignalWithCoinMarketCapContext: () => enrichSignalWithCoinMarketCapContext,
|
|
5559
|
+
enrichSignalWithHyperliquidWhaleContext: () => enrichSignalWithHyperliquidWhaleContext,
|
|
5559
5560
|
enrichSignalWithMl: () => enrichSignalWithMl,
|
|
5560
5561
|
enrichSignalWithMlAi: () => enrichSignalWithMlAi,
|
|
5561
5562
|
ensureAiStrategyPluginsLoaded: () => ensureAiStrategyPluginsLoaded,
|
|
@@ -5566,6 +5567,10 @@ __export(strategies_exports, {
|
|
|
5566
5567
|
getBinanceBreadthUniverseSnapshot: () => getBinanceBreadthUniverseSnapshot,
|
|
5567
5568
|
getBinanceBreadthUniverses: () => getBinanceBreadthUniverses,
|
|
5568
5569
|
getDeterministicAiGateContext: () => getDeterministicAiGateContext,
|
|
5570
|
+
getHyperliquidPerpSymbols: () => getHyperliquidPerpSymbols,
|
|
5571
|
+
getHyperliquidPerpUniverseSnapshot: () => getHyperliquidPerpUniverseSnapshot,
|
|
5572
|
+
getHyperliquidWhaleAddresses: () => getHyperliquidWhaleAddresses,
|
|
5573
|
+
getHyperliquidWhaleRegistrySnapshot: () => getHyperliquidWhaleRegistrySnapshot,
|
|
5569
5574
|
getOpenRouterModelKwargs: () => getOpenRouterModelKwargs,
|
|
5570
5575
|
getOrderArrivalSnapshot: () => getOrderArrivalSnapshot,
|
|
5571
5576
|
getPrimaryBinanceBreadthUniverse: () => getPrimaryBinanceBreadthUniverse,
|
|
@@ -5574,9 +5579,12 @@ __export(strategies_exports, {
|
|
|
5574
5579
|
getStrategyCreator: () => getStrategyCreator,
|
|
5575
5580
|
getStrategyManifest: () => getStrategyManifest,
|
|
5576
5581
|
isKnownStrategy: () => isKnownStrategy,
|
|
5582
|
+
isTrackedHyperliquidPerp: () => isTrackedHyperliquidPerp,
|
|
5583
|
+
isTrackedHyperliquidWhale: () => isTrackedHyperliquidWhale,
|
|
5577
5584
|
registerStrategyEntries: () => registerStrategyEntries,
|
|
5578
5585
|
resetAiRuntimeCache: () => resetAiRuntimeCache,
|
|
5579
5586
|
resetStrategyRegistryCache: () => resetStrategyRegistryCache,
|
|
5587
|
+
resolveHyperliquidPerpFromSignalSymbol: () => resolveHyperliquidPerpFromSignalSymbol,
|
|
5580
5588
|
resolveStrategyConfig: () => resolveStrategyConfig,
|
|
5581
5589
|
runAiPrompt: () => runAiPrompt,
|
|
5582
5590
|
runAiPromptLocal: () => runAiPromptLocal,
|
|
@@ -6932,7 +6940,7 @@ Input payload structure:
|
|
|
6932
6940
|
\u2022 \`baseContext.raw\`: current MA, ATR, BB, OBV, price stats, levels, BTC correlation.
|
|
6933
6941
|
\u2022 \`baseContext.regime\`: derived trend / volatility / momentum / session regime fields.
|
|
6934
6942
|
\u2022 \`baseContext.structure\`: local range position, breakout freshness/quality, level-touch counts, rejection wick context.
|
|
6935
|
-
\u2022 \`baseContext.participation\`: volume/turnover participation, effort-vs-result context,
|
|
6943
|
+
\u2022 \`baseContext.participation\`: volume/turnover participation, effort-vs-result context, Binance aggTrades, and fingerprinted Hyperliquid whale-flow when available.
|
|
6936
6944
|
\u2022 \`baseContext.relative\`: BTC/ETH relative-strength, benchmark MA bias context, Binance alt-basket breadth, and CoinMarketCap historical global/exchange/index context when available.
|
|
6937
6945
|
\u2022 \`baseContext.derivatives\`: Coinalyze-aligned derivatives summary when available.
|
|
6938
6946
|
\u2022 \`baseContext.mtf\`: compact multi-timeframe summary plus only the latest few candles for each timeframe.
|
|
@@ -7253,12 +7261,12 @@ var askAI = async (signal, options = {}) => {
|
|
|
7253
7261
|
// src/strategyRuntime.ts
|
|
7254
7262
|
var import_node_path2 = __toESM(require("path"));
|
|
7255
7263
|
var import_constants4 = require("@tradejs/core/constants");
|
|
7256
|
-
var
|
|
7257
|
-
var
|
|
7258
|
-
var
|
|
7264
|
+
var import_data3 = require("@tradejs/core/data");
|
|
7265
|
+
var import_strategies5 = require("@tradejs/core/strategies");
|
|
7266
|
+
var import_logger9 = require("@tradejs/infra/logger");
|
|
7259
7267
|
|
|
7260
7268
|
// src/strategyHelpers/runtime.ts
|
|
7261
|
-
var
|
|
7269
|
+
var import_logger8 = require("@tradejs/infra/logger");
|
|
7262
7270
|
var import_constants3 = require("@tradejs/core/constants");
|
|
7263
7271
|
var import_ml2 = require("@tradejs/infra/ml");
|
|
7264
7272
|
|
|
@@ -8856,6 +8864,562 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
|
|
|
8856
8864
|
}
|
|
8857
8865
|
};
|
|
8858
8866
|
|
|
8867
|
+
// src/strategyHelpers/hyperliquidWhaleContext.ts
|
|
8868
|
+
var import_data2 = require("@tradejs/core/data");
|
|
8869
|
+
var import_strategies4 = require("@tradejs/core/strategies");
|
|
8870
|
+
var import_timescale4 = require("@tradejs/infra/timescale");
|
|
8871
|
+
var import_logger7 = require("@tradejs/infra/logger");
|
|
8872
|
+
|
|
8873
|
+
// src/hyperliquidWhaleUniverse.ts
|
|
8874
|
+
var import_node_crypto3 = require("crypto");
|
|
8875
|
+
|
|
8876
|
+
// src/config/hyperliquidPerpUniverse.json
|
|
8877
|
+
var hyperliquidPerpUniverse_default = {
|
|
8878
|
+
schemaVersion: 1,
|
|
8879
|
+
updatedAt: "2026-08-04T11:46:43.476Z",
|
|
8880
|
+
source: "hyperliquid_main_perp_day_notional_volume",
|
|
8881
|
+
fingerprint: "58f7e024b19158dc",
|
|
8882
|
+
size: 30,
|
|
8883
|
+
symbols: [
|
|
8884
|
+
"BTC",
|
|
8885
|
+
"ETH",
|
|
8886
|
+
"HYPE",
|
|
8887
|
+
"SOL",
|
|
8888
|
+
"ZEC",
|
|
8889
|
+
"PUMP",
|
|
8890
|
+
"XRP",
|
|
8891
|
+
"CASHCAT",
|
|
8892
|
+
"WLD",
|
|
8893
|
+
"GRAM",
|
|
8894
|
+
"UNI",
|
|
8895
|
+
"ADA",
|
|
8896
|
+
"LIT",
|
|
8897
|
+
"ENA",
|
|
8898
|
+
"NEAR",
|
|
8899
|
+
"kPEPE",
|
|
8900
|
+
"FARTCOIN",
|
|
8901
|
+
"KAITO",
|
|
8902
|
+
"AAVE",
|
|
8903
|
+
"SUI",
|
|
8904
|
+
"ONDO",
|
|
8905
|
+
"AVAX",
|
|
8906
|
+
"DOGE",
|
|
8907
|
+
"VVV",
|
|
8908
|
+
"BNB",
|
|
8909
|
+
"ALGO",
|
|
8910
|
+
"XMR",
|
|
8911
|
+
"MEGA",
|
|
8912
|
+
"LINK",
|
|
8913
|
+
"TAO"
|
|
8914
|
+
]
|
|
8915
|
+
};
|
|
8916
|
+
|
|
8917
|
+
// src/config/hyperliquidWhales.json
|
|
8918
|
+
var hyperliquidWhales_default = {
|
|
8919
|
+
schemaVersion: 2,
|
|
8920
|
+
updatedAt: "2026-08-04T15:10:21.316Z",
|
|
8921
|
+
source: "hyperliquid_structural_fills_snapshot",
|
|
8922
|
+
selection: {
|
|
8923
|
+
calibrationFrom: "2026-07-28T00:00:00.000Z",
|
|
8924
|
+
calibrationTo: "2026-08-04T00:00:00.000Z",
|
|
8925
|
+
effectiveFrom: "2026-08-04T00:00:00.000Z",
|
|
8926
|
+
candidateLimit: 400,
|
|
8927
|
+
minimumAccountValueUsd: 5e5,
|
|
8928
|
+
minimumActiveDays: 1,
|
|
8929
|
+
maximumRawFillsPerDay: 20,
|
|
8930
|
+
maximumDirectionalExecutionsPerDay: 10,
|
|
8931
|
+
minimumMedianNotionalUsd: 0,
|
|
8932
|
+
minimumMedianInterExecutionMinutes: 0,
|
|
8933
|
+
minimumTop30NotionalShare: 1e-3,
|
|
8934
|
+
minimumTurnoverToEquity: 0.05,
|
|
8935
|
+
maximumTurnoverToEquity: 5,
|
|
8936
|
+
score: "log1p(accountValue)*log1p(medianExecutionNotional)*log1p(max(1,medianInterExecutionMinutes))*sqrt(activeDays)*top30Share/sqrt(1+rawFillsPerDay)",
|
|
8937
|
+
forbiddenSelectionMetrics: ["pnl", "roi", "winRate", "closedPnl"]
|
|
8938
|
+
},
|
|
8939
|
+
fingerprint: "77a6e9d41222efdb",
|
|
8940
|
+
size: 100,
|
|
8941
|
+
addresses: [
|
|
8942
|
+
"0xacb66d1996501bcc82a0e7819c9e041599f5efbd",
|
|
8943
|
+
"0x90dbb196cacf24bd212b377a0dd62eaad5e8151b",
|
|
8944
|
+
"0xde5b8c8e713f7c29ec72c22a326d61e5ac76e402",
|
|
8945
|
+
"0x22edc38749b59c31c9319eae7fc62143ac2fcc6c",
|
|
8946
|
+
"0x4bc9a771cd2c96cb2a4501f2c049402b4e7e11b3",
|
|
8947
|
+
"0x9a0825ca6c4c577a1202a8fae3b8f044c1d5711d",
|
|
8948
|
+
"0xb6ca5d1ed0ca4bf8444c9dee2d068a9f4c5e2e92",
|
|
8949
|
+
"0xc3610d02548cdb1a30ede87c5dc0d2ffe5b9b99f",
|
|
8950
|
+
"0x48c6aaa647ad5197e85797f8eb95d7b9ce1ec5b6",
|
|
8951
|
+
"0x8c1ab015da7e5319649afca4a551924f89eff883",
|
|
8952
|
+
"0x64bddab5f13a99576fca6747f0aa205422c5f708",
|
|
8953
|
+
"0x98785f2a43fe32f972476b86ed5a5cfaf5240f00",
|
|
8954
|
+
"0x9836e286fbf4f71998827d4bd6ea3b470c26457e",
|
|
8955
|
+
"0x8f8d2d2565bfb10608a7ce64b48e2aea7875a344",
|
|
8956
|
+
"0xe6df4ed7a6ccb8426cbc87bdcdd3cc6d0e6c0690",
|
|
8957
|
+
"0xab04d040dec929a204298d44701476968b238b69",
|
|
8958
|
+
"0x870f718a84843abc3e22412a9b4dc2924466d448",
|
|
8959
|
+
"0x12c206d3e2f0d0059420c54d33fe604ebbecc230",
|
|
8960
|
+
"0x7d9e91a8a47eb553cbfd323e7633c0c213327124",
|
|
8961
|
+
"0x2057d4f2b6ea957b63371980775b0a5505a438f0",
|
|
8962
|
+
"0xead5b7d86c681c036c59cd00a0390541061c69f2",
|
|
8963
|
+
"0x3005fade4c0df5e1cd187d7062da359416f0eb8e",
|
|
8964
|
+
"0xe83b5e3644b50e802a25b34b38b91a061a0d3ca8",
|
|
8965
|
+
"0x525232cb6ed5030d2b052b36bfc0baec96986ee3",
|
|
8966
|
+
"0xa251520154ca342f0b1d702bf5a56f78c982405b",
|
|
8967
|
+
"0xa9184bb57fd75c7c63e4c074d6319eceac6be53b",
|
|
8968
|
+
"0xa20fb0c9e04063eec5be286e9269028d966646fa",
|
|
8969
|
+
"0x169ba96d963e77a87dbe58922ecdcdd0f0cf3315",
|
|
8970
|
+
"0x115849ce84370f25cadcf0d348510d73837e1aa5",
|
|
8971
|
+
"0x37b81ab9e3ab04b9e3738e4891621205aaa31fd5",
|
|
8972
|
+
"0x90f57d90a7dd3114312d4c31803ad5732baf5935",
|
|
8973
|
+
"0xad227f63d34e7251c1d0ab65e64eeea07aee4e44",
|
|
8974
|
+
"0xd38e2b0b3c85ae138532f9fe1a1d5f5455866b82",
|
|
8975
|
+
"0xf5f4c3aa62a0f903a8529905031b1536d1cf16f8",
|
|
8976
|
+
"0x75632aaf83120eae9b0618f8f50773ce347de2ad",
|
|
8977
|
+
"0x3927af597c09774f91ef84bf765ded4109e9f8ea",
|
|
8978
|
+
"0xf1863bd6d60a8f4b5f583ec54009af6a044877bf",
|
|
8979
|
+
"0xe7b34f28c54f85533896f8827edc92edac28b17f",
|
|
8980
|
+
"0x1cda20f9f6a23c209d54940af3ef63b96c9b2c31",
|
|
8981
|
+
"0x9e55b0e43b7f7f3909af841d326b2dadfda9392e",
|
|
8982
|
+
"0x610b8dd6b392d010c2b6ad8d121dfc09524cb613",
|
|
8983
|
+
"0x1d639a688b78f3d7e57166e59d9a8886b1bfb5a5",
|
|
8984
|
+
"0x34d3a17095ef7def39a489d63c7c916e673c9ca2",
|
|
8985
|
+
"0x5d0bde4017530ed43370e332a5d30194941f73c6",
|
|
8986
|
+
"0xaa7afc250041e2c56a06d3b7a5295bd01929e11b",
|
|
8987
|
+
"0x325edd95bb016c36027ce3b9f7595af7094a9564",
|
|
8988
|
+
"0x47f5a6397b79deaaca5c456503e7c1a49357b942",
|
|
8989
|
+
"0xf5e7ffe523d0491709958490b4877e1d9de6c6f7",
|
|
8990
|
+
"0x64702807a1f0f9888ea22b858099d7f481227b55",
|
|
8991
|
+
"0xd08a4557671ca465e7bba41110a93148c90f9931",
|
|
8992
|
+
"0x0423b4b2acb4f219ae4a270abd5dde2360e455bb",
|
|
8993
|
+
"0x7b29f8c0ea709b96b72214b3de5d85c3d9570794",
|
|
8994
|
+
"0xeb8ebad162a9ce4cb7e2325c92b960b9df63365c",
|
|
8995
|
+
"0x939f95036d2e7b6d7419ec072bf9d967352204d2",
|
|
8996
|
+
"0x2490aa2b48022e857d44e738911787c8e2296aed",
|
|
8997
|
+
"0x7622f628135378f1b8d1876952de9bab80245f1c",
|
|
8998
|
+
"0x9d677028e0e592d48fc8a8ddc910693301a4a450",
|
|
8999
|
+
"0x85e410e4c535cb1709dbd36468f132037a5b2087",
|
|
9000
|
+
"0xd6f52e2ab58a678eced4a4d1693757b0677631c8",
|
|
9001
|
+
"0x24d8969e2bd6aabb6c4dfe042ef8b2cd8085217e",
|
|
9002
|
+
"0xda51323fe9800c8365646ad5c7ade0dd17fdc167",
|
|
9003
|
+
"0x53f8f390fd4f70941c5d160a964f6893c8dbceff",
|
|
9004
|
+
"0x72dae3560e7f4c59a305e2e739d6bd6777f738b5",
|
|
9005
|
+
"0x36f5e448c9cf0032551e58919cf4eabefcd742c1",
|
|
9006
|
+
"0x5b43b7162694de766c164202df0f0c716e4292ab",
|
|
9007
|
+
"0xae551d73161bac3315c5ade0e2d499a44ebe2236",
|
|
9008
|
+
"0x4eca8d62e07b3f3e78a8ae8725d4666da324c5a8",
|
|
9009
|
+
"0x40a632026febd007b0e4431a29170507f7aa3896",
|
|
9010
|
+
"0xd453e91f692eb5437cf345e09545827576e3225d",
|
|
9011
|
+
"0xbe2c69eb3d7b8ee35cbe3a28293472be31179d75",
|
|
9012
|
+
"0xfdf891f2b214a4c9374d26595ec6d4080262e381",
|
|
9013
|
+
"0xfd97600ac44b3c4e20ac1a5f23e3b18d10fa5912",
|
|
9014
|
+
"0x98e073b579fd483eac8f10d5bd0b32c8c3bbd7e0",
|
|
9015
|
+
"0xb56f19e917546a60d658110a611cf62a6877b517",
|
|
9016
|
+
"0xbd334a55db91617545e8d1b09941e036ad8e4200",
|
|
9017
|
+
"0x9f1920d0cbb63ed03376a1e09fd2851d601234c8",
|
|
9018
|
+
"0xe9cef9fd872a03cedf9d3e6e90309782b3724ea6",
|
|
9019
|
+
"0xa43682a1f129e4faf0152175cc03c44e4957e8cf",
|
|
9020
|
+
"0x6fbb33de5f39c690d2decb95b9ab46ed0c83e3bc",
|
|
9021
|
+
"0x81d4163289cf61a0eaaac4862cb88ef0f4215c29",
|
|
9022
|
+
"0xd248d2f09bfbe04e67fc7fea08828d6ad6d95b6d",
|
|
9023
|
+
"0x01ffcc7285866e5cee14c8e807cb2e8d5f61079f",
|
|
9024
|
+
"0xc69ae428f6049e78d445f053d2c1df879c59b34c",
|
|
9025
|
+
"0xaab4dfe6d735c4ac46217216fe883a39fbfe8284",
|
|
9026
|
+
"0xe912cac1a6641004a8803687ee7699227fdb0550",
|
|
9027
|
+
"0x5fdbf83c3d95d525704f61401db68cbec1b2a775",
|
|
9028
|
+
"0xebd7c4b3677a4480fb5f69ac2f51c51d66a19990",
|
|
9029
|
+
"0xe4d1fa7e6141f9131345117bdb8b5701bca67662",
|
|
9030
|
+
"0x685feceec46dd4e5c9b5b726f5d7550fd0eda526",
|
|
9031
|
+
"0x3ea8b09da72972e953541500721803a187526da6",
|
|
9032
|
+
"0xdbe0780a5c5a0e3b345101bbc01ac2218196d6d5",
|
|
9033
|
+
"0x18cd4597e06b7fe0a8cd33dda499121b3a145a8b",
|
|
9034
|
+
"0xb8243756956e722bff5c763971b562ac551bfbd2",
|
|
9035
|
+
"0xe0bf8c96795d2df0b61b3b17e7cfd7d3ba13d4be",
|
|
9036
|
+
"0x218a65e21eddeece7a9df38c6bbdd89f692b7da2",
|
|
9037
|
+
"0x53b63a30a688beb53b5dc7bd731c661d678c555c",
|
|
9038
|
+
"0xfce053a5e461683454bf37ad66d20344c0e3f4c0",
|
|
9039
|
+
"0x3e516cf3c9d4f29fae6c1324c2414dc872fc9c09",
|
|
9040
|
+
"0xe5f1486dc84706d2509885fe6bbc46d21ba81286",
|
|
9041
|
+
"0x38042d713af713f0275b00640a83654db91ea543"
|
|
9042
|
+
]
|
|
9043
|
+
};
|
|
9044
|
+
|
|
9045
|
+
// src/hyperliquidWhaleUniverse.ts
|
|
9046
|
+
var fingerprint2 = (value) => (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(value)).digest("hex").slice(0, 16);
|
|
9047
|
+
var validateUnique = (values, label) => {
|
|
9048
|
+
if (new Set(values).size !== values.length) {
|
|
9049
|
+
throw new Error(`Hyperliquid ${label} snapshot contains duplicates`);
|
|
9050
|
+
}
|
|
9051
|
+
};
|
|
9052
|
+
var validatePerpSnapshot = (value) => {
|
|
9053
|
+
const symbols = value.symbols.map((symbol) => symbol.trim()).filter(Boolean);
|
|
9054
|
+
validateUnique(symbols, "perp universe");
|
|
9055
|
+
if (value.schemaVersion !== 1 || value.source !== "hyperliquid_main_perp_day_notional_volume" || value.size !== 30 || symbols.length !== 30 || value.fingerprint !== fingerprint2(symbols)) {
|
|
9056
|
+
throw new Error("Invalid Hyperliquid perp universe snapshot");
|
|
9057
|
+
}
|
|
9058
|
+
return value;
|
|
9059
|
+
};
|
|
9060
|
+
var validateWhaleSnapshot = (value) => {
|
|
9061
|
+
const addresses = value.addresses.map((address) => address.toLowerCase());
|
|
9062
|
+
validateUnique(addresses, "whale registry");
|
|
9063
|
+
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)) {
|
|
9064
|
+
throw new Error("Invalid Hyperliquid whale registry snapshot");
|
|
9065
|
+
}
|
|
9066
|
+
return value;
|
|
9067
|
+
};
|
|
9068
|
+
var perpSnapshot = validatePerpSnapshot(hyperliquidPerpUniverse_default);
|
|
9069
|
+
var whaleSnapshot = validateWhaleSnapshot(hyperliquidWhales_default);
|
|
9070
|
+
var perpSymbolSet = new Set(perpSnapshot.symbols);
|
|
9071
|
+
var whaleAddressSet = new Set(whaleSnapshot.addresses);
|
|
9072
|
+
var getHyperliquidPerpUniverseSnapshot = () => perpSnapshot;
|
|
9073
|
+
var getHyperliquidWhaleRegistrySnapshot = () => whaleSnapshot;
|
|
9074
|
+
var getHyperliquidPerpSymbols = () => [...perpSnapshot.symbols];
|
|
9075
|
+
var getHyperliquidWhaleAddresses = () => [...whaleSnapshot.addresses];
|
|
9076
|
+
var isTrackedHyperliquidPerp = (symbol) => perpSymbolSet.has(symbol.trim());
|
|
9077
|
+
var isTrackedHyperliquidWhale = (address) => whaleAddressSet.has(address.trim().toLowerCase());
|
|
9078
|
+
var SIGNAL_TO_HYPERLIQUID_ALIASES = {
|
|
9079
|
+
PEPE: "kPEPE",
|
|
9080
|
+
"1000PEPE": "kPEPE",
|
|
9081
|
+
PUMPFUN: "PUMP",
|
|
9082
|
+
SHIB: "kSHIB",
|
|
9083
|
+
BONK: "kBONK"
|
|
9084
|
+
};
|
|
9085
|
+
var resolveHyperliquidPerpFromSignalSymbol = (symbol) => {
|
|
9086
|
+
const normalized = symbol.trim().toUpperCase().replace(/(?:USDT|USDC)$/, "");
|
|
9087
|
+
const candidate = SIGNAL_TO_HYPERLIQUID_ALIASES[normalized] ?? normalized;
|
|
9088
|
+
return perpSymbolSet.has(candidate) ? candidate : null;
|
|
9089
|
+
};
|
|
9090
|
+
|
|
9091
|
+
// src/strategyHelpers/hyperliquidWhaleContext.ts
|
|
9092
|
+
var MAX_CACHE_ENTRIES = 2048;
|
|
9093
|
+
var MAX_COVERAGE_SERIES_CACHE_ENTRIES = 20;
|
|
9094
|
+
var MAX_FLOW_SERIES_CACHE_ENTRIES = 64;
|
|
9095
|
+
var SERIES_CHUNK_MS = 30 * 24 * 60 * 6e4;
|
|
9096
|
+
var MAX_SERIES_LOOKBACK_MS = 60 * 6e4;
|
|
9097
|
+
var DEFAULT_MIN_COVERAGE_PCT = 0.8;
|
|
9098
|
+
var INTERVAL_MS = {
|
|
9099
|
+
"1m": 6e4,
|
|
9100
|
+
"5m": 5 * 6e4,
|
|
9101
|
+
"15m": 15 * 6e4,
|
|
9102
|
+
"1h": 60 * 6e4
|
|
9103
|
+
};
|
|
9104
|
+
var DEFAULT_MAX_AGE_BY_INTERVAL2 = {
|
|
9105
|
+
"1m": 2 * 6e4,
|
|
9106
|
+
"5m": 10 * 6e4,
|
|
9107
|
+
"15m": 30 * 6e4,
|
|
9108
|
+
"1h": 2 * 60 * 6e4
|
|
9109
|
+
};
|
|
9110
|
+
var hyperliquidWhaleContextUnavailable = false;
|
|
9111
|
+
var contextCache = /* @__PURE__ */ new Map();
|
|
9112
|
+
var coverageSeriesCache = /* @__PURE__ */ new Map();
|
|
9113
|
+
var flowSeriesCache = /* @__PURE__ */ new Map();
|
|
9114
|
+
var parseEnabledFlag4 = (value, env) => {
|
|
9115
|
+
const normalized = String(value ?? "").trim().toLowerCase();
|
|
9116
|
+
if (!normalized) return env !== "TEST";
|
|
9117
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
9118
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
9119
|
+
if (normalized === "backtest") return env === "BACKTEST";
|
|
9120
|
+
if (normalized === "live") return env !== "BACKTEST";
|
|
9121
|
+
return false;
|
|
9122
|
+
};
|
|
9123
|
+
var getMinimumCoveragePct = () => {
|
|
9124
|
+
const parsed = Number(process.env.HYPERLIQUID_WHALE_MIN_COVERAGE_PCT);
|
|
9125
|
+
return Number.isFinite(parsed) ? Math.max(0, Math.min(1, parsed)) : DEFAULT_MIN_COVERAGE_PCT;
|
|
9126
|
+
};
|
|
9127
|
+
var signalIntervalToMarketInterval2 = (value) => {
|
|
9128
|
+
const normalized = String(value).trim().toLowerCase();
|
|
9129
|
+
if (normalized === "1" || normalized === "1m") return "1m";
|
|
9130
|
+
if (normalized === "5" || normalized === "5m") return "5m";
|
|
9131
|
+
if (normalized === "60" || normalized === "1h") return "1h";
|
|
9132
|
+
return "15m";
|
|
9133
|
+
};
|
|
9134
|
+
var hasBaseContext3 = (signal) => Boolean(
|
|
9135
|
+
signal.additionalIndicators?.baseContext && typeof signal.additionalIndicators.baseContext === "object" && !Array.isArray(signal.additionalIndicators.baseContext)
|
|
9136
|
+
);
|
|
9137
|
+
var setBoundedCache = (key, value) => {
|
|
9138
|
+
if (contextCache.size >= MAX_CACHE_ENTRIES) {
|
|
9139
|
+
const oldestKey = contextCache.keys().next().value;
|
|
9140
|
+
if (oldestKey != null) contextCache.delete(oldestKey);
|
|
9141
|
+
}
|
|
9142
|
+
contextCache.set(key, value);
|
|
9143
|
+
};
|
|
9144
|
+
var setBoundedSeriesCache = (cache, maxEntries, key, value) => {
|
|
9145
|
+
if (cache.size >= maxEntries) {
|
|
9146
|
+
const oldestKey = cache.keys().next().value;
|
|
9147
|
+
if (oldestKey != null) cache.delete(oldestKey);
|
|
9148
|
+
}
|
|
9149
|
+
cache.set(key, value);
|
|
9150
|
+
};
|
|
9151
|
+
var uniqueAddressCount = (rows, field) => {
|
|
9152
|
+
const addresses = /* @__PURE__ */ new Set();
|
|
9153
|
+
for (const row of rows) {
|
|
9154
|
+
for (const address of row[field]) addresses.add(address);
|
|
9155
|
+
}
|
|
9156
|
+
return addresses.size;
|
|
9157
|
+
};
|
|
9158
|
+
var sumFlowField = (rows, field) => rows.reduce((sum, row) => sum + row[field], 0);
|
|
9159
|
+
var sliceSeriesWindow = (rows, fromMs, toMs) => {
|
|
9160
|
+
const lowerBound = (timestamp) => {
|
|
9161
|
+
let low = 0;
|
|
9162
|
+
let high = rows.length;
|
|
9163
|
+
while (low < high) {
|
|
9164
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
9165
|
+
if (rows[middle].ts.getTime() < timestamp) low = middle + 1;
|
|
9166
|
+
else high = middle;
|
|
9167
|
+
}
|
|
9168
|
+
return low;
|
|
9169
|
+
};
|
|
9170
|
+
return rows.slice(lowerBound(fromMs), lowerBound(toMs));
|
|
9171
|
+
};
|
|
9172
|
+
var aggregateHyperliquidWhaleFlowSeries = (params) => {
|
|
9173
|
+
const intervalMs = INTERVAL_MS[params.interval];
|
|
9174
|
+
const windowStartMs = params.decisionTimeMs - intervalMs;
|
|
9175
|
+
const coverageRows = sliceSeriesWindow(
|
|
9176
|
+
params.coverageRows,
|
|
9177
|
+
windowStartMs,
|
|
9178
|
+
params.decisionTimeMs
|
|
9179
|
+
);
|
|
9180
|
+
const expectedBuckets = Math.ceil(intervalMs / 6e4);
|
|
9181
|
+
if (coverageRows.length !== expectedBuckets || coverageRows.some((row) => row.coveredWhales <= 0)) {
|
|
9182
|
+
return null;
|
|
9183
|
+
}
|
|
9184
|
+
const flowRows = sliceSeriesWindow(
|
|
9185
|
+
params.flowRows,
|
|
9186
|
+
windowStartMs,
|
|
9187
|
+
params.decisionTimeMs
|
|
9188
|
+
);
|
|
9189
|
+
const asOfTs = new Date(
|
|
9190
|
+
Math.max(...coverageRows.map((row) => row.ts.getTime()))
|
|
9191
|
+
);
|
|
9192
|
+
const coveredWhales = Math.min(
|
|
9193
|
+
...coverageRows.map((row) => row.coveredWhales)
|
|
9194
|
+
);
|
|
9195
|
+
const expectedWhales = Math.max(
|
|
9196
|
+
...coverageRows.map((row) => row.expectedWhales)
|
|
9197
|
+
);
|
|
9198
|
+
const coveragePct = Math.min(...coverageRows.map((row) => row.coveragePct));
|
|
9199
|
+
const trades = sumFlowField(flowRows, "trades");
|
|
9200
|
+
const whaleSides = sumFlowField(flowRows, "whaleSides");
|
|
9201
|
+
const buyNotionalUsd = sumFlowField(flowRows, "buyNotionalUsd");
|
|
9202
|
+
const sellNotionalUsd = sumFlowField(flowRows, "sellNotionalUsd");
|
|
9203
|
+
const positionAwareWhaleSides = sumFlowField(
|
|
9204
|
+
flowRows,
|
|
9205
|
+
"positionAwareWhaleSides"
|
|
9206
|
+
);
|
|
9207
|
+
const longEntryNotionalUsd = sumFlowField(flowRows, "longEntryNotionalUsd");
|
|
9208
|
+
const shortEntryNotionalUsd = sumFlowField(flowRows, "shortEntryNotionalUsd");
|
|
9209
|
+
const longExitNotionalUsd = sumFlowField(flowRows, "longExitNotionalUsd");
|
|
9210
|
+
const shortExitNotionalUsd = sumFlowField(flowRows, "shortExitNotionalUsd");
|
|
9211
|
+
const totalNotionalUsd = buyNotionalUsd + sellNotionalUsd;
|
|
9212
|
+
const totalEntryNotionalUsd = longEntryNotionalUsd + shortEntryNotionalUsd;
|
|
9213
|
+
const ageMs = params.decisionTimeMs - (asOfTs.getTime() + 6e4);
|
|
9214
|
+
return {
|
|
9215
|
+
symbol: params.symbol,
|
|
9216
|
+
interval: params.interval,
|
|
9217
|
+
asOfTs,
|
|
9218
|
+
windowEndTs: new Date(params.decisionTimeMs),
|
|
9219
|
+
trades,
|
|
9220
|
+
whaleSides,
|
|
9221
|
+
uniqueWhales: uniqueAddressCount(flowRows, "whaleAddresses"),
|
|
9222
|
+
coveredWhales,
|
|
9223
|
+
expectedWhales,
|
|
9224
|
+
coveragePct,
|
|
9225
|
+
buyNotionalUsd,
|
|
9226
|
+
sellNotionalUsd,
|
|
9227
|
+
netNotionalUsd: buyNotionalUsd - sellNotionalUsd,
|
|
9228
|
+
buySharePct: totalNotionalUsd > 0 ? buyNotionalUsd / totalNotionalUsd : null,
|
|
9229
|
+
positionAwareWhaleSides,
|
|
9230
|
+
positionAwarePct: whaleSides > 0 ? positionAwareWhaleSides / whaleSides : 0,
|
|
9231
|
+
longEntryWhales: uniqueAddressCount(flowRows, "longEntryWhaleAddresses"),
|
|
9232
|
+
shortEntryWhales: uniqueAddressCount(flowRows, "shortEntryWhaleAddresses"),
|
|
9233
|
+
longExitWhales: uniqueAddressCount(flowRows, "longExitWhaleAddresses"),
|
|
9234
|
+
shortExitWhales: uniqueAddressCount(flowRows, "shortExitWhaleAddresses"),
|
|
9235
|
+
longEntryNotionalUsd,
|
|
9236
|
+
shortEntryNotionalUsd,
|
|
9237
|
+
longExitNotionalUsd,
|
|
9238
|
+
shortExitNotionalUsd,
|
|
9239
|
+
entryNetNotionalUsd: longEntryNotionalUsd - shortEntryNotionalUsd,
|
|
9240
|
+
entryLongSharePct: totalEntryNotionalUsd > 0 ? longEntryNotionalUsd / totalEntryNotionalUsd : null,
|
|
9241
|
+
universeFingerprint: params.universeFingerprint,
|
|
9242
|
+
whaleRegistryFingerprint: params.whaleRegistryFingerprint,
|
|
9243
|
+
source: positionAwareWhaleSides > 0 ? "hyperliquid_user_fills" : null,
|
|
9244
|
+
ageMs,
|
|
9245
|
+
stale: ageMs < 0 || (params.maxAgeMs != null && Number.isFinite(params.maxAgeMs) ? ageMs > params.maxAgeMs : false)
|
|
9246
|
+
};
|
|
9247
|
+
};
|
|
9248
|
+
var loadHyperliquidWhaleFlowAggregateFromSeries = async (params) => {
|
|
9249
|
+
const chunkStartMs = Math.floor(params.decisionTimeMs / SERIES_CHUNK_MS) * SERIES_CHUNK_MS;
|
|
9250
|
+
const fromMs = chunkStartMs - MAX_SERIES_LOOKBACK_MS;
|
|
9251
|
+
const toMs = chunkStartMs + SERIES_CHUNK_MS;
|
|
9252
|
+
const sharedKey = [
|
|
9253
|
+
fromMs,
|
|
9254
|
+
toMs,
|
|
9255
|
+
params.universeFingerprint,
|
|
9256
|
+
params.whaleRegistryFingerprint
|
|
9257
|
+
].join(":");
|
|
9258
|
+
let pendingCoverage = coverageSeriesCache.get(sharedKey);
|
|
9259
|
+
if (!pendingCoverage) {
|
|
9260
|
+
pendingCoverage = (0, import_timescale4.getHyperliquidWhaleCoverageSeriesRows)({
|
|
9261
|
+
fromMs,
|
|
9262
|
+
toMs,
|
|
9263
|
+
universeFingerprint: params.universeFingerprint,
|
|
9264
|
+
whaleRegistryFingerprint: params.whaleRegistryFingerprint
|
|
9265
|
+
});
|
|
9266
|
+
setBoundedSeriesCache(
|
|
9267
|
+
coverageSeriesCache,
|
|
9268
|
+
MAX_COVERAGE_SERIES_CACHE_ENTRIES,
|
|
9269
|
+
sharedKey,
|
|
9270
|
+
pendingCoverage
|
|
9271
|
+
);
|
|
9272
|
+
}
|
|
9273
|
+
const flowKey = `${params.symbol}:${sharedKey}`;
|
|
9274
|
+
let pendingFlow = flowSeriesCache.get(flowKey);
|
|
9275
|
+
if (!pendingFlow) {
|
|
9276
|
+
pendingFlow = (0, import_timescale4.getHyperliquidWhaleFlowSeriesRows)({
|
|
9277
|
+
symbol: params.symbol,
|
|
9278
|
+
fromMs,
|
|
9279
|
+
toMs,
|
|
9280
|
+
universeFingerprint: params.universeFingerprint,
|
|
9281
|
+
whaleRegistryFingerprint: params.whaleRegistryFingerprint
|
|
9282
|
+
});
|
|
9283
|
+
setBoundedSeriesCache(
|
|
9284
|
+
flowSeriesCache,
|
|
9285
|
+
MAX_FLOW_SERIES_CACHE_ENTRIES,
|
|
9286
|
+
flowKey,
|
|
9287
|
+
pendingFlow
|
|
9288
|
+
);
|
|
9289
|
+
}
|
|
9290
|
+
const [coverageRows, flowRows] = await Promise.all([
|
|
9291
|
+
pendingCoverage,
|
|
9292
|
+
pendingFlow
|
|
9293
|
+
]);
|
|
9294
|
+
return aggregateHyperliquidWhaleFlowSeries({
|
|
9295
|
+
...params,
|
|
9296
|
+
coverageRows,
|
|
9297
|
+
flowRows
|
|
9298
|
+
});
|
|
9299
|
+
};
|
|
9300
|
+
var toBaseHyperliquidWhaleFlowContext = (row, minimumCoveragePct) => ({
|
|
9301
|
+
source: row.positionAwareWhaleSides > 0 ? "hyperliquid_user_fills" : "hyperliquid_trades",
|
|
9302
|
+
interval: row.interval,
|
|
9303
|
+
asOfTs: row.asOfTs.getTime(),
|
|
9304
|
+
windowEndTs: row.windowEndTs.getTime(),
|
|
9305
|
+
ageMs: row.ageMs,
|
|
9306
|
+
stale: row.stale,
|
|
9307
|
+
symbol: row.symbol,
|
|
9308
|
+
trades: row.trades,
|
|
9309
|
+
whaleSides: row.whaleSides,
|
|
9310
|
+
uniqueWhales: row.uniqueWhales,
|
|
9311
|
+
coveredWhales: row.coveredWhales,
|
|
9312
|
+
expectedWhales: row.expectedWhales,
|
|
9313
|
+
coveragePct: row.coveragePct,
|
|
9314
|
+
coverageSufficient: row.coveragePct >= minimumCoveragePct,
|
|
9315
|
+
buyNotionalUsd: row.buyNotionalUsd,
|
|
9316
|
+
sellNotionalUsd: row.sellNotionalUsd,
|
|
9317
|
+
netNotionalUsd: row.netNotionalUsd,
|
|
9318
|
+
buySharePct: row.buySharePct,
|
|
9319
|
+
positionAwareWhaleSides: row.positionAwareWhaleSides,
|
|
9320
|
+
positionAwarePct: row.positionAwarePct,
|
|
9321
|
+
longEntryWhales: row.longEntryWhales,
|
|
9322
|
+
shortEntryWhales: row.shortEntryWhales,
|
|
9323
|
+
longExitWhales: row.longExitWhales,
|
|
9324
|
+
shortExitWhales: row.shortExitWhales,
|
|
9325
|
+
longEntryNotionalUsd: row.longEntryNotionalUsd,
|
|
9326
|
+
shortEntryNotionalUsd: row.shortEntryNotionalUsd,
|
|
9327
|
+
longExitNotionalUsd: row.longExitNotionalUsd,
|
|
9328
|
+
shortExitNotionalUsd: row.shortExitNotionalUsd,
|
|
9329
|
+
entryNetNotionalUsd: row.entryNetNotionalUsd,
|
|
9330
|
+
entryLongSharePct: row.entryLongSharePct,
|
|
9331
|
+
universeFingerprint: row.universeFingerprint,
|
|
9332
|
+
whaleRegistryFingerprint: row.whaleRegistryFingerprint
|
|
9333
|
+
});
|
|
9334
|
+
var isHyperliquidWhaleContextEnabled = (env) => parseEnabledFlag4(process.env.HYPERLIQUID_WHALE_CONTEXT_ENABLED, env);
|
|
9335
|
+
var loadHyperliquidWhaleFlowContext = async (params) => {
|
|
9336
|
+
if (!(params.enabled ?? isHyperliquidWhaleContextEnabled(params.env)) || hyperliquidWhaleContextUnavailable || params.interval == null) {
|
|
9337
|
+
return null;
|
|
9338
|
+
}
|
|
9339
|
+
const symbol = resolveHyperliquidPerpFromSignalSymbol(params.symbol);
|
|
9340
|
+
if (!symbol) return null;
|
|
9341
|
+
const interval = params.marketInterval ?? signalIntervalToMarketInterval2(params.interval);
|
|
9342
|
+
const decisionTimeMs = params.timestamp + (0, import_data2.intervalToMs)(params.interval);
|
|
9343
|
+
const maxAgeMs = params.maxAgeMs ?? DEFAULT_MAX_AGE_BY_INTERVAL2[interval];
|
|
9344
|
+
const universe = getHyperliquidPerpUniverseSnapshot();
|
|
9345
|
+
const whales = getHyperliquidWhaleRegistrySnapshot();
|
|
9346
|
+
const minimumCoveragePct = getMinimumCoveragePct();
|
|
9347
|
+
const cacheKey = [
|
|
9348
|
+
symbol,
|
|
9349
|
+
interval,
|
|
9350
|
+
decisionTimeMs,
|
|
9351
|
+
maxAgeMs,
|
|
9352
|
+
universe.fingerprint,
|
|
9353
|
+
whales.fingerprint,
|
|
9354
|
+
minimumCoveragePct
|
|
9355
|
+
].join(":");
|
|
9356
|
+
try {
|
|
9357
|
+
let row;
|
|
9358
|
+
if (params.useSeriesCache) {
|
|
9359
|
+
row = await loadHyperliquidWhaleFlowAggregateFromSeries({
|
|
9360
|
+
symbol,
|
|
9361
|
+
interval,
|
|
9362
|
+
decisionTimeMs,
|
|
9363
|
+
maxAgeMs,
|
|
9364
|
+
universeFingerprint: universe.fingerprint,
|
|
9365
|
+
whaleRegistryFingerprint: whales.fingerprint
|
|
9366
|
+
});
|
|
9367
|
+
} else {
|
|
9368
|
+
let pending = contextCache.get(cacheKey);
|
|
9369
|
+
if (!pending) {
|
|
9370
|
+
pending = (0, import_timescale4.getHyperliquidWhaleFlowAggregate)({
|
|
9371
|
+
symbol,
|
|
9372
|
+
interval,
|
|
9373
|
+
decisionTimeMs,
|
|
9374
|
+
maxAgeMs,
|
|
9375
|
+
universeFingerprint: universe.fingerprint,
|
|
9376
|
+
whaleRegistryFingerprint: whales.fingerprint
|
|
9377
|
+
});
|
|
9378
|
+
setBoundedCache(cacheKey, pending);
|
|
9379
|
+
}
|
|
9380
|
+
row = await pending;
|
|
9381
|
+
}
|
|
9382
|
+
if (!row) return null;
|
|
9383
|
+
return toBaseHyperliquidWhaleFlowContext(row, minimumCoveragePct);
|
|
9384
|
+
} catch (error) {
|
|
9385
|
+
hyperliquidWhaleContextUnavailable = true;
|
|
9386
|
+
import_logger7.logger.warn(
|
|
9387
|
+
"Hyperliquid whale context disabled after Timescale read failure: %s",
|
|
9388
|
+
String(error)
|
|
9389
|
+
);
|
|
9390
|
+
return null;
|
|
9391
|
+
}
|
|
9392
|
+
};
|
|
9393
|
+
var enrichSignalWithHyperliquidWhaleContext = async (params) => {
|
|
9394
|
+
const { signal, env } = params;
|
|
9395
|
+
if (signal.universe === "tradfi" || signal.interval == null || !hasBaseContext3(signal)) {
|
|
9396
|
+
return false;
|
|
9397
|
+
}
|
|
9398
|
+
const hyperliquidWhales = await loadHyperliquidWhaleFlowContext({
|
|
9399
|
+
symbol: signal.symbol,
|
|
9400
|
+
interval: signal.interval,
|
|
9401
|
+
timestamp: signal.timestamp,
|
|
9402
|
+
env,
|
|
9403
|
+
enabled: params.enabled,
|
|
9404
|
+
marketInterval: params.interval,
|
|
9405
|
+
maxAgeMs: params.maxAgeMs
|
|
9406
|
+
});
|
|
9407
|
+
if (!hyperliquidWhales) return false;
|
|
9408
|
+
const baseContext = signal.additionalIndicators.baseContext;
|
|
9409
|
+
signal.additionalIndicators = {
|
|
9410
|
+
...signal.additionalIndicators,
|
|
9411
|
+
baseContext: {
|
|
9412
|
+
...baseContext,
|
|
9413
|
+
participation: {
|
|
9414
|
+
...baseContext.participation,
|
|
9415
|
+
hyperliquidWhales
|
|
9416
|
+
}
|
|
9417
|
+
}
|
|
9418
|
+
};
|
|
9419
|
+
(0, import_strategies4.refreshSignalBaseContextGateFeatures)(signal);
|
|
9420
|
+
return true;
|
|
9421
|
+
};
|
|
9422
|
+
|
|
8859
9423
|
// src/strategyHelpers/runtime.ts
|
|
8860
9424
|
var formatAiError = (err) => {
|
|
8861
9425
|
const error = err;
|
|
@@ -8972,7 +9536,7 @@ var enrichSignalWithAi = async ({
|
|
|
8972
9536
|
signal.aiAnalysis = analysis;
|
|
8973
9537
|
return resolveAiQuality(analysis, direction);
|
|
8974
9538
|
} catch (err) {
|
|
8975
|
-
|
|
9539
|
+
import_logger8.logger.error("AI analysis error: %s %s", symbol, formatAiError(err));
|
|
8976
9540
|
}
|
|
8977
9541
|
return void 0;
|
|
8978
9542
|
};
|
|
@@ -8988,6 +9552,7 @@ var enrichSignalWithMlAi = async ({
|
|
|
8988
9552
|
await enrichSignalWithBinanceMarketContext({ signal, env });
|
|
8989
9553
|
await enrichSignalWithCoinMarketCapContext({ signal, env });
|
|
8990
9554
|
await enrichSignalWithDerivativesContext({ signal, env });
|
|
9555
|
+
await enrichSignalWithHyperliquidWhaleContext({ signal, env });
|
|
8991
9556
|
await enrichSignalWithMl({ signal, env, ml });
|
|
8992
9557
|
return enrichSignalWithAi({ signal, userName, symbol, direction, env, ai });
|
|
8993
9558
|
};
|
|
@@ -9022,7 +9587,7 @@ var getOrderArrivalSnapshot = async ({
|
|
|
9022
9587
|
spreadBps
|
|
9023
9588
|
};
|
|
9024
9589
|
} catch (error) {
|
|
9025
|
-
|
|
9590
|
+
import_logger8.logger.warn(
|
|
9026
9591
|
"runtime order arrival snapshot failed: %s %s",
|
|
9027
9592
|
symbol,
|
|
9028
9593
|
error?.message || String(error)
|
|
@@ -9526,7 +10091,7 @@ var resolveBacktestExecutionDelayMs = (value, fallbackDelayMs) => {
|
|
|
9526
10091
|
};
|
|
9527
10092
|
var safeIntervalToMs = (interval) => {
|
|
9528
10093
|
try {
|
|
9529
|
-
return (0,
|
|
10094
|
+
return (0, import_data3.intervalToMs)(interval);
|
|
9530
10095
|
} catch {
|
|
9531
10096
|
return null;
|
|
9532
10097
|
}
|
|
@@ -9608,14 +10173,14 @@ var applyBacktestDelayedEntryExecution = ({
|
|
|
9608
10173
|
btcExecutionCandle: null
|
|
9609
10174
|
};
|
|
9610
10175
|
}
|
|
9611
|
-
const executionPrice = (0,
|
|
10176
|
+
const executionPrice = (0, import_strategies5.resolveBacktestExecutionPrice)(
|
|
9612
10177
|
candle,
|
|
9613
10178
|
backtestPriceMode ?? "open"
|
|
9614
10179
|
);
|
|
9615
10180
|
const executionTimestamp = candle.timestamp;
|
|
9616
10181
|
const takeProfitPrice = decision.entryContext.prices.takeProfitPrice;
|
|
9617
10182
|
const stopLossPrice = decision.orderPlan.stopLossPrice;
|
|
9618
|
-
const riskRatio = (0,
|
|
10183
|
+
const riskRatio = (0, import_strategies5.calculateRiskRatio)({
|
|
9619
10184
|
direction: decision.entryContext.direction,
|
|
9620
10185
|
currentPrice: executionPrice,
|
|
9621
10186
|
takeProfitPrice,
|
|
@@ -9643,7 +10208,7 @@ var applyBacktestDelayedEntryExecution = ({
|
|
|
9643
10208
|
executionCandle: buildBacktestExecutionOnlyCandle(candle, executionPrice),
|
|
9644
10209
|
btcExecutionCandle: buildBacktestExecutionOnlyCandle(
|
|
9645
10210
|
btcCandle,
|
|
9646
|
-
(0,
|
|
10211
|
+
(0, import_strategies5.resolveBacktestExecutionPrice)(btcCandle, backtestPriceMode ?? "open")
|
|
9647
10212
|
)
|
|
9648
10213
|
};
|
|
9649
10214
|
if (!decision.signal) {
|
|
@@ -9888,7 +10453,7 @@ var handleExitDecision = async ({
|
|
|
9888
10453
|
deploymentId: connector.deploymentId
|
|
9889
10454
|
});
|
|
9890
10455
|
if (!activeTrade) {
|
|
9891
|
-
|
|
10456
|
+
import_logger9.logger.warn(
|
|
9892
10457
|
"[%s] blocked closePosition for untracked runtime position: %s",
|
|
9893
10458
|
strategyName ?? "unknown",
|
|
9894
10459
|
symbol
|
|
@@ -9896,7 +10461,7 @@ var handleExitDecision = async ({
|
|
|
9896
10461
|
return "CLOSE_BLOCKED_BY_UNTRACKED_POSITION";
|
|
9897
10462
|
}
|
|
9898
10463
|
if (!strategyName || activeTrade.strategy !== strategyName) {
|
|
9899
|
-
|
|
10464
|
+
import_logger9.logger.warn(
|
|
9900
10465
|
"[%s] blocked closePosition for foreign runtime position: %s ownedBy=%s",
|
|
9901
10466
|
strategyName ?? "unknown",
|
|
9902
10467
|
symbol,
|
|
@@ -9948,7 +10513,7 @@ var handleExitDecision = async ({
|
|
|
9948
10513
|
exitType: closedTrade?.exitType ?? "exit"
|
|
9949
10514
|
});
|
|
9950
10515
|
} catch (notificationError) {
|
|
9951
|
-
|
|
10516
|
+
import_logger9.logger.error(
|
|
9952
10517
|
"runtime close notification error: %s %s",
|
|
9953
10518
|
symbol,
|
|
9954
10519
|
notificationError
|
|
@@ -9962,7 +10527,7 @@ var handleExitDecision = async ({
|
|
|
9962
10527
|
decision,
|
|
9963
10528
|
market
|
|
9964
10529
|
});
|
|
9965
|
-
|
|
10530
|
+
import_logger9.logger.error("close order error: %s %s", symbol, err);
|
|
9966
10531
|
return "ORDER_ERROR";
|
|
9967
10532
|
}
|
|
9968
10533
|
return decision.code;
|
|
@@ -9989,7 +10554,7 @@ var handleProtectDecision = async ({
|
|
|
9989
10554
|
decision,
|
|
9990
10555
|
market
|
|
9991
10556
|
});
|
|
9992
|
-
|
|
10557
|
+
import_logger9.logger.error("protect position error: %s %s", symbol, err);
|
|
9993
10558
|
return "ORDER_ERROR";
|
|
9994
10559
|
}
|
|
9995
10560
|
return decision.code;
|
|
@@ -10152,9 +10717,9 @@ var executeEntryDecision = async ({
|
|
|
10152
10717
|
market
|
|
10153
10718
|
});
|
|
10154
10719
|
if (err?.message === import_types.BACKTEST_WARNING_CODES.TAKE_PROFIT_CROSSED_BEFORE_ENTRY) {
|
|
10155
|
-
|
|
10720
|
+
import_logger9.logger.warn("order warning: %s %s", symbol, err);
|
|
10156
10721
|
} else {
|
|
10157
|
-
|
|
10722
|
+
import_logger9.logger.error("order error: %s %s", symbol, err);
|
|
10158
10723
|
}
|
|
10159
10724
|
return signal ?? "ORDER_ERROR";
|
|
10160
10725
|
}
|
|
@@ -10251,7 +10816,7 @@ var createStrategyRuntime = ({
|
|
|
10251
10816
|
assetClass
|
|
10252
10817
|
});
|
|
10253
10818
|
const strategyPolicyProfile = getPolicyProfile();
|
|
10254
|
-
const indicatorPeriods = (0,
|
|
10819
|
+
const indicatorPeriods = (0, import_strategies5.buildDefaultIndicatorPeriods)(config);
|
|
10255
10820
|
const hookBase = {
|
|
10256
10821
|
connector,
|
|
10257
10822
|
strategyName,
|
|
@@ -10309,7 +10874,7 @@ var createStrategyRuntime = ({
|
|
|
10309
10874
|
try {
|
|
10310
10875
|
await projectHook(errorParams);
|
|
10311
10876
|
} catch (hookError) {
|
|
10312
|
-
|
|
10877
|
+
import_logger9.logger.error(
|
|
10313
10878
|
"project hook onRuntimeError failed: %s %s",
|
|
10314
10879
|
strategyName,
|
|
10315
10880
|
hookError
|
|
@@ -10323,7 +10888,7 @@ var createStrategyRuntime = ({
|
|
|
10323
10888
|
try {
|
|
10324
10889
|
await onRuntimeError(errorParams);
|
|
10325
10890
|
} catch (hookError) {
|
|
10326
|
-
|
|
10891
|
+
import_logger9.logger.error(
|
|
10327
10892
|
"runtime hook onRuntimeError failed: %s %s",
|
|
10328
10893
|
strategyName,
|
|
10329
10894
|
hookError
|
|
@@ -10337,7 +10902,7 @@ var createStrategyRuntime = ({
|
|
|
10337
10902
|
try {
|
|
10338
10903
|
return await hook(params);
|
|
10339
10904
|
} catch (error) {
|
|
10340
|
-
|
|
10905
|
+
import_logger9.logger.error(
|
|
10341
10906
|
'strategy hook "%s" failed for %s: %s',
|
|
10342
10907
|
stage,
|
|
10343
10908
|
strategyName,
|
|
@@ -10473,7 +11038,7 @@ var createStrategyRuntime = ({
|
|
|
10473
11038
|
}
|
|
10474
11039
|
return void 0;
|
|
10475
11040
|
};
|
|
10476
|
-
const indicatorsState = (0,
|
|
11041
|
+
const indicatorsState = (0, import_strategies5.createStrategyIndicatorsState)({
|
|
10477
11042
|
env,
|
|
10478
11043
|
data,
|
|
10479
11044
|
btcData,
|
|
@@ -10485,7 +11050,7 @@ var createStrategyRuntime = ({
|
|
|
10485
11050
|
sharedReplayKey: indicatorSharedReplayKey,
|
|
10486
11051
|
useBtcReference: universe === "crypto"
|
|
10487
11052
|
});
|
|
10488
|
-
const strategyApi = (0,
|
|
11053
|
+
const strategyApi = (0, import_strategies5.createStrategyAPI)({
|
|
10489
11054
|
strategy: strategyName,
|
|
10490
11055
|
symbol,
|
|
10491
11056
|
interval: config.INTERVAL ?? "15",
|
|
@@ -10495,7 +11060,30 @@ var createStrategyRuntime = ({
|
|
|
10495
11060
|
indicatorsState,
|
|
10496
11061
|
isConfigFromBacktest,
|
|
10497
11062
|
sharedReplayKey: strategySharedReplayKey,
|
|
10498
|
-
getSharedReplayState:
|
|
11063
|
+
getSharedReplayState: import_strategies5.getSharedStrategyReplayState,
|
|
11064
|
+
loadDecisionBaseContext: async ({
|
|
11065
|
+
baseContext,
|
|
11066
|
+
candle,
|
|
11067
|
+
symbol: decisionSymbol,
|
|
11068
|
+
interval: decisionInterval
|
|
11069
|
+
}) => {
|
|
11070
|
+
if (!baseContext) return void 0;
|
|
11071
|
+
const hyperliquidWhales = await loadHyperliquidWhaleFlowContext({
|
|
11072
|
+
symbol: decisionSymbol,
|
|
11073
|
+
interval: decisionInterval,
|
|
11074
|
+
timestamp: candle.timestamp,
|
|
11075
|
+
env,
|
|
11076
|
+
useSeriesCache: env === "BACKTEST" || env === "PARITY"
|
|
11077
|
+
});
|
|
11078
|
+
if (!hyperliquidWhales) return baseContext;
|
|
11079
|
+
return {
|
|
11080
|
+
...baseContext,
|
|
11081
|
+
participation: {
|
|
11082
|
+
...baseContext.participation,
|
|
11083
|
+
hyperliquidWhales
|
|
11084
|
+
}
|
|
11085
|
+
};
|
|
11086
|
+
}
|
|
10499
11087
|
});
|
|
10500
11088
|
const core = await createCore({
|
|
10501
11089
|
userName,
|
|
@@ -10510,7 +11098,7 @@ var createStrategyRuntime = ({
|
|
|
10510
11098
|
strategyApi,
|
|
10511
11099
|
indicatorsState,
|
|
10512
11100
|
sharedReplayKey: strategySharedReplayKey,
|
|
10513
|
-
getSharedReplayState:
|
|
11101
|
+
getSharedReplayState: import_strategies5.getSharedStrategyReplayState
|
|
10514
11102
|
});
|
|
10515
11103
|
await invokeStageHooks("onInit", strategyManifest?.hooks?.onInit, {
|
|
10516
11104
|
ctx: getHookCtx(),
|
|
@@ -11056,7 +11644,7 @@ var createStrategyRuntime = ({
|
|
|
11056
11644
|
|
|
11057
11645
|
// src/strategyHooks/closeOppositePositionsBeforeOpen.ts
|
|
11058
11646
|
var import_lodash2 = __toESM(require_lodash());
|
|
11059
|
-
var
|
|
11647
|
+
var import_logger10 = require("@tradejs/infra/logger");
|
|
11060
11648
|
var closeOppositePositionsBeforeOpen = async ({
|
|
11061
11649
|
connector,
|
|
11062
11650
|
entryContext
|
|
@@ -11070,7 +11658,7 @@ var closeOppositePositionsBeforeOpen = async ({
|
|
|
11070
11658
|
} = entryContext;
|
|
11071
11659
|
const price = prices.currentPrice;
|
|
11072
11660
|
try {
|
|
11073
|
-
|
|
11661
|
+
import_logger10.logger.log(
|
|
11074
11662
|
"info",
|
|
11075
11663
|
"[%s] checking open positions before open: %s %s",
|
|
11076
11664
|
strategyName,
|
|
@@ -11081,7 +11669,7 @@ var closeOppositePositionsBeforeOpen = async ({
|
|
|
11081
11669
|
const openPositions = (positions || []).filter(
|
|
11082
11670
|
(item) => item && Number(item.qty) > 0
|
|
11083
11671
|
);
|
|
11084
|
-
|
|
11672
|
+
import_logger10.logger.log(
|
|
11085
11673
|
"info",
|
|
11086
11674
|
"[%s] open positions found: %s",
|
|
11087
11675
|
strategyName,
|
|
@@ -11091,7 +11679,7 @@ var closeOppositePositionsBeforeOpen = async ({
|
|
|
11091
11679
|
(item) => item.symbol !== currentSymbol && item.direction !== currentDirection
|
|
11092
11680
|
);
|
|
11093
11681
|
if (import_lodash2.default.isEmpty(oppositePositions)) {
|
|
11094
|
-
|
|
11682
|
+
import_logger10.logger.log(
|
|
11095
11683
|
"info",
|
|
11096
11684
|
"[%s] no opposite positions to close before open: %s",
|
|
11097
11685
|
strategyName,
|
|
@@ -11100,7 +11688,7 @@ var closeOppositePositionsBeforeOpen = async ({
|
|
|
11100
11688
|
return;
|
|
11101
11689
|
}
|
|
11102
11690
|
for (const position of oppositePositions) {
|
|
11103
|
-
|
|
11691
|
+
import_logger10.logger.log(
|
|
11104
11692
|
"info",
|
|
11105
11693
|
"[%s] closing opposite position: %s %s qty=%s",
|
|
11106
11694
|
strategyName,
|
|
@@ -11115,14 +11703,14 @@ var closeOppositePositionsBeforeOpen = async ({
|
|
|
11115
11703
|
timestamp,
|
|
11116
11704
|
direction: position.direction
|
|
11117
11705
|
});
|
|
11118
|
-
|
|
11706
|
+
import_logger10.logger.log(
|
|
11119
11707
|
"info",
|
|
11120
11708
|
"[%s] opposite position closed: %s",
|
|
11121
11709
|
strategyName,
|
|
11122
11710
|
position.symbol
|
|
11123
11711
|
);
|
|
11124
11712
|
} catch (err) {
|
|
11125
|
-
|
|
11713
|
+
import_logger10.logger.log(
|
|
11126
11714
|
"error",
|
|
11127
11715
|
"[%s] failed to close opposite position: %s %s",
|
|
11128
11716
|
strategyName,
|
|
@@ -11132,7 +11720,7 @@ var closeOppositePositionsBeforeOpen = async ({
|
|
|
11132
11720
|
}
|
|
11133
11721
|
}
|
|
11134
11722
|
} catch (err) {
|
|
11135
|
-
|
|
11723
|
+
import_logger10.logger.log(
|
|
11136
11724
|
"error",
|
|
11137
11725
|
"[%s] failed to load open positions before open: %s %s",
|
|
11138
11726
|
strategyName,
|
|
@@ -11344,7 +11932,7 @@ var createMoveStopToBreakEvenOnBarHook = ({
|
|
|
11344
11932
|
var createMoveStopToBreakEvenAfterCoreDecisionHook = createMoveStopToBreakEvenOnBarHook;
|
|
11345
11933
|
|
|
11346
11934
|
// src/signalsHooks/closeAllPositionsOnGlobalProfitBeforeSignals.ts
|
|
11347
|
-
var
|
|
11935
|
+
var import_logger11 = require("@tradejs/infra/logger");
|
|
11348
11936
|
var createCloseAllOnGlobalProfitBeforeSignalsHook = ({
|
|
11349
11937
|
getStrategyDefaultConfig = () => void 0,
|
|
11350
11938
|
profitRiskMultiplier = DEFAULT_GLOBAL_UNREALIZED_PNL_TRIGGER_RISK_MULTIPLIER
|
|
@@ -11383,7 +11971,7 @@ var createCloseAllOnGlobalProfitBeforeSignalsHook = ({
|
|
|
11383
11971
|
if (!Number.isFinite(unrealizedPnlThreshold) || unrealizedPnlThreshold <= 0 || totalUnrealizedPnl < unrealizedPnlThreshold) {
|
|
11384
11972
|
return;
|
|
11385
11973
|
}
|
|
11386
|
-
|
|
11974
|
+
import_logger11.logger.info(
|
|
11387
11975
|
"closing all positions before signals by global unrealized pnl threshold: totalPnl=%s threshold=%s positions=%s",
|
|
11388
11976
|
totalUnrealizedPnl,
|
|
11389
11977
|
unrealizedPnlThreshold,
|
|
@@ -11409,7 +11997,7 @@ var createCloseAllOnGlobalProfitBeforeSignalsHook = ({
|
|
|
11409
11997
|
];
|
|
11410
11998
|
});
|
|
11411
11999
|
if (failedClosures.length) {
|
|
11412
|
-
|
|
12000
|
+
import_logger11.logger.warn(
|
|
11413
12001
|
"close-all before signals hook could not confirm closures for %s",
|
|
11414
12002
|
failedClosures.join(", ")
|
|
11415
12003
|
);
|
|
@@ -11441,6 +12029,7 @@ var createCloseAllOnGlobalProfitBeforeSignalsHook = ({
|
|
|
11441
12029
|
enrichSignalWithAi,
|
|
11442
12030
|
enrichSignalWithBinanceMarketContext,
|
|
11443
12031
|
enrichSignalWithCoinMarketCapContext,
|
|
12032
|
+
enrichSignalWithHyperliquidWhaleContext,
|
|
11444
12033
|
enrichSignalWithMl,
|
|
11445
12034
|
enrichSignalWithMlAi,
|
|
11446
12035
|
ensureAiStrategyPluginsLoaded,
|
|
@@ -11451,6 +12040,10 @@ var createCloseAllOnGlobalProfitBeforeSignalsHook = ({
|
|
|
11451
12040
|
getBinanceBreadthUniverseSnapshot,
|
|
11452
12041
|
getBinanceBreadthUniverses,
|
|
11453
12042
|
getDeterministicAiGateContext,
|
|
12043
|
+
getHyperliquidPerpSymbols,
|
|
12044
|
+
getHyperliquidPerpUniverseSnapshot,
|
|
12045
|
+
getHyperliquidWhaleAddresses,
|
|
12046
|
+
getHyperliquidWhaleRegistrySnapshot,
|
|
11454
12047
|
getOpenRouterModelKwargs,
|
|
11455
12048
|
getOrderArrivalSnapshot,
|
|
11456
12049
|
getPrimaryBinanceBreadthUniverse,
|
|
@@ -11459,9 +12052,12 @@ var createCloseAllOnGlobalProfitBeforeSignalsHook = ({
|
|
|
11459
12052
|
getStrategyCreator,
|
|
11460
12053
|
getStrategyManifest,
|
|
11461
12054
|
isKnownStrategy,
|
|
12055
|
+
isTrackedHyperliquidPerp,
|
|
12056
|
+
isTrackedHyperliquidWhale,
|
|
11462
12057
|
registerStrategyEntries,
|
|
11463
12058
|
resetAiRuntimeCache,
|
|
11464
12059
|
resetStrategyRegistryCache,
|
|
12060
|
+
resolveHyperliquidPerpFromSignalSymbol,
|
|
11465
12061
|
resolveStrategyConfig,
|
|
11466
12062
|
runAiPrompt,
|
|
11467
12063
|
runAiPromptLocal,
|