@tradejs/node 3.1.11 → 3.1.12-beta.218

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/registry.js CHANGED
@@ -48,10 +48,10 @@ module.exports = __toCommonJS(registry_exports);
48
48
  // src/strategyRuntime.ts
49
49
  var import_constants5 = require("@tradejs/core/constants");
50
50
  var import_strategies6 = require("@tradejs/core/strategies");
51
- var import_logger11 = require("@tradejs/infra/logger");
51
+ var import_logger10 = require("@tradejs/infra/logger");
52
52
 
53
53
  // src/strategyHelpers/runtime.ts
54
- var import_logger9 = require("@tradejs/infra/logger");
54
+ var import_logger8 = require("@tradejs/infra/logger");
55
55
  var import_constants3 = require("@tradejs/core/constants");
56
56
  var import_ml2 = require("@tradejs/infra/ml");
57
57
 
@@ -633,7 +633,6 @@ var buildAiMarketContext = (signal) => ({
633
633
 
634
634
  // src/strategy/manifests.ts
635
635
  var import_indicators = require("@tradejs/core/indicators");
636
- var import_logger2 = require("@tradejs/infra/logger");
637
636
 
638
637
  // src/tradejsConfig.ts
639
638
  var import_fs = __toESM(require("fs"));
@@ -986,21 +985,34 @@ var extractIndicatorPluginDefinition = (moduleExport) => {
986
985
  );
987
986
  return indicatorEntries ? { indicatorEntries } : null;
988
987
  };
989
- var registerEntries = (entries, source, state) => {
990
- for (const entry of entries) {
991
- const strategyName = entry.manifest?.name;
992
- if (!strategyName) {
993
- import_logger2.logger.warn("Skip strategy entry without name from %s", source);
994
- continue;
988
+ var validateStrategyEntries = (moduleName, entries, state) => {
989
+ const issues = [];
990
+ const names = /* @__PURE__ */ new Set();
991
+ entries.forEach((entry, index) => {
992
+ const entryPath = `${moduleName}.strategyEntries[${index}]`;
993
+ const strategyName = entry?.manifest?.name;
994
+ if (typeof strategyName !== "string" || !strategyName.trim()) {
995
+ issues.push(`${entryPath}: manifest.name is required`);
996
+ } else if (names.has(strategyName) || state.strategyEntriesMap.has(strategyName)) {
997
+ issues.push(`${entryPath}: duplicate strategy ${strategyName}`);
998
+ } else {
999
+ names.add(strategyName);
995
1000
  }
996
- if (state.strategyCreators.has(strategyName)) {
997
- import_logger2.logger.warn(
998
- 'Skip duplicate strategy "%s" from %s: already registered',
999
- strategyName,
1000
- source
1001
- );
1002
- continue;
1001
+ if (!entry || typeof entry !== "object" || !entry.defaults || typeof entry.defaults !== "object" || Array.isArray(entry.defaults)) {
1002
+ issues.push(`${entryPath}: defaults must be an object`);
1003
+ }
1004
+ if (typeof entry?.parseConfig !== "function") {
1005
+ issues.push(`${entryPath}: parseConfig is required`);
1003
1006
  }
1007
+ if (typeof entry?.createCore !== "function") {
1008
+ issues.push(`${entryPath}: createCore is required`);
1009
+ }
1010
+ });
1011
+ return issues;
1012
+ };
1013
+ var registerEntries = (entries, source, state) => {
1014
+ for (const entry of entries) {
1015
+ const strategyName = entry.manifest.name;
1004
1016
  state.strategyManifestsMap.set(strategyName, entry.manifest);
1005
1017
  state.strategyEntriesMap.set(strategyName, entry);
1006
1018
  state.strategySourcesMap.set(strategyName, source);
@@ -1057,6 +1069,7 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
1057
1069
  if (!pluginModuleNames.length) {
1058
1070
  return;
1059
1071
  }
1072
+ const issues = [];
1060
1073
  for (const moduleName of pluginModuleNames) {
1061
1074
  try {
1062
1075
  const resolvedModuleName = resolvePluginModuleSpecifier(
@@ -1070,24 +1083,30 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
1070
1083
  if (strategySet.has(moduleName)) {
1071
1084
  const pluginDefinition = extractStrategyPluginDefinition(moduleExport);
1072
1085
  if (!pluginDefinition) {
1073
- import_logger2.logger.warn(
1074
- 'Skip strategy plugin "%s": export { strategyEntries } is missing',
1075
- moduleName
1086
+ issues.push(
1087
+ `${moduleName}: export { strategyEntries } is missing`
1076
1088
  );
1077
1089
  } else {
1078
- registerEntries(
1079
- pluginDefinition.strategyEntries,
1090
+ const entryIssues = validateStrategyEntries(
1080
1091
  moduleName,
1092
+ pluginDefinition.strategyEntries,
1081
1093
  state
1082
1094
  );
1095
+ issues.push(...entryIssues);
1096
+ if (entryIssues.length === 0) {
1097
+ registerEntries(
1098
+ pluginDefinition.strategyEntries,
1099
+ moduleName,
1100
+ state
1101
+ );
1102
+ }
1083
1103
  }
1084
1104
  }
1085
1105
  if (indicatorSet.has(moduleName)) {
1086
1106
  const indicatorPluginDefinition = extractIndicatorPluginDefinition(moduleExport);
1087
1107
  if (!indicatorPluginDefinition) {
1088
- import_logger2.logger.warn(
1089
- 'Skip indicator plugin "%s": export { indicatorEntries } is missing',
1090
- moduleName
1108
+ issues.push(
1109
+ `${moduleName}: export { indicatorEntries } is missing`
1091
1110
  );
1092
1111
  } else {
1093
1112
  (0, import_indicators.registerIndicatorEntries)(
@@ -1098,19 +1117,17 @@ var ensureStrategyPluginsLoaded = async (cwd = getTradejsProjectCwd()) => {
1098
1117
  }
1099
1118
  }
1100
1119
  if (!strategySet.has(moduleName) && !indicatorSet.has(moduleName)) {
1101
- import_logger2.logger.warn(
1102
- 'Skip plugin "%s": no strategy/indicator sections requested in config',
1103
- moduleName
1104
- );
1120
+ issues.push(`${moduleName}: plugin is not declared in config`);
1105
1121
  }
1106
1122
  } catch (error) {
1107
- import_logger2.logger.warn(
1108
- 'Failed to load plugin "%s": %s',
1109
- moduleName,
1110
- String(error)
1111
- );
1123
+ issues.push(`${moduleName}: failed to import: ${String(error)}`);
1112
1124
  }
1113
1125
  }
1126
+ if (issues.length > 0) {
1127
+ throw new Error(
1128
+ ["Invalid TradeJS plugin catalog:", ...issues].join("\n")
1129
+ );
1130
+ }
1114
1131
  })();
1115
1132
  }
1116
1133
  await state.pluginsLoadPromise;
@@ -1152,6 +1169,10 @@ var isKnownStrategy = (name, cwd = getTradejsProjectCwd()) => {
1152
1169
  };
1153
1170
  var registerStrategyEntries = (entries, cwd = getTradejsProjectCwd()) => {
1154
1171
  const { state } = getStrategyRegistryState(cwd);
1172
+ const issues = validateStrategyEntries("runtime", entries, state);
1173
+ if (issues.length > 0) {
1174
+ throw new Error(["Invalid TradeJS plugin catalog:", ...issues].join("\n"));
1175
+ }
1155
1176
  registerEntries(entries, "runtime", state);
1156
1177
  };
1157
1178
  var resetStrategyRegistryCache = (cwd) => {
@@ -1805,7 +1826,7 @@ var import_node_crypto = require("crypto");
1805
1826
  var import_constants = require("@tradejs/core/constants");
1806
1827
  var import_time = require("@tradejs/core/time");
1807
1828
  var import_trade = require("@tradejs/core/trade");
1808
- var import_logger3 = require("@tradejs/infra/logger");
1829
+ var import_logger2 = require("@tradejs/infra/logger");
1809
1830
  var import_redis2 = require("@tradejs/infra/redis");
1810
1831
  var now = () => Date.now();
1811
1832
  var toRandomOrderSuffix = () => (0, import_node_crypto.randomUUID)().replace(/-/g, "").slice(0, 12).toLowerCase();
@@ -1864,7 +1885,7 @@ var recordRuntimeTradeOpen = async (params) => {
1864
1885
  )
1865
1886
  ]);
1866
1887
  } catch (error) {
1867
- import_logger3.logger.error(
1888
+ import_logger2.logger.error(
1868
1889
  "runtime trade open journal failed: %s %s",
1869
1890
  record.symbol,
1870
1891
  error?.message || String(error)
@@ -1931,7 +1952,7 @@ var recordRuntimeTradeIncrease = async (params) => {
1931
1952
  )
1932
1953
  ]);
1933
1954
  } catch (error) {
1934
- import_logger3.logger.error(
1955
+ import_logger2.logger.error(
1935
1956
  "runtime trade increase journal failed: %s %s",
1936
1957
  symbol,
1937
1958
  error?.message || String(error)
@@ -2038,7 +2059,7 @@ var markRuntimeTradeClosed = async (params) => {
2038
2059
  )
2039
2060
  ]);
2040
2061
  } catch (error) {
2041
- import_logger3.logger.error(
2062
+ import_logger2.logger.error(
2042
2063
  "runtime trade close journal failed: %s %s",
2043
2064
  symbol,
2044
2065
  error?.message || String(error)
@@ -2048,11 +2069,11 @@ var markRuntimeTradeClosed = async (params) => {
2048
2069
  };
2049
2070
 
2050
2071
  // src/strategyHelpers/marketContextStages.ts
2051
- var import_logger8 = require("@tradejs/infra/logger");
2072
+ var import_logger7 = require("@tradejs/infra/logger");
2052
2073
 
2053
2074
  // src/strategyHelpers/binanceMarketContext.ts
2054
2075
  var import_marketContext = require("@tradejs/infra/timescale/marketContext");
2055
- var import_logger4 = require("@tradejs/infra/logger");
2076
+ var import_logger3 = require("@tradejs/infra/logger");
2056
2077
  var import_strategies = require("@tradejs/core/strategies");
2057
2078
 
2058
2079
  // src/binanceBreadthUniverses.ts
@@ -2648,7 +2669,7 @@ var enrichSignalWithBinanceMarketContext = async (params) => {
2648
2669
  throw error;
2649
2670
  }
2650
2671
  binanceMarketContextUnavailable = true;
2651
- import_logger4.logger.warn(
2672
+ import_logger3.logger.warn(
2652
2673
  "Binance market context disabled after Timescale read failure: %s",
2653
2674
  String(error)
2654
2675
  );
@@ -2658,7 +2679,7 @@ var enrichSignalWithBinanceMarketContext = async (params) => {
2658
2679
 
2659
2680
  // src/strategyHelpers/coinMarketCapContext.ts
2660
2681
  var import_strategies2 = require("@tradejs/core/strategies");
2661
- var import_logger5 = require("@tradejs/infra/logger");
2682
+ var import_logger4 = require("@tradejs/infra/logger");
2662
2683
  var import_marketContext2 = require("@tradejs/infra/timescale/marketContext");
2663
2684
  var DEFAULT_MAX_AGE_MS = 48 * 60 * 6e4;
2664
2685
  var SOURCE_GLOBAL_DAILY = "coinmarketcap_global";
@@ -3147,7 +3168,7 @@ var enrichSignalWithCoinMarketCapContext = async (params) => {
3147
3168
  throw error;
3148
3169
  }
3149
3170
  coinMarketCapContextUnavailable = true;
3150
- import_logger5.logger.warn(
3171
+ import_logger4.logger.warn(
3151
3172
  "CoinMarketCap context disabled after Timescale read failure: %s",
3152
3173
  String(error)
3153
3174
  );
@@ -3161,7 +3182,7 @@ var import_data = require("@tradejs/core/data");
3161
3182
  var import_strategies3 = require("@tradejs/core/strategies");
3162
3183
  var import_constants2 = require("@tradejs/core/constants");
3163
3184
  var import_derivatives = require("@tradejs/infra/timescale/derivatives");
3164
- var import_logger6 = require("@tradejs/infra/logger");
3185
+ var import_logger5 = require("@tradejs/infra/logger");
3165
3186
  var STORED_INTERVALS = ["15m", "1h"];
3166
3187
  var CONTEXT_INTERVALS = ["15m", "1h"];
3167
3188
  var DEFAULT_LOOKBACK_HOURS = 48;
@@ -3393,7 +3414,7 @@ var enrichSignalWithDerivativesContext = async (params) => {
3393
3414
  throw error;
3394
3415
  }
3395
3416
  derivativesContextUnavailable = true;
3396
- import_logger6.logger.warn(
3417
+ import_logger5.logger.warn(
3397
3418
  "Derivatives context disabled after Timescale read failure: %s",
3398
3419
  String(error)
3399
3420
  );
@@ -3405,7 +3426,7 @@ var enrichSignalWithDerivativesContext = async (params) => {
3405
3426
  var import_data2 = require("@tradejs/core/data");
3406
3427
  var import_strategies4 = require("@tradejs/core/strategies");
3407
3428
  var import_hyperliquidWhales2 = require("@tradejs/infra/timescale/hyperliquidWhales");
3408
- var import_logger7 = require("@tradejs/infra/logger");
3429
+ var import_logger6 = require("@tradejs/infra/logger");
3409
3430
 
3410
3431
  // src/hyperliquidWhaleUniverse.ts
3411
3432
  var import_node_crypto3 = require("crypto");
@@ -3925,7 +3946,7 @@ var loadHyperliquidWhaleFlowContext = async (params) => {
3925
3946
  throw error;
3926
3947
  }
3927
3948
  hyperliquidWhaleContextUnavailable = true;
3928
- import_logger7.logger.warn(
3949
+ import_logger6.logger.warn(
3929
3950
  "Hyperliquid whale context disabled after Timescale read failure: %s",
3930
3951
  String(error)
3931
3952
  );
@@ -4008,7 +4029,7 @@ var runMarketContextStage = async ({
4008
4029
  elapsedMs: Date.now() - startedAt
4009
4030
  };
4010
4031
  if (status === "timed_out") {
4011
- import_logger8.logger.warn(
4032
+ import_logger7.logger.warn(
4012
4033
  "Market context stage timed out: %s after %sms",
4013
4034
  stage,
4014
4035
  result.elapsedMs
@@ -4198,7 +4219,7 @@ var enrichSignalWithAi = async ({
4198
4219
  signal.aiAnalysis = analysis;
4199
4220
  return resolveAiQuality(analysis, direction);
4200
4221
  } catch (err) {
4201
- import_logger9.logger.error("AI analysis error: %s %s", symbol, formatAiError(err));
4222
+ import_logger8.logger.error("AI analysis error: %s %s", symbol, formatAiError(err));
4202
4223
  }
4203
4224
  return void 0;
4204
4225
  };
@@ -4233,7 +4254,7 @@ var getOrderArrivalSnapshot = async ({
4233
4254
  spreadBps
4234
4255
  };
4235
4256
  } catch (error) {
4236
- import_logger9.logger.warn(
4257
+ import_logger8.logger.warn(
4237
4258
  "runtime order arrival snapshot failed: %s %s",
4238
4259
  symbol,
4239
4260
  error?.message || String(error)
@@ -4462,7 +4483,7 @@ var executeEntryOrder = async ({
4462
4483
  deploymentId: signal.deploymentId,
4463
4484
  policyProfileId: signal.policyProfileId,
4464
4485
  runtimeConfigId: signal.runtimeConfigId,
4465
- runtimeVersion: signal.runtimeVersion,
4486
+ strategyRevision: signal.strategyRevision,
4466
4487
  runtimeLineage: signal.runtimeLineage,
4467
4488
  ...signal.aiAnalysis ? { aiAnalysis: signal.aiAnalysis } : {}
4468
4489
  });
@@ -5014,7 +5035,7 @@ var canUseSharedReplayState = ({
5014
5035
  }) => (env === "BACKTEST" || env === "PARITY") && Boolean(sharedReplayKey);
5015
5036
 
5016
5037
  // src/strategy/runtimeExecution.ts
5017
- var import_logger10 = require("@tradejs/infra/logger");
5038
+ var import_logger9 = require("@tradejs/infra/logger");
5018
5039
  var import_types = require("@tradejs/types");
5019
5040
  var buildExitOrderSignal = ({
5020
5041
  strategyName,
@@ -5066,7 +5087,7 @@ var handleExitDecision = async ({
5066
5087
  deploymentId: connector.deploymentId
5067
5088
  });
5068
5089
  if (!activeTrade) {
5069
- import_logger10.logger.warn(
5090
+ import_logger9.logger.warn(
5070
5091
  "[%s] blocked closePosition for untracked runtime position: %s",
5071
5092
  strategyName ?? "unknown",
5072
5093
  symbol
@@ -5074,7 +5095,7 @@ var handleExitDecision = async ({
5074
5095
  return "CLOSE_BLOCKED_BY_UNTRACKED_POSITION";
5075
5096
  }
5076
5097
  if (!strategyName || activeTrade.strategy !== strategyName) {
5077
- import_logger10.logger.warn(
5098
+ import_logger9.logger.warn(
5078
5099
  "[%s] blocked closePosition for foreign runtime position: %s ownedBy=%s",
5079
5100
  strategyName ?? "unknown",
5080
5101
  symbol,
@@ -5126,7 +5147,7 @@ var handleExitDecision = async ({
5126
5147
  exitType: closedTrade?.exitType ?? "exit"
5127
5148
  });
5128
5149
  } catch (notificationError) {
5129
- import_logger10.logger.error(
5150
+ import_logger9.logger.error(
5130
5151
  "runtime close notification error: %s %s",
5131
5152
  symbol,
5132
5153
  notificationError
@@ -5140,7 +5161,7 @@ var handleExitDecision = async ({
5140
5161
  decision,
5141
5162
  market
5142
5163
  });
5143
- import_logger10.logger.error("close order error: %s %s", symbol, err);
5164
+ import_logger9.logger.error("close order error: %s %s", symbol, err);
5144
5165
  return "ORDER_ERROR";
5145
5166
  }
5146
5167
  return decision.code;
@@ -5167,7 +5188,7 @@ var handleProtectDecision = async ({
5167
5188
  decision,
5168
5189
  market
5169
5190
  });
5170
- import_logger10.logger.error("protect position error: %s %s", symbol, err);
5191
+ import_logger9.logger.error("protect position error: %s %s", symbol, err);
5171
5192
  return "ORDER_ERROR";
5172
5193
  }
5173
5194
  return decision.code;
@@ -5330,9 +5351,9 @@ var executeEntryDecision = async ({
5330
5351
  market
5331
5352
  });
5332
5353
  if (err?.message === import_types.BACKTEST_WARNING_CODES.TAKE_PROFIT_CROSSED_BEFORE_ENTRY) {
5333
- import_logger10.logger.warn("order warning: %s %s", symbol, err);
5354
+ import_logger9.logger.warn("order warning: %s %s", symbol, err);
5334
5355
  } else {
5335
- import_logger10.logger.error("order error: %s %s", symbol, err);
5356
+ import_logger9.logger.error("order error: %s %s", symbol, err);
5336
5357
  }
5337
5358
  return signal ?? "ORDER_ERROR";
5338
5359
  }
@@ -5373,7 +5394,7 @@ var createStrategyRuntime = ({
5373
5394
  deploymentId: requestedDeploymentId,
5374
5395
  policyProfileId,
5375
5396
  runtimeConfigId,
5376
- runtimeVersion,
5397
+ strategyRevision,
5377
5398
  entriesPaused = false,
5378
5399
  runtimeLineage,
5379
5400
  runtimeConfigSnapshot,
@@ -5486,7 +5507,7 @@ var createStrategyRuntime = ({
5486
5507
  try {
5487
5508
  await projectHook(errorParams);
5488
5509
  } catch (hookError) {
5489
- import_logger11.logger.error(
5510
+ import_logger10.logger.error(
5490
5511
  "project hook onRuntimeError failed: %s %s",
5491
5512
  strategyName,
5492
5513
  hookError
@@ -5500,7 +5521,7 @@ var createStrategyRuntime = ({
5500
5521
  try {
5501
5522
  await onRuntimeError(errorParams);
5502
5523
  } catch (hookError) {
5503
- import_logger11.logger.error(
5524
+ import_logger10.logger.error(
5504
5525
  "runtime hook onRuntimeError failed: %s %s",
5505
5526
  strategyName,
5506
5527
  hookError
@@ -5514,7 +5535,7 @@ var createStrategyRuntime = ({
5514
5535
  try {
5515
5536
  return await hook(params);
5516
5537
  } catch (error) {
5517
- import_logger11.logger.error(
5538
+ import_logger10.logger.error(
5518
5539
  'strategy hook "%s" failed for %s: %s',
5519
5540
  stage,
5520
5541
  strategyName,
@@ -6045,8 +6066,8 @@ var createStrategyRuntime = ({
6045
6066
  signal.signalId = `${signal.signalId}:${runtimeConfigId}`;
6046
6067
  }
6047
6068
  }
6048
- if (runtimeVersion) {
6049
- signal.runtimeVersion = runtimeVersion;
6069
+ if (strategyRevision) {
6070
+ signal.strategyRevision = strategyRevision;
6050
6071
  }
6051
6072
  if (decisionHookCtx.policyProfileId) {
6052
6073
  signal.policyProfileId = decisionHookCtx.policyProfileId;
@@ -6159,7 +6180,7 @@ var createStrategyRuntime = ({
6159
6180
  if (signal) {
6160
6181
  signal.orderStatus = "skipped";
6161
6182
  signal.orderSkipReason = skipReason;
6162
- signal.runtimeVersion = runtimeVersion;
6183
+ signal.strategyRevision = strategyRevision;
6163
6184
  }
6164
6185
  return signal ?? skipReason;
6165
6186
  }
package/dist/registry.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import "./chunk-B6X2HEGL.mjs";
1
+ import "./chunk-6PIVDS4M.mjs";
2
2
  import {
3
3
  ensureIndicatorPluginsLoaded,
4
4
  ensureStrategyPluginsLoaded,
@@ -12,7 +12,7 @@ import {
12
12
  registerStrategyEntries,
13
13
  resetStrategyRegistryCache,
14
14
  strategies
15
- } from "./chunk-C3KRBNUR.mjs";
15
+ } from "./chunk-IKRSNRP6.mjs";
16
16
  import "./chunk-LZDXRXIU.mjs";
17
17
  import "./chunk-Y6FXYEAI.mjs";
18
18
  export {