@tradejs/node 3.1.29-beta.289 → 3.1.29-beta.290

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/backtest.js CHANGED
@@ -1121,11 +1121,8 @@ var validateEntryExecution = ({
1121
1121
  throw new EntrySubmissionValidationError(
1122
1122
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
1123
1123
  );
1124
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
1125
- throw new EntrySubmissionValidationError(
1126
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
1127
- );
1128
- return { netRiskRatio, plannedLossValue };
1124
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
1125
+ return { netRiskRatio, plannedLossValue, riskExceeded };
1129
1126
  };
1130
1127
 
1131
1128
  // src/strategy/entrySubmissionValidation.ts
@@ -5735,12 +5732,12 @@ var executeEntryOrder = async ({
5735
5732
  if (executionLimits?.maxLossValue != null) {
5736
5733
  signal.riskDecision = {
5737
5734
  stage: "order_plan",
5738
- status: "approved",
5739
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5735
+ status: economics2.riskExceeded ? "warning" : "approved",
5736
+ reason: economics2.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5740
5737
  plannedLossValue: economics2.plannedLossValue,
5741
5738
  maxLossValue: executionLimits.maxLossValue,
5742
5739
  limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
5743
- enforced: true
5740
+ enforced: false
5744
5741
  };
5745
5742
  }
5746
5743
  }
@@ -7069,6 +7066,9 @@ var createStrategyRuntime = ({
7069
7066
  });
7070
7067
  const strategyPolicyProfile = getPolicyProfile();
7071
7068
  const indicatorPeriods = (0, import_strategies6.buildDefaultIndicatorPeriods)(config);
7069
+ const strategyConfig = { ...config };
7070
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
7071
+ delete strategyConfig.SIMULATE_ORDERS;
7072
7072
  const hookBase = {
7073
7073
  connector,
7074
7074
  strategyName,
@@ -7079,7 +7079,7 @@ var createStrategyRuntime = ({
7079
7079
  accountId,
7080
7080
  deploymentId,
7081
7081
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
7082
- strategyConfig: config,
7082
+ strategyConfig,
7083
7083
  env,
7084
7084
  isConfigFromBacktest
7085
7085
  };
@@ -7147,7 +7147,7 @@ var createStrategyRuntime = ({
7147
7147
  );
7148
7148
  }
7149
7149
  };
7150
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
7150
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
7151
7151
  if (!hook) {
7152
7152
  return void 0;
7153
7153
  }
@@ -7167,17 +7167,18 @@ var createStrategyRuntime = ({
7167
7167
  entry: errorContext.entry,
7168
7168
  market: errorContext.market
7169
7169
  });
7170
- return void 0;
7170
+ return failureResult;
7171
7171
  }
7172
7172
  };
7173
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
7173
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
7174
7174
  const results = [];
7175
7175
  for (const hook of getProjectHookList(stage)) {
7176
7176
  const result = await invokeHook(
7177
7177
  stage,
7178
7178
  hook,
7179
7179
  params,
7180
- errorContext
7180
+ errorContext,
7181
+ failureResult
7181
7182
  );
7182
7183
  if (result !== void 0) {
7183
7184
  results.push(result);
@@ -7192,10 +7193,12 @@ var createStrategyRuntime = ({
7192
7193
  return invokeHook(stage, hook, params, errorContext);
7193
7194
  };
7194
7195
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
7196
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
7195
7197
  const projectResults = await invokeProjectHooks(
7196
7198
  stage,
7197
7199
  params,
7198
- errorContext
7200
+ errorContext,
7201
+ failureResult
7199
7202
  );
7200
7203
  const projectBlock = projectResults.find(
7201
7204
  (result) => result?.allow === false
@@ -7207,7 +7210,8 @@ var createStrategyRuntime = ({
7207
7210
  stage,
7208
7211
  hook,
7209
7212
  params,
7210
- errorContext
7213
+ errorContext,
7214
+ failureResult
7211
7215
  );
7212
7216
  };
7213
7217
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -7353,11 +7357,8 @@ var createStrategyRuntime = ({
7353
7357
  return enrichedBaseContext;
7354
7358
  }
7355
7359
  });
7356
- const coreConfig = { ...config };
7357
- delete coreConfig.RECORD_RUNTIME_TRADES;
7358
- delete coreConfig.SIMULATE_ORDERS;
7359
7360
  const core = await createCore({
7360
- config: coreConfig,
7361
+ config: strategyConfig,
7361
7362
  data,
7362
7363
  strategyApi,
7363
7364
  indicatorsState
package/dist/backtest.mjs CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  evaluateResearchEntryPolicy,
11
11
  matchesResearchEntryRules,
12
12
  parseResearchEntryPolicy
13
- } from "./chunk-KYGJBMKE.mjs";
13
+ } from "./chunk-PB2KHBGH.mjs";
14
14
  import {
15
15
  buildAiPayload,
16
16
  getStrategyCreator
@@ -76,11 +76,8 @@ var validateEntryExecution = ({
76
76
  throw new EntrySubmissionValidationError(
77
77
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
78
78
  );
79
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
80
- throw new EntrySubmissionValidationError(
81
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
82
- );
83
- return { netRiskRatio, plannedLossValue };
79
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
80
+ return { netRiskRatio, plannedLossValue, riskExceeded };
84
81
  };
85
82
 
86
83
  // src/strategy/entrySubmissionValidation.ts
@@ -3145,12 +3142,12 @@ var executeEntryOrder = async ({
3145
3142
  if (executionLimits?.maxLossValue != null) {
3146
3143
  signal.riskDecision = {
3147
3144
  stage: "order_plan",
3148
- status: "approved",
3149
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
3145
+ status: economics.riskExceeded ? "warning" : "approved",
3146
+ reason: economics.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
3150
3147
  plannedLossValue: economics.plannedLossValue,
3151
3148
  maxLossValue: executionLimits.maxLossValue,
3152
3149
  limitUtilization: economics.plannedLossValue / executionLimits.maxLossValue,
3153
- enforced: true
3150
+ enforced: false
3154
3151
  };
3155
3152
  }
3156
3153
  }
@@ -4498,6 +4495,9 @@ var createStrategyRuntime = ({
4498
4495
  });
4499
4496
  const strategyPolicyProfile = getPolicyProfile();
4500
4497
  const indicatorPeriods = buildDefaultIndicatorPeriods(config);
4498
+ const strategyConfig = { ...config };
4499
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
4500
+ delete strategyConfig.SIMULATE_ORDERS;
4501
4501
  const hookBase = {
4502
4502
  connector,
4503
4503
  strategyName,
@@ -4508,7 +4508,7 @@ var createStrategyRuntime = ({
4508
4508
  accountId,
4509
4509
  deploymentId,
4510
4510
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
4511
- strategyConfig: config,
4511
+ strategyConfig,
4512
4512
  env,
4513
4513
  isConfigFromBacktest
4514
4514
  };
@@ -4576,7 +4576,7 @@ var createStrategyRuntime = ({
4576
4576
  );
4577
4577
  }
4578
4578
  };
4579
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
4579
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
4580
4580
  if (!hook) {
4581
4581
  return void 0;
4582
4582
  }
@@ -4596,17 +4596,18 @@ var createStrategyRuntime = ({
4596
4596
  entry: errorContext.entry,
4597
4597
  market: errorContext.market
4598
4598
  });
4599
- return void 0;
4599
+ return failureResult;
4600
4600
  }
4601
4601
  };
4602
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
4602
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
4603
4603
  const results = [];
4604
4604
  for (const hook of getProjectHookList(stage)) {
4605
4605
  const result = await invokeHook(
4606
4606
  stage,
4607
4607
  hook,
4608
4608
  params,
4609
- errorContext
4609
+ errorContext,
4610
+ failureResult
4610
4611
  );
4611
4612
  if (result !== void 0) {
4612
4613
  results.push(result);
@@ -4621,10 +4622,12 @@ var createStrategyRuntime = ({
4621
4622
  return invokeHook(stage, hook, params, errorContext);
4622
4623
  };
4623
4624
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
4625
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
4624
4626
  const projectResults = await invokeProjectHooks(
4625
4627
  stage,
4626
4628
  params,
4627
- errorContext
4629
+ errorContext,
4630
+ failureResult
4628
4631
  );
4629
4632
  const projectBlock = projectResults.find(
4630
4633
  (result) => result?.allow === false
@@ -4636,7 +4639,8 @@ var createStrategyRuntime = ({
4636
4639
  stage,
4637
4640
  hook,
4638
4641
  params,
4639
- errorContext
4642
+ errorContext,
4643
+ failureResult
4640
4644
  );
4641
4645
  };
4642
4646
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -4782,11 +4786,8 @@ var createStrategyRuntime = ({
4782
4786
  return enrichedBaseContext;
4783
4787
  }
4784
4788
  });
4785
- const coreConfig = { ...config };
4786
- delete coreConfig.RECORD_RUNTIME_TRADES;
4787
- delete coreConfig.SIMULATE_ORDERS;
4788
4789
  const core = await createCore({
4789
- config: coreConfig,
4790
+ config: strategyConfig,
4790
4791
  data,
4791
4792
  strategyApi,
4792
4793
  indicatorsState
package/dist/cli.js CHANGED
@@ -2396,8 +2396,9 @@ var formatMessage = (signal, analysis, _options = {}) => {
2396
2396
  }
2397
2397
  if (isConfigFromBacktest) {
2398
2398
  lines.push("\u{1F7E2} Using config from backtest");
2399
- } else {
2400
- lines.push("\u{1F7E1} Using base config");
2399
+ }
2400
+ if (signal.riskDecision?.status === "warning") {
2401
+ lines.push("\u{1F7E1} Entry risk exceeds limit");
2401
2402
  }
2402
2403
  if (ml) {
2403
2404
  lines.push(
package/dist/cli.mjs CHANGED
@@ -806,8 +806,9 @@ var formatMessage = (signal, analysis, _options = {}) => {
806
806
  }
807
807
  if (isConfigFromBacktest) {
808
808
  lines.push("\u{1F7E2} Using config from backtest");
809
- } else {
810
- lines.push("\u{1F7E1} Using base config");
809
+ }
810
+ if (signal.riskDecision?.status === "warning") {
811
+ lines.push("\u{1F7E1} Entry risk exceeds limit");
811
812
  }
812
813
  if (ml) {
813
814
  lines.push(
@@ -1140,11 +1140,8 @@ var validateEntryExecution = ({
1140
1140
  throw new EntrySubmissionValidationError(
1141
1141
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
1142
1142
  );
1143
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
1144
- throw new EntrySubmissionValidationError(
1145
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
1146
- );
1147
- return { netRiskRatio, plannedLossValue };
1143
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
1144
+ return { netRiskRatio, plannedLossValue, riskExceeded };
1148
1145
  };
1149
1146
 
1150
1147
  // src/strategy/entrySubmissionValidation.ts
@@ -5772,12 +5769,12 @@ var executeEntryOrder = async ({
5772
5769
  if (executionLimits?.maxLossValue != null) {
5773
5770
  signal.riskDecision = {
5774
5771
  stage: "order_plan",
5775
- status: "approved",
5776
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5772
+ status: economics2.riskExceeded ? "warning" : "approved",
5773
+ reason: economics2.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5777
5774
  plannedLossValue: economics2.plannedLossValue,
5778
5775
  maxLossValue: executionLimits.maxLossValue,
5779
5776
  limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
5780
- enforced: true
5777
+ enforced: false
5781
5778
  };
5782
5779
  }
5783
5780
  }
@@ -7103,6 +7100,9 @@ var createStrategyRuntime = ({
7103
7100
  });
7104
7101
  const strategyPolicyProfile = getPolicyProfile();
7105
7102
  const indicatorPeriods = (0, import_strategies6.buildDefaultIndicatorPeriods)(config);
7103
+ const strategyConfig = { ...config };
7104
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
7105
+ delete strategyConfig.SIMULATE_ORDERS;
7106
7106
  const hookBase = {
7107
7107
  connector,
7108
7108
  strategyName,
@@ -7113,7 +7113,7 @@ var createStrategyRuntime = ({
7113
7113
  accountId,
7114
7114
  deploymentId,
7115
7115
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
7116
- strategyConfig: config,
7116
+ strategyConfig,
7117
7117
  env,
7118
7118
  isConfigFromBacktest
7119
7119
  };
@@ -7181,7 +7181,7 @@ var createStrategyRuntime = ({
7181
7181
  );
7182
7182
  }
7183
7183
  };
7184
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
7184
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
7185
7185
  if (!hook) {
7186
7186
  return void 0;
7187
7187
  }
@@ -7201,17 +7201,18 @@ var createStrategyRuntime = ({
7201
7201
  entry: errorContext.entry,
7202
7202
  market: errorContext.market
7203
7203
  });
7204
- return void 0;
7204
+ return failureResult;
7205
7205
  }
7206
7206
  };
7207
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
7207
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
7208
7208
  const results = [];
7209
7209
  for (const hook of getProjectHookList(stage)) {
7210
7210
  const result = await invokeHook(
7211
7211
  stage,
7212
7212
  hook,
7213
7213
  params,
7214
- errorContext
7214
+ errorContext,
7215
+ failureResult
7215
7216
  );
7216
7217
  if (result !== void 0) {
7217
7218
  results.push(result);
@@ -7226,10 +7227,12 @@ var createStrategyRuntime = ({
7226
7227
  return invokeHook(stage, hook, params, errorContext);
7227
7228
  };
7228
7229
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
7230
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
7229
7231
  const projectResults = await invokeProjectHooks(
7230
7232
  stage,
7231
7233
  params,
7232
- errorContext
7234
+ errorContext,
7235
+ failureResult
7233
7236
  );
7234
7237
  const projectBlock = projectResults.find(
7235
7238
  (result) => result?.allow === false
@@ -7241,7 +7244,8 @@ var createStrategyRuntime = ({
7241
7244
  stage,
7242
7245
  hook,
7243
7246
  params,
7244
- errorContext
7247
+ errorContext,
7248
+ failureResult
7245
7249
  );
7246
7250
  };
7247
7251
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -7387,11 +7391,8 @@ var createStrategyRuntime = ({
7387
7391
  return enrichedBaseContext;
7388
7392
  }
7389
7393
  });
7390
- const coreConfig = { ...config };
7391
- delete coreConfig.RECORD_RUNTIME_TRADES;
7392
- delete coreConfig.SIMULATE_ORDERS;
7393
7394
  const core = await createCore({
7394
- config: coreConfig,
7395
+ config: strategyConfig,
7395
7396
  data,
7396
7397
  strategyApi,
7397
7398
  indicatorsState
@@ -2,7 +2,7 @@ import {
2
2
  getRuntimeDeployment,
3
3
  loadResolvedRuntimeStrategies
4
4
  } from "./chunk-BO42QWAB.mjs";
5
- import "./chunk-KYGJBMKE.mjs";
5
+ import "./chunk-PB2KHBGH.mjs";
6
6
  import "./chunk-UL5Z46JL.mjs";
7
7
  import "./chunk-LZDXRXIU.mjs";
8
8
  import "./chunk-YR55Q355.mjs";
package/dist/mcp.d.mts CHANGED
@@ -9,6 +9,8 @@ declare const enqueueMcpJob: (principal: McpPrincipal, kind: McpJob["kind"], req
9
9
  declare const readMcpJob: (userName: string, id: string) => Promise<McpJob>;
10
10
  declare const readAuthorizedMcpJob: (principal: McpPrincipal, id: string) => Promise<McpJob>;
11
11
  declare const redactMcpJobLog: (line: string) => string;
12
+ /** Redact the complete line before wrapping it for checksum-bound export. */
13
+ declare const formatMcpArtifactLogLine: (line: string) => string;
12
14
  /** Offsets refer to the retained worker tail, which may shift while running. */
13
15
  declare const readMcpJobLogs: (principal: McpPrincipal, id: string, offset?: number, limit?: number) => Promise<{
14
16
  jobId: string;
@@ -228,4 +230,4 @@ declare const readMcpBacktestResult: (userName: string, id: string, offset?: num
228
230
  source: string;
229
231
  }>;
230
232
 
231
- export { MCP_JOB_TTL, McpCursorError, cancelMcpJob, enqueueMcpJob, isMcpRecord, mcpId, mcpJobDirectory, mcpJobStorageId, mcpPackageManifestHash, mcpProjectRoot, publicMcpJob, readAuthorizedMcpJob, readMcpBacktestPage, readMcpBacktestResult, readMcpChart, readMcpDeployments, readMcpEvaluationStats, readMcpJob, readMcpJobLogs, readMcpMarket, readMcpRuntimePage, readMcpSignal, readMcpStrategies, redactMcpData, redactMcpJobLog, requireMcpDeployment };
233
+ export { MCP_JOB_TTL, McpCursorError, cancelMcpJob, enqueueMcpJob, formatMcpArtifactLogLine, isMcpRecord, mcpId, mcpJobDirectory, mcpJobStorageId, mcpPackageManifestHash, mcpProjectRoot, publicMcpJob, readAuthorizedMcpJob, readMcpBacktestPage, readMcpBacktestResult, readMcpChart, readMcpDeployments, readMcpEvaluationStats, readMcpJob, readMcpJobLogs, readMcpMarket, readMcpRuntimePage, readMcpSignal, readMcpStrategies, redactMcpData, redactMcpJobLog, requireMcpDeployment };
package/dist/mcp.d.ts CHANGED
@@ -9,6 +9,8 @@ declare const enqueueMcpJob: (principal: McpPrincipal, kind: McpJob["kind"], req
9
9
  declare const readMcpJob: (userName: string, id: string) => Promise<McpJob>;
10
10
  declare const readAuthorizedMcpJob: (principal: McpPrincipal, id: string) => Promise<McpJob>;
11
11
  declare const redactMcpJobLog: (line: string) => string;
12
+ /** Redact the complete line before wrapping it for checksum-bound export. */
13
+ declare const formatMcpArtifactLogLine: (line: string) => string;
12
14
  /** Offsets refer to the retained worker tail, which may shift while running. */
13
15
  declare const readMcpJobLogs: (principal: McpPrincipal, id: string, offset?: number, limit?: number) => Promise<{
14
16
  jobId: string;
@@ -228,4 +230,4 @@ declare const readMcpBacktestResult: (userName: string, id: string, offset?: num
228
230
  source: string;
229
231
  }>;
230
232
 
231
- export { MCP_JOB_TTL, McpCursorError, cancelMcpJob, enqueueMcpJob, isMcpRecord, mcpId, mcpJobDirectory, mcpJobStorageId, mcpPackageManifestHash, mcpProjectRoot, publicMcpJob, readAuthorizedMcpJob, readMcpBacktestPage, readMcpBacktestResult, readMcpChart, readMcpDeployments, readMcpEvaluationStats, readMcpJob, readMcpJobLogs, readMcpMarket, readMcpRuntimePage, readMcpSignal, readMcpStrategies, redactMcpData, redactMcpJobLog, requireMcpDeployment };
233
+ export { MCP_JOB_TTL, McpCursorError, cancelMcpJob, enqueueMcpJob, formatMcpArtifactLogLine, isMcpRecord, mcpId, mcpJobDirectory, mcpJobStorageId, mcpPackageManifestHash, mcpProjectRoot, publicMcpJob, readAuthorizedMcpJob, readMcpBacktestPage, readMcpBacktestResult, readMcpChart, readMcpDeployments, readMcpEvaluationStats, readMcpJob, readMcpJobLogs, readMcpMarket, readMcpRuntimePage, readMcpSignal, readMcpStrategies, redactMcpData, redactMcpJobLog, requireMcpDeployment };
package/dist/mcp.js CHANGED
@@ -781,6 +781,7 @@ __export(mcp_exports, {
781
781
  McpCursorError: () => McpCursorError,
782
782
  cancelMcpJob: () => cancelMcpJob,
783
783
  enqueueMcpJob: () => enqueueMcpJob,
784
+ formatMcpArtifactLogLine: () => formatMcpArtifactLogLine,
784
785
  isMcpRecord: () => isMcpRecord,
785
786
  mcpId: () => mcpId,
786
787
  mcpJobDirectory: () => mcpJobDirectory,
@@ -1133,11 +1134,8 @@ var validateEntryExecution = ({
1133
1134
  throw new EntrySubmissionValidationError(
1134
1135
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
1135
1136
  );
1136
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
1137
- throw new EntrySubmissionValidationError(
1138
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
1139
- );
1140
- return { netRiskRatio, plannedLossValue };
1137
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
1138
+ return { netRiskRatio, plannedLossValue, riskExceeded };
1141
1139
  };
1142
1140
 
1143
1141
  // src/strategy/entrySubmissionValidation.ts
@@ -5766,12 +5764,12 @@ var executeEntryOrder = async ({
5766
5764
  if (executionLimits?.maxLossValue != null) {
5767
5765
  signal.riskDecision = {
5768
5766
  stage: "order_plan",
5769
- status: "approved",
5770
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5767
+ status: economics2.riskExceeded ? "warning" : "approved",
5768
+ reason: economics2.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5771
5769
  plannedLossValue: economics2.plannedLossValue,
5772
5770
  maxLossValue: executionLimits.maxLossValue,
5773
5771
  limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
5774
- enforced: true
5772
+ enforced: false
5775
5773
  };
5776
5774
  }
5777
5775
  }
@@ -7097,6 +7095,9 @@ var createStrategyRuntime = ({
7097
7095
  });
7098
7096
  const strategyPolicyProfile = getPolicyProfile();
7099
7097
  const indicatorPeriods = (0, import_strategies6.buildDefaultIndicatorPeriods)(config);
7098
+ const strategyConfig = { ...config };
7099
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
7100
+ delete strategyConfig.SIMULATE_ORDERS;
7100
7101
  const hookBase = {
7101
7102
  connector,
7102
7103
  strategyName,
@@ -7107,7 +7108,7 @@ var createStrategyRuntime = ({
7107
7108
  accountId,
7108
7109
  deploymentId,
7109
7110
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
7110
- strategyConfig: config,
7111
+ strategyConfig,
7111
7112
  env,
7112
7113
  isConfigFromBacktest
7113
7114
  };
@@ -7175,7 +7176,7 @@ var createStrategyRuntime = ({
7175
7176
  );
7176
7177
  }
7177
7178
  };
7178
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
7179
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
7179
7180
  if (!hook) {
7180
7181
  return void 0;
7181
7182
  }
@@ -7195,17 +7196,18 @@ var createStrategyRuntime = ({
7195
7196
  entry: errorContext.entry,
7196
7197
  market: errorContext.market
7197
7198
  });
7198
- return void 0;
7199
+ return failureResult;
7199
7200
  }
7200
7201
  };
7201
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
7202
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
7202
7203
  const results = [];
7203
7204
  for (const hook of getProjectHookList(stage)) {
7204
7205
  const result = await invokeHook(
7205
7206
  stage,
7206
7207
  hook,
7207
7208
  params,
7208
- errorContext
7209
+ errorContext,
7210
+ failureResult
7209
7211
  );
7210
7212
  if (result !== void 0) {
7211
7213
  results.push(result);
@@ -7220,10 +7222,12 @@ var createStrategyRuntime = ({
7220
7222
  return invokeHook(stage, hook, params, errorContext);
7221
7223
  };
7222
7224
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
7225
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
7223
7226
  const projectResults = await invokeProjectHooks(
7224
7227
  stage,
7225
7228
  params,
7226
- errorContext
7229
+ errorContext,
7230
+ failureResult
7227
7231
  );
7228
7232
  const projectBlock = projectResults.find(
7229
7233
  (result) => result?.allow === false
@@ -7235,7 +7239,8 @@ var createStrategyRuntime = ({
7235
7239
  stage,
7236
7240
  hook,
7237
7241
  params,
7238
- errorContext
7242
+ errorContext,
7243
+ failureResult
7239
7244
  );
7240
7245
  };
7241
7246
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -7381,11 +7386,8 @@ var createStrategyRuntime = ({
7381
7386
  return enrichedBaseContext;
7382
7387
  }
7383
7388
  });
7384
- const coreConfig = { ...config };
7385
- delete coreConfig.RECORD_RUNTIME_TRADES;
7386
- delete coreConfig.SIMULATE_ORDERS;
7387
7389
  const core = await createCore({
7388
- config: coreConfig,
7390
+ config: strategyConfig,
7389
7391
  data,
7390
7392
  strategyApi,
7391
7393
  indicatorsState
@@ -9052,6 +9054,7 @@ var loadResolvedRuntimeStrategies = async ({
9052
9054
  var import_node_crypto5 = require("crypto");
9053
9055
  var import_promises3 = require("fs/promises");
9054
9056
  var import_node_path3 = __toESM(require("path"));
9057
+ var import_node_util = require("util");
9055
9058
  var import_redis3 = require("@tradejs/infra/redis");
9056
9059
  var MCP_JOB_TTL = 7 * 86400;
9057
9060
  var hash = (value) => (0, import_node_crypto5.createHash)("sha256").update(value).digest("hex");
@@ -9217,10 +9220,29 @@ var readAuthorizedMcpJob = async (principal, id) => {
9217
9220
  throw new Error("Insufficient scope");
9218
9221
  return job;
9219
9222
  };
9220
- var redactMcpJobLog = (line) => line.replace(/\u001b\[[0-9;]*m/g, "").replace(/\b(Bearer|Basic)\s+\S+/gi, "$1 [redacted]").replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]*:[^\s/@]+@/gi, "$1[redacted]@").replace(/((?:authorization|cookie)\s*:\s*)[^\r\n]+/gi, "$1[redacted]").replace(
9223
+ var redactMcpLogLine = (line) => line.replace(/\u001b\[[0-9;]*m/g, "").replace(/\b(Bearer|Basic)\s+\S+/gi, "$1 [redacted]").replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]*:[^\s/@]+@/gi, "$1[redacted]@").replace(/((?:authorization|cookie)\s*:\s*)[^\r\n]+/gi, "$1[redacted]").replace(
9221
9224
  /((?:[\w.-]*(?:secret|password|token|api[_-]?key|private[_-]?key|authorization|cookie|credential)[\w.-]*)["']?\s*[:=]\s*)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\s,;&}]+)/gi,
9222
9225
  "$1[redacted]"
9223
- ).slice(0, 1e3);
9226
+ );
9227
+ var MCP_LOG_LINE_LIMIT = 1e3;
9228
+ var redactMcpJobLog = (line) => redactMcpLogLine(line).slice(0, MCP_LOG_LINE_LIMIT);
9229
+ var formatMcpArtifactLogLine = (line) => {
9230
+ const text = redactMcpLogLine(
9231
+ (0, import_node_util.stripVTControlCharacters)(line).replace(/\r/g, "")
9232
+ );
9233
+ const fragments = [];
9234
+ let start = 0;
9235
+ while (start < text.length) {
9236
+ let end = Math.min(start + MCP_LOG_LINE_LIMIT, text.length);
9237
+ const lastCodeUnit = text.charCodeAt(end - 1);
9238
+ if (end < text.length && lastCodeUnit >= 55296 && lastCodeUnit <= 56319) {
9239
+ end -= 1;
9240
+ }
9241
+ fragments.push(redactMcpJobLog(text.slice(start, end)));
9242
+ start = end;
9243
+ }
9244
+ return fragments.join("\n") + "\n";
9245
+ };
9224
9246
  var readMcpJobLogs = async (principal, id, offset = 0, limit = 50) => {
9225
9247
  if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(limit) || limit < 1 || limit > 100)
9226
9248
  throw new Error("Select a non-negative log offset and a limit of 1\u2013100");
@@ -9683,6 +9705,7 @@ var readMcpBacktestResult = async (userName, id, offset = 0, limit = 20) => {
9683
9705
  McpCursorError,
9684
9706
  cancelMcpJob,
9685
9707
  enqueueMcpJob,
9708
+ formatMcpArtifactLogLine,
9686
9709
  isMcpRecord,
9687
9710
  mcpId,
9688
9711
  mcpJobDirectory,
package/dist/mcp.mjs CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  listRuntimeDeployments,
8
8
  loadResolvedRuntimeStrategies
9
9
  } from "./chunk-BO42QWAB.mjs";
10
- import "./chunk-KYGJBMKE.mjs";
10
+ import "./chunk-PB2KHBGH.mjs";
11
11
  import {
12
12
  ensureIndicatorPluginsLoaded
13
13
  } from "./chunk-UL5Z46JL.mjs";
@@ -37,6 +37,7 @@ import { getRuntimeStorageDayKey } from "@tradejs/core/time";
37
37
  import { createHash } from "crypto";
38
38
  import { readFile } from "fs/promises";
39
39
  import path from "path";
40
+ import { stripVTControlCharacters } from "util";
40
41
  import { getDataStrict, mcpStorage, redisKeys } from "@tradejs/infra/redis";
41
42
  var MCP_JOB_TTL = 7 * 86400;
42
43
  var hash = (value) => createHash("sha256").update(value).digest("hex");
@@ -202,10 +203,29 @@ var readAuthorizedMcpJob = async (principal, id) => {
202
203
  throw new Error("Insufficient scope");
203
204
  return job;
204
205
  };
205
- var redactMcpJobLog = (line) => line.replace(/\u001b\[[0-9;]*m/g, "").replace(/\b(Bearer|Basic)\s+\S+/gi, "$1 [redacted]").replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]*:[^\s/@]+@/gi, "$1[redacted]@").replace(/((?:authorization|cookie)\s*:\s*)[^\r\n]+/gi, "$1[redacted]").replace(
206
+ var redactMcpLogLine = (line) => line.replace(/\u001b\[[0-9;]*m/g, "").replace(/\b(Bearer|Basic)\s+\S+/gi, "$1 [redacted]").replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]*:[^\s/@]+@/gi, "$1[redacted]@").replace(/((?:authorization|cookie)\s*:\s*)[^\r\n]+/gi, "$1[redacted]").replace(
206
207
  /((?:[\w.-]*(?:secret|password|token|api[_-]?key|private[_-]?key|authorization|cookie|credential)[\w.-]*)["']?\s*[:=]\s*)(?:"[^"\r\n]*"|'[^'\r\n]*'|[^\s,;&}]+)/gi,
207
208
  "$1[redacted]"
208
- ).slice(0, 1e3);
209
+ );
210
+ var MCP_LOG_LINE_LIMIT = 1e3;
211
+ var redactMcpJobLog = (line) => redactMcpLogLine(line).slice(0, MCP_LOG_LINE_LIMIT);
212
+ var formatMcpArtifactLogLine = (line) => {
213
+ const text = redactMcpLogLine(
214
+ stripVTControlCharacters(line).replace(/\r/g, "")
215
+ );
216
+ const fragments = [];
217
+ let start = 0;
218
+ while (start < text.length) {
219
+ let end = Math.min(start + MCP_LOG_LINE_LIMIT, text.length);
220
+ const lastCodeUnit = text.charCodeAt(end - 1);
221
+ if (end < text.length && lastCodeUnit >= 55296 && lastCodeUnit <= 56319) {
222
+ end -= 1;
223
+ }
224
+ fragments.push(redactMcpJobLog(text.slice(start, end)));
225
+ start = end;
226
+ }
227
+ return fragments.join("\n") + "\n";
228
+ };
209
229
  var readMcpJobLogs = async (principal, id, offset = 0, limit = 50) => {
210
230
  if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isSafeInteger(limit) || limit < 1 || limit > 100)
211
231
  throw new Error("Select a non-negative log offset and a limit of 1\u2013100");
@@ -667,6 +687,7 @@ export {
667
687
  McpCursorError,
668
688
  cancelMcpJob,
669
689
  enqueueMcpJob,
690
+ formatMcpArtifactLogLine,
670
691
  isMcpRecord,
671
692
  mcpId,
672
693
  mcpJobDirectory,
package/dist/registry.js CHANGED
@@ -1112,11 +1112,8 @@ var validateEntryExecution = ({
1112
1112
  throw new EntrySubmissionValidationError(
1113
1113
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
1114
1114
  );
1115
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
1116
- throw new EntrySubmissionValidationError(
1117
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
1118
- );
1119
- return { netRiskRatio, plannedLossValue };
1115
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
1116
+ return { netRiskRatio, plannedLossValue, riskExceeded };
1120
1117
  };
1121
1118
 
1122
1119
  // src/strategy/entrySubmissionValidation.ts
@@ -5768,12 +5765,12 @@ var executeEntryOrder = async ({
5768
5765
  if (executionLimits?.maxLossValue != null) {
5769
5766
  signal.riskDecision = {
5770
5767
  stage: "order_plan",
5771
- status: "approved",
5772
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5768
+ status: economics2.riskExceeded ? "warning" : "approved",
5769
+ reason: economics2.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5773
5770
  plannedLossValue: economics2.plannedLossValue,
5774
5771
  maxLossValue: executionLimits.maxLossValue,
5775
5772
  limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
5776
- enforced: true
5773
+ enforced: false
5777
5774
  };
5778
5775
  }
5779
5776
  }
@@ -7099,6 +7096,9 @@ var createStrategyRuntime = ({
7099
7096
  });
7100
7097
  const strategyPolicyProfile = getPolicyProfile();
7101
7098
  const indicatorPeriods = (0, import_strategies6.buildDefaultIndicatorPeriods)(config);
7099
+ const strategyConfig = { ...config };
7100
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
7101
+ delete strategyConfig.SIMULATE_ORDERS;
7102
7102
  const hookBase = {
7103
7103
  connector,
7104
7104
  strategyName,
@@ -7109,7 +7109,7 @@ var createStrategyRuntime = ({
7109
7109
  accountId,
7110
7110
  deploymentId,
7111
7111
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
7112
- strategyConfig: config,
7112
+ strategyConfig,
7113
7113
  env,
7114
7114
  isConfigFromBacktest
7115
7115
  };
@@ -7177,7 +7177,7 @@ var createStrategyRuntime = ({
7177
7177
  );
7178
7178
  }
7179
7179
  };
7180
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
7180
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
7181
7181
  if (!hook) {
7182
7182
  return void 0;
7183
7183
  }
@@ -7197,17 +7197,18 @@ var createStrategyRuntime = ({
7197
7197
  entry: errorContext.entry,
7198
7198
  market: errorContext.market
7199
7199
  });
7200
- return void 0;
7200
+ return failureResult;
7201
7201
  }
7202
7202
  };
7203
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
7203
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
7204
7204
  const results = [];
7205
7205
  for (const hook of getProjectHookList(stage)) {
7206
7206
  const result = await invokeHook(
7207
7207
  stage,
7208
7208
  hook,
7209
7209
  params,
7210
- errorContext
7210
+ errorContext,
7211
+ failureResult
7211
7212
  );
7212
7213
  if (result !== void 0) {
7213
7214
  results.push(result);
@@ -7222,10 +7223,12 @@ var createStrategyRuntime = ({
7222
7223
  return invokeHook(stage, hook, params, errorContext);
7223
7224
  };
7224
7225
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
7226
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
7225
7227
  const projectResults = await invokeProjectHooks(
7226
7228
  stage,
7227
7229
  params,
7228
- errorContext
7230
+ errorContext,
7231
+ failureResult
7229
7232
  );
7230
7233
  const projectBlock = projectResults.find(
7231
7234
  (result) => result?.allow === false
@@ -7237,7 +7240,8 @@ var createStrategyRuntime = ({
7237
7240
  stage,
7238
7241
  hook,
7239
7242
  params,
7240
- errorContext
7243
+ errorContext,
7244
+ failureResult
7241
7245
  );
7242
7246
  };
7243
7247
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -7383,11 +7387,8 @@ var createStrategyRuntime = ({
7383
7387
  return enrichedBaseContext;
7384
7388
  }
7385
7389
  });
7386
- const coreConfig = { ...config };
7387
- delete coreConfig.RECORD_RUNTIME_TRADES;
7388
- delete coreConfig.SIMULATE_ORDERS;
7389
7390
  const core = await createCore({
7390
- config: coreConfig,
7391
+ config: strategyConfig,
7391
7392
  data,
7392
7393
  strategyApi,
7393
7394
  indicatorsState
package/dist/registry.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./chunk-JQOLTLEY.mjs";
2
- import "./chunk-KYGJBMKE.mjs";
2
+ import "./chunk-PB2KHBGH.mjs";
3
3
  import {
4
4
  ensureIndicatorPluginsLoaded,
5
5
  ensureStrategyPluginsLoaded,
@@ -2409,11 +2409,8 @@ var validateEntryExecution = ({
2409
2409
  throw new EntrySubmissionValidationError(
2410
2410
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
2411
2411
  );
2412
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
2413
- throw new EntrySubmissionValidationError(
2414
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
2415
- );
2416
- return { netRiskRatio, plannedLossValue };
2412
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
2413
+ return { netRiskRatio, plannedLossValue, riskExceeded };
2417
2414
  };
2418
2415
 
2419
2416
  // src/strategy/entrySubmissionValidation.ts
@@ -6752,12 +6749,12 @@ var executeEntryOrder = async ({
6752
6749
  if (executionLimits?.maxLossValue != null) {
6753
6750
  signal.riskDecision = {
6754
6751
  stage: "order_plan",
6755
- status: "approved",
6756
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
6752
+ status: economics2.riskExceeded ? "warning" : "approved",
6753
+ reason: economics2.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
6757
6754
  plannedLossValue: economics2.plannedLossValue,
6758
6755
  maxLossValue: executionLimits.maxLossValue,
6759
6756
  limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
6760
- enforced: true
6757
+ enforced: false
6761
6758
  };
6762
6759
  }
6763
6760
  }
@@ -8083,6 +8080,9 @@ var createStrategyRuntime = ({
8083
8080
  });
8084
8081
  const strategyPolicyProfile = getPolicyProfile();
8085
8082
  const indicatorPeriods = (0, import_strategies6.buildDefaultIndicatorPeriods)(config);
8083
+ const strategyConfig = { ...config };
8084
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
8085
+ delete strategyConfig.SIMULATE_ORDERS;
8086
8086
  const hookBase = {
8087
8087
  connector,
8088
8088
  strategyName,
@@ -8093,7 +8093,7 @@ var createStrategyRuntime = ({
8093
8093
  accountId,
8094
8094
  deploymentId,
8095
8095
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
8096
- strategyConfig: config,
8096
+ strategyConfig,
8097
8097
  env,
8098
8098
  isConfigFromBacktest
8099
8099
  };
@@ -8161,7 +8161,7 @@ var createStrategyRuntime = ({
8161
8161
  );
8162
8162
  }
8163
8163
  };
8164
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
8164
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
8165
8165
  if (!hook) {
8166
8166
  return void 0;
8167
8167
  }
@@ -8181,17 +8181,18 @@ var createStrategyRuntime = ({
8181
8181
  entry: errorContext.entry,
8182
8182
  market: errorContext.market
8183
8183
  });
8184
- return void 0;
8184
+ return failureResult;
8185
8185
  }
8186
8186
  };
8187
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
8187
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
8188
8188
  const results = [];
8189
8189
  for (const hook of getProjectHookList(stage)) {
8190
8190
  const result = await invokeHook(
8191
8191
  stage,
8192
8192
  hook,
8193
8193
  params,
8194
- errorContext
8194
+ errorContext,
8195
+ failureResult
8195
8196
  );
8196
8197
  if (result !== void 0) {
8197
8198
  results.push(result);
@@ -8206,10 +8207,12 @@ var createStrategyRuntime = ({
8206
8207
  return invokeHook(stage, hook, params, errorContext);
8207
8208
  };
8208
8209
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
8210
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
8209
8211
  const projectResults = await invokeProjectHooks(
8210
8212
  stage,
8211
8213
  params,
8212
- errorContext
8214
+ errorContext,
8215
+ failureResult
8213
8216
  );
8214
8217
  const projectBlock = projectResults.find(
8215
8218
  (result) => result?.allow === false
@@ -8221,7 +8224,8 @@ var createStrategyRuntime = ({
8221
8224
  stage,
8222
8225
  hook,
8223
8226
  params,
8224
- errorContext
8227
+ errorContext,
8228
+ failureResult
8225
8229
  );
8226
8230
  };
8227
8231
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -8367,11 +8371,8 @@ var createStrategyRuntime = ({
8367
8371
  return enrichedBaseContext;
8368
8372
  }
8369
8373
  });
8370
- const coreConfig = { ...config };
8371
- delete coreConfig.RECORD_RUNTIME_TRADES;
8372
- delete coreConfig.SIMULATE_ORDERS;
8373
8374
  const core = await createCore({
8374
- config: coreConfig,
8375
+ config: strategyConfig,
8375
8376
  data,
8376
8377
  strategyApi,
8377
8378
  indicatorsState
@@ -9,7 +9,7 @@ import {
9
9
  listRuntimeDeployments,
10
10
  loadResolvedRuntimeStrategies
11
11
  } from "./chunk-BO42QWAB.mjs";
12
- import "./chunk-KYGJBMKE.mjs";
12
+ import "./chunk-PB2KHBGH.mjs";
13
13
  import "./chunk-UL5Z46JL.mjs";
14
14
  import "./chunk-LZDXRXIU.mjs";
15
15
  import "./chunk-YR55Q355.mjs";
@@ -1115,11 +1115,8 @@ var validateEntryExecution = ({
1115
1115
  throw new EntrySubmissionValidationError(
1116
1116
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
1117
1117
  );
1118
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
1119
- throw new EntrySubmissionValidationError(
1120
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
1121
- );
1122
- return { netRiskRatio, plannedLossValue };
1118
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
1119
+ return { netRiskRatio, plannedLossValue, riskExceeded };
1123
1120
  };
1124
1121
 
1125
1122
  // src/strategy/entrySubmissionValidation.ts
@@ -5747,12 +5744,12 @@ var executeEntryOrder = async ({
5747
5744
  if (executionLimits?.maxLossValue != null) {
5748
5745
  signal.riskDecision = {
5749
5746
  stage: "order_plan",
5750
- status: "approved",
5751
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5747
+ status: economics2.riskExceeded ? "warning" : "approved",
5748
+ reason: economics2.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
5752
5749
  plannedLossValue: economics2.plannedLossValue,
5753
5750
  maxLossValue: executionLimits.maxLossValue,
5754
5751
  limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
5755
- enforced: true
5752
+ enforced: false
5756
5753
  };
5757
5754
  }
5758
5755
  }
@@ -7078,6 +7075,9 @@ var createStrategyRuntime = ({
7078
7075
  });
7079
7076
  const strategyPolicyProfile = getPolicyProfile();
7080
7077
  const indicatorPeriods = (0, import_strategies6.buildDefaultIndicatorPeriods)(config);
7078
+ const strategyConfig = { ...config };
7079
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
7080
+ delete strategyConfig.SIMULATE_ORDERS;
7081
7081
  const hookBase = {
7082
7082
  connector,
7083
7083
  strategyName,
@@ -7088,7 +7088,7 @@ var createStrategyRuntime = ({
7088
7088
  accountId,
7089
7089
  deploymentId,
7090
7090
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
7091
- strategyConfig: config,
7091
+ strategyConfig,
7092
7092
  env,
7093
7093
  isConfigFromBacktest
7094
7094
  };
@@ -7156,7 +7156,7 @@ var createStrategyRuntime = ({
7156
7156
  );
7157
7157
  }
7158
7158
  };
7159
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
7159
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
7160
7160
  if (!hook) {
7161
7161
  return void 0;
7162
7162
  }
@@ -7176,17 +7176,18 @@ var createStrategyRuntime = ({
7176
7176
  entry: errorContext.entry,
7177
7177
  market: errorContext.market
7178
7178
  });
7179
- return void 0;
7179
+ return failureResult;
7180
7180
  }
7181
7181
  };
7182
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
7182
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
7183
7183
  const results = [];
7184
7184
  for (const hook of getProjectHookList(stage)) {
7185
7185
  const result = await invokeHook(
7186
7186
  stage,
7187
7187
  hook,
7188
7188
  params,
7189
- errorContext
7189
+ errorContext,
7190
+ failureResult
7190
7191
  );
7191
7192
  if (result !== void 0) {
7192
7193
  results.push(result);
@@ -7201,10 +7202,12 @@ var createStrategyRuntime = ({
7201
7202
  return invokeHook(stage, hook, params, errorContext);
7202
7203
  };
7203
7204
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
7205
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
7204
7206
  const projectResults = await invokeProjectHooks(
7205
7207
  stage,
7206
7208
  params,
7207
- errorContext
7209
+ errorContext,
7210
+ failureResult
7208
7211
  );
7209
7212
  const projectBlock = projectResults.find(
7210
7213
  (result) => result?.allow === false
@@ -7216,7 +7219,8 @@ var createStrategyRuntime = ({
7216
7219
  stage,
7217
7220
  hook,
7218
7221
  params,
7219
- errorContext
7222
+ errorContext,
7223
+ failureResult
7220
7224
  );
7221
7225
  };
7222
7226
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -7362,11 +7366,8 @@ var createStrategyRuntime = ({
7362
7366
  return enrichedBaseContext;
7363
7367
  }
7364
7368
  });
7365
- const coreConfig = { ...config };
7366
- delete coreConfig.RECORD_RUNTIME_TRADES;
7367
- delete coreConfig.SIMULATE_ORDERS;
7368
7369
  const core = await createCore({
7369
- config: coreConfig,
7370
+ config: strategyConfig,
7370
7371
  data,
7371
7372
  strategyApi,
7372
7373
  indicatorsState
@@ -9,7 +9,7 @@ import {
9
9
  resolveRuntimeComposition,
10
10
  verifyRuntimeDeclaration
11
11
  } from "./chunk-BO42QWAB.mjs";
12
- import "./chunk-KYGJBMKE.mjs";
12
+ import "./chunk-PB2KHBGH.mjs";
13
13
  import "./chunk-UL5Z46JL.mjs";
14
14
  import "./chunk-LZDXRXIU.mjs";
15
15
  import "./chunk-YR55Q355.mjs";
@@ -2976,11 +2976,8 @@ var validateEntryExecution = ({
2976
2976
  throw new EntrySubmissionValidationError(
2977
2977
  "ENTRY_RR_BELOW_MIN_AT_SUBMISSION"
2978
2978
  );
2979
- if (limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9))
2980
- throw new EntrySubmissionValidationError(
2981
- "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION"
2982
- );
2983
- return { netRiskRatio, plannedLossValue };
2979
+ const riskExceeded = limits.maxLossValue != null && plannedLossValue > limits.maxLossValue * (1 + 1e-9);
2980
+ return { netRiskRatio, plannedLossValue, riskExceeded };
2984
2981
  };
2985
2982
 
2986
2983
  // src/strategy/entrySubmissionValidation.ts
@@ -6009,12 +6006,12 @@ var executeEntryOrder = async ({
6009
6006
  if (executionLimits?.maxLossValue != null) {
6010
6007
  signal.riskDecision = {
6011
6008
  stage: "order_plan",
6012
- status: "approved",
6013
- reason: "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
6009
+ status: economics2.riskExceeded ? "warning" : "approved",
6010
+ reason: economics2.riskExceeded ? "ENTRY_RISK_EXCEEDS_MAX_LOSS_AT_SUBMISSION" : "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE",
6014
6011
  plannedLossValue: economics2.plannedLossValue,
6015
6012
  maxLossValue: executionLimits.maxLossValue,
6016
6013
  limitUtilization: economics2.plannedLossValue / executionLimits.maxLossValue,
6017
- enforced: true
6014
+ enforced: false
6018
6015
  };
6019
6016
  }
6020
6017
  }
@@ -7340,6 +7337,9 @@ var createStrategyRuntime = ({
7340
7337
  });
7341
7338
  const strategyPolicyProfile = getPolicyProfile();
7342
7339
  const indicatorPeriods = (0, import_strategies6.buildDefaultIndicatorPeriods)(config);
7340
+ const strategyConfig = { ...config };
7341
+ delete strategyConfig.RECORD_RUNTIME_TRADES;
7342
+ delete strategyConfig.SIMULATE_ORDERS;
7343
7343
  const hookBase = {
7344
7344
  connector,
7345
7345
  strategyName,
@@ -7350,7 +7350,7 @@ var createStrategyRuntime = ({
7350
7350
  accountId,
7351
7351
  deploymentId,
7352
7352
  policyProfileId: strategyPolicyProfile?.id ?? requestedPolicyProfileId,
7353
- strategyConfig: config,
7353
+ strategyConfig,
7354
7354
  env,
7355
7355
  isConfigFromBacktest
7356
7356
  };
@@ -7418,7 +7418,7 @@ var createStrategyRuntime = ({
7418
7418
  );
7419
7419
  }
7420
7420
  };
7421
- const invokeHook = async (stage, hook, params, errorContext = {}) => {
7421
+ const invokeHook = async (stage, hook, params, errorContext = {}, failureResult) => {
7422
7422
  if (!hook) {
7423
7423
  return void 0;
7424
7424
  }
@@ -7438,17 +7438,18 @@ var createStrategyRuntime = ({
7438
7438
  entry: errorContext.entry,
7439
7439
  market: errorContext.market
7440
7440
  });
7441
- return void 0;
7441
+ return failureResult;
7442
7442
  }
7443
7443
  };
7444
- const invokeProjectHooks = async (stage, params, errorContext = {}) => {
7444
+ const invokeProjectHooks = async (stage, params, errorContext = {}, failureResult) => {
7445
7445
  const results = [];
7446
7446
  for (const hook of getProjectHookList(stage)) {
7447
7447
  const result = await invokeHook(
7448
7448
  stage,
7449
7449
  hook,
7450
7450
  params,
7451
- errorContext
7451
+ errorContext,
7452
+ failureResult
7452
7453
  );
7453
7454
  if (result !== void 0) {
7454
7455
  results.push(result);
@@ -7463,10 +7464,12 @@ var createStrategyRuntime = ({
7463
7464
  return invokeHook(stage, hook, params, errorContext);
7464
7465
  };
7465
7466
  const invokeGateHooks = async (stage, hook, params, errorContext = {}) => {
7467
+ const failureResult = stage === "beforeEntryGate" ? { allow: false, reason: "ERROR" } : void 0;
7466
7468
  const projectResults = await invokeProjectHooks(
7467
7469
  stage,
7468
7470
  params,
7469
- errorContext
7471
+ errorContext,
7472
+ failureResult
7470
7473
  );
7471
7474
  const projectBlock = projectResults.find(
7472
7475
  (result) => result?.allow === false
@@ -7478,7 +7481,8 @@ var createStrategyRuntime = ({
7478
7481
  stage,
7479
7482
  hook,
7480
7483
  params,
7481
- errorContext
7484
+ errorContext,
7485
+ failureResult
7482
7486
  );
7483
7487
  };
7484
7488
  const applyProjectAfterCoreDecisionHooks = async ({
@@ -7624,11 +7628,8 @@ var createStrategyRuntime = ({
7624
7628
  return enrichedBaseContext;
7625
7629
  }
7626
7630
  });
7627
- const coreConfig = { ...config };
7628
- delete coreConfig.RECORD_RUNTIME_TRADES;
7629
- delete coreConfig.SIMULATE_ORDERS;
7630
7631
  const core = await createCore({
7631
- config: coreConfig,
7632
+ config: strategyConfig,
7632
7633
  data,
7633
7634
  strategyApi,
7634
7635
  indicatorsState
@@ -23,7 +23,7 @@ import {
23
23
  resolveHyperliquidPerpFromSignalSymbol,
24
24
  resolveStrategyConfig,
25
25
  validateEntryProtectionAtArrival
26
- } from "./chunk-KYGJBMKE.mjs";
26
+ } from "./chunk-PB2KHBGH.mjs";
27
27
  import {
28
28
  DEFAULT_AI_MODEL,
29
29
  MAX_AI_SERIES_POINTS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/node",
3
- "version": "3.1.29-beta.289",
3
+ "version": "3.1.29-beta.290",
4
4
  "description": "Node-only runtime for the TradeJS TypeScript framework: strategies, backtests, Pine strategy loading, and plugin registries.",
5
5
  "keywords": [
6
6
  "tradejs",
@@ -105,9 +105,9 @@
105
105
  "dependencies": {
106
106
  "@langchain/core": "^1.2.3",
107
107
  "@langchain/openai": "^1.5.5",
108
- "@tradejs/core": "^3.1.29-beta.289",
109
- "@tradejs/infra": "^3.1.29-beta.289",
110
- "@tradejs/types": "^3.1.29-beta.289",
108
+ "@tradejs/core": "^3.1.29-beta.290",
109
+ "@tradejs/infra": "^3.1.29-beta.290",
110
+ "@tradejs/types": "^3.1.29-beta.290",
111
111
  "@types/node": "^24",
112
112
  "chalk": "4.1.2",
113
113
  "ioredis": "5.11.1",
@@ -120,7 +120,7 @@
120
120
  "typescript": "^5.9"
121
121
  },
122
122
  "devDependencies": {
123
- "@tradejs/indicators": "^3.1.29-beta.289",
123
+ "@tradejs/indicators": "^3.1.29-beta.290",
124
124
  "@tradejs/strategy-adaptive-momentum-ribbon": "3.0.5",
125
125
  "@tradejs/strategy-hyperliquid-consensus": "3.0.5",
126
126
  "@tradejs/strategy-kit": "3.0.6",