@tradejs/node 3.1.26-beta.244 → 3.1.27-beta.245
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 +95 -2
- package/dist/backtest.mjs +1 -1
- package/dist/{chunk-6DGLTGLW.mjs → chunk-XHNJ757K.mjs} +95 -2
- package/dist/registry.js +95 -2
- package/dist/registry.mjs +1 -1
- package/dist/runtimeDashboard.js +95 -2
- package/dist/runtimeDashboard.mjs +1 -1
- package/dist/runtimeStrategies.js +95 -2
- package/dist/runtimeStrategies.mjs +1 -1
- package/dist/strategies.js +95 -2
- package/dist/strategies.mjs +1 -1
- package/package.json +5 -5
package/dist/backtest.js
CHANGED
|
@@ -4927,6 +4927,68 @@ var buildAiHookContext = ({
|
|
|
4927
4927
|
};
|
|
4928
4928
|
};
|
|
4929
4929
|
|
|
4930
|
+
// src/strategy/runtimeDecisionTelemetry.ts
|
|
4931
|
+
var finitePositive = (value) => {
|
|
4932
|
+
const parsed = Number(value);
|
|
4933
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
4934
|
+
};
|
|
4935
|
+
var round = (value) => Number(value.toFixed(12));
|
|
4936
|
+
var assessRuntimeEntryRisk = ({
|
|
4937
|
+
qty,
|
|
4938
|
+
entryPrice,
|
|
4939
|
+
stopLossPrice,
|
|
4940
|
+
maxLossValue
|
|
4941
|
+
}) => {
|
|
4942
|
+
const normalizedQty = finitePositive(qty);
|
|
4943
|
+
const normalizedEntryPrice = finitePositive(entryPrice);
|
|
4944
|
+
const normalizedStopLossPrice = finitePositive(stopLossPrice);
|
|
4945
|
+
const normalizedMaxLossValue = finitePositive(maxLossValue);
|
|
4946
|
+
const plannedLossValue = normalizedQty != null && normalizedEntryPrice != null && normalizedStopLossPrice != null ? round(
|
|
4947
|
+
Math.abs(normalizedEntryPrice - normalizedStopLossPrice) * normalizedQty
|
|
4948
|
+
) : null;
|
|
4949
|
+
if (plannedLossValue == null) {
|
|
4950
|
+
return {
|
|
4951
|
+
stage: "order_plan",
|
|
4952
|
+
status: "unavailable",
|
|
4953
|
+
reason: "ORDER_PLAN_RISK_INPUTS_UNAVAILABLE",
|
|
4954
|
+
plannedLossValue: null,
|
|
4955
|
+
maxLossValue: normalizedMaxLossValue,
|
|
4956
|
+
limitUtilization: null,
|
|
4957
|
+
enforced: false
|
|
4958
|
+
};
|
|
4959
|
+
}
|
|
4960
|
+
if (normalizedMaxLossValue == null) {
|
|
4961
|
+
return {
|
|
4962
|
+
stage: "order_plan",
|
|
4963
|
+
status: "unavailable",
|
|
4964
|
+
reason: "MAX_LOSS_VALUE_UNAVAILABLE",
|
|
4965
|
+
plannedLossValue,
|
|
4966
|
+
maxLossValue: null,
|
|
4967
|
+
limitUtilization: null,
|
|
4968
|
+
enforced: false
|
|
4969
|
+
};
|
|
4970
|
+
}
|
|
4971
|
+
const limitUtilization = round(plannedLossValue / normalizedMaxLossValue);
|
|
4972
|
+
const withinLimit = plannedLossValue <= normalizedMaxLossValue * (1 + 1e-9);
|
|
4973
|
+
return {
|
|
4974
|
+
stage: "order_plan",
|
|
4975
|
+
status: withinLimit ? "approved" : "rejected",
|
|
4976
|
+
reason: withinLimit ? "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE" : "PLANNED_LOSS_EXCEEDS_MAX_LOSS_VALUE",
|
|
4977
|
+
plannedLossValue,
|
|
4978
|
+
maxLossValue: normalizedMaxLossValue,
|
|
4979
|
+
limitUtilization,
|
|
4980
|
+
enforced: false
|
|
4981
|
+
};
|
|
4982
|
+
};
|
|
4983
|
+
var buildRuntimeAdmissionDecision = ({
|
|
4984
|
+
status,
|
|
4985
|
+
reason
|
|
4986
|
+
}) => ({
|
|
4987
|
+
stage: "runtime_admission",
|
|
4988
|
+
status,
|
|
4989
|
+
reason
|
|
4990
|
+
});
|
|
4991
|
+
|
|
4930
4992
|
// src/strategy/runtimeHooks.ts
|
|
4931
4993
|
var normalizeConfigHookList = (value) => {
|
|
4932
4994
|
if (Array.isArray(value)) {
|
|
@@ -6050,6 +6112,12 @@ var createStrategyRuntime = ({
|
|
|
6050
6112
|
if (decisionHookCtx.policyProfileId) {
|
|
6051
6113
|
signal.policyProfileId = decisionHookCtx.policyProfileId;
|
|
6052
6114
|
}
|
|
6115
|
+
signal.riskDecision = assessRuntimeEntryRisk({
|
|
6116
|
+
qty: decision.orderPlan.qty,
|
|
6117
|
+
entryPrice: decision.entryContext.prices.currentPrice,
|
|
6118
|
+
stopLossPrice: decision.orderPlan.stopLossPrice,
|
|
6119
|
+
maxLossValue: runtimeLineage?.maxLossValue ?? config.MAX_LOSS_VALUE
|
|
6120
|
+
});
|
|
6053
6121
|
}
|
|
6054
6122
|
const entry = buildHookEntry({
|
|
6055
6123
|
decision,
|
|
@@ -6159,13 +6227,16 @@ var createStrategyRuntime = ({
|
|
|
6159
6227
|
signal.orderStatus = "skipped";
|
|
6160
6228
|
signal.orderSkipReason = skipReason;
|
|
6161
6229
|
signal.strategyRevision = strategyRevision;
|
|
6230
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6231
|
+
status: "rejected",
|
|
6232
|
+
reason: skipReason
|
|
6233
|
+
});
|
|
6162
6234
|
}
|
|
6163
6235
|
return signal ?? skipReason;
|
|
6164
6236
|
}
|
|
6165
6237
|
if (!shouldMakeOrder) {
|
|
6166
6238
|
if (signal) {
|
|
6167
|
-
|
|
6168
|
-
signal.orderSkipReason = getEntrySkipReason({
|
|
6239
|
+
const skipReason = getEntrySkipReason({
|
|
6169
6240
|
makeOrdersEnabled,
|
|
6170
6241
|
env,
|
|
6171
6242
|
ml,
|
|
@@ -6173,6 +6244,12 @@ var createStrategyRuntime = ({
|
|
|
6173
6244
|
quality,
|
|
6174
6245
|
minAiQuality
|
|
6175
6246
|
});
|
|
6247
|
+
signal.orderStatus = "skipped";
|
|
6248
|
+
signal.orderSkipReason = skipReason;
|
|
6249
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6250
|
+
status: "not_applicable",
|
|
6251
|
+
reason: `ENTRY_POLICY_REJECTED:${skipReason}`
|
|
6252
|
+
});
|
|
6176
6253
|
}
|
|
6177
6254
|
return signal ?? decision.code;
|
|
6178
6255
|
}
|
|
@@ -6195,10 +6272,20 @@ var createStrategyRuntime = ({
|
|
|
6195
6272
|
if (signal) {
|
|
6196
6273
|
signal.orderStatus = "skipped";
|
|
6197
6274
|
signal.orderSkipReason = skipReason;
|
|
6275
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6276
|
+
status: "rejected",
|
|
6277
|
+
reason: skipReason
|
|
6278
|
+
});
|
|
6198
6279
|
}
|
|
6199
6280
|
return signal ?? skipReason;
|
|
6200
6281
|
}
|
|
6201
6282
|
if (backtestEntryDelayBars > 0) {
|
|
6283
|
+
if (signal) {
|
|
6284
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6285
|
+
status: "approved",
|
|
6286
|
+
reason: "ENTRY_ADMITTED"
|
|
6287
|
+
});
|
|
6288
|
+
}
|
|
6202
6289
|
pendingBacktestEntry = {
|
|
6203
6290
|
delayBars: backtestEntryDelayBars,
|
|
6204
6291
|
delayBarsRemaining: backtestEntryDelayBars,
|
|
@@ -6212,6 +6299,12 @@ var createStrategyRuntime = ({
|
|
|
6212
6299
|
};
|
|
6213
6300
|
return `BACKTEST_ENTRY_DELAY_QUEUED:${backtestEntryDelayBars}`;
|
|
6214
6301
|
}
|
|
6302
|
+
if (signal) {
|
|
6303
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6304
|
+
status: "approved",
|
|
6305
|
+
reason: "ENTRY_ADMITTED"
|
|
6306
|
+
});
|
|
6307
|
+
}
|
|
6215
6308
|
return executeEntryDecision({
|
|
6216
6309
|
connector,
|
|
6217
6310
|
symbol,
|
package/dist/backtest.mjs
CHANGED
|
@@ -3272,6 +3272,68 @@ var buildAiHookContext = ({
|
|
|
3272
3272
|
};
|
|
3273
3273
|
};
|
|
3274
3274
|
|
|
3275
|
+
// src/strategy/runtimeDecisionTelemetry.ts
|
|
3276
|
+
var finitePositive = (value) => {
|
|
3277
|
+
const parsed = Number(value);
|
|
3278
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
3279
|
+
};
|
|
3280
|
+
var round = (value) => Number(value.toFixed(12));
|
|
3281
|
+
var assessRuntimeEntryRisk = ({
|
|
3282
|
+
qty,
|
|
3283
|
+
entryPrice,
|
|
3284
|
+
stopLossPrice,
|
|
3285
|
+
maxLossValue
|
|
3286
|
+
}) => {
|
|
3287
|
+
const normalizedQty = finitePositive(qty);
|
|
3288
|
+
const normalizedEntryPrice = finitePositive(entryPrice);
|
|
3289
|
+
const normalizedStopLossPrice = finitePositive(stopLossPrice);
|
|
3290
|
+
const normalizedMaxLossValue = finitePositive(maxLossValue);
|
|
3291
|
+
const plannedLossValue = normalizedQty != null && normalizedEntryPrice != null && normalizedStopLossPrice != null ? round(
|
|
3292
|
+
Math.abs(normalizedEntryPrice - normalizedStopLossPrice) * normalizedQty
|
|
3293
|
+
) : null;
|
|
3294
|
+
if (plannedLossValue == null) {
|
|
3295
|
+
return {
|
|
3296
|
+
stage: "order_plan",
|
|
3297
|
+
status: "unavailable",
|
|
3298
|
+
reason: "ORDER_PLAN_RISK_INPUTS_UNAVAILABLE",
|
|
3299
|
+
plannedLossValue: null,
|
|
3300
|
+
maxLossValue: normalizedMaxLossValue,
|
|
3301
|
+
limitUtilization: null,
|
|
3302
|
+
enforced: false
|
|
3303
|
+
};
|
|
3304
|
+
}
|
|
3305
|
+
if (normalizedMaxLossValue == null) {
|
|
3306
|
+
return {
|
|
3307
|
+
stage: "order_plan",
|
|
3308
|
+
status: "unavailable",
|
|
3309
|
+
reason: "MAX_LOSS_VALUE_UNAVAILABLE",
|
|
3310
|
+
plannedLossValue,
|
|
3311
|
+
maxLossValue: null,
|
|
3312
|
+
limitUtilization: null,
|
|
3313
|
+
enforced: false
|
|
3314
|
+
};
|
|
3315
|
+
}
|
|
3316
|
+
const limitUtilization = round(plannedLossValue / normalizedMaxLossValue);
|
|
3317
|
+
const withinLimit = plannedLossValue <= normalizedMaxLossValue * (1 + 1e-9);
|
|
3318
|
+
return {
|
|
3319
|
+
stage: "order_plan",
|
|
3320
|
+
status: withinLimit ? "approved" : "rejected",
|
|
3321
|
+
reason: withinLimit ? "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE" : "PLANNED_LOSS_EXCEEDS_MAX_LOSS_VALUE",
|
|
3322
|
+
plannedLossValue,
|
|
3323
|
+
maxLossValue: normalizedMaxLossValue,
|
|
3324
|
+
limitUtilization,
|
|
3325
|
+
enforced: false
|
|
3326
|
+
};
|
|
3327
|
+
};
|
|
3328
|
+
var buildRuntimeAdmissionDecision = ({
|
|
3329
|
+
status,
|
|
3330
|
+
reason
|
|
3331
|
+
}) => ({
|
|
3332
|
+
stage: "runtime_admission",
|
|
3333
|
+
status,
|
|
3334
|
+
reason
|
|
3335
|
+
});
|
|
3336
|
+
|
|
3275
3337
|
// src/strategy/runtimeHooks.ts
|
|
3276
3338
|
var normalizeConfigHookList = (value) => {
|
|
3277
3339
|
if (Array.isArray(value)) {
|
|
@@ -4397,6 +4459,12 @@ var createStrategyRuntime = ({
|
|
|
4397
4459
|
if (decisionHookCtx.policyProfileId) {
|
|
4398
4460
|
signal.policyProfileId = decisionHookCtx.policyProfileId;
|
|
4399
4461
|
}
|
|
4462
|
+
signal.riskDecision = assessRuntimeEntryRisk({
|
|
4463
|
+
qty: decision.orderPlan.qty,
|
|
4464
|
+
entryPrice: decision.entryContext.prices.currentPrice,
|
|
4465
|
+
stopLossPrice: decision.orderPlan.stopLossPrice,
|
|
4466
|
+
maxLossValue: runtimeLineage?.maxLossValue ?? config.MAX_LOSS_VALUE
|
|
4467
|
+
});
|
|
4400
4468
|
}
|
|
4401
4469
|
const entry = buildHookEntry({
|
|
4402
4470
|
decision,
|
|
@@ -4506,13 +4574,16 @@ var createStrategyRuntime = ({
|
|
|
4506
4574
|
signal.orderStatus = "skipped";
|
|
4507
4575
|
signal.orderSkipReason = skipReason;
|
|
4508
4576
|
signal.strategyRevision = strategyRevision;
|
|
4577
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
4578
|
+
status: "rejected",
|
|
4579
|
+
reason: skipReason
|
|
4580
|
+
});
|
|
4509
4581
|
}
|
|
4510
4582
|
return signal ?? skipReason;
|
|
4511
4583
|
}
|
|
4512
4584
|
if (!shouldMakeOrder) {
|
|
4513
4585
|
if (signal) {
|
|
4514
|
-
|
|
4515
|
-
signal.orderSkipReason = getEntrySkipReason({
|
|
4586
|
+
const skipReason = getEntrySkipReason({
|
|
4516
4587
|
makeOrdersEnabled,
|
|
4517
4588
|
env,
|
|
4518
4589
|
ml,
|
|
@@ -4520,6 +4591,12 @@ var createStrategyRuntime = ({
|
|
|
4520
4591
|
quality,
|
|
4521
4592
|
minAiQuality
|
|
4522
4593
|
});
|
|
4594
|
+
signal.orderStatus = "skipped";
|
|
4595
|
+
signal.orderSkipReason = skipReason;
|
|
4596
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
4597
|
+
status: "not_applicable",
|
|
4598
|
+
reason: `ENTRY_POLICY_REJECTED:${skipReason}`
|
|
4599
|
+
});
|
|
4523
4600
|
}
|
|
4524
4601
|
return signal ?? decision.code;
|
|
4525
4602
|
}
|
|
@@ -4542,10 +4619,20 @@ var createStrategyRuntime = ({
|
|
|
4542
4619
|
if (signal) {
|
|
4543
4620
|
signal.orderStatus = "skipped";
|
|
4544
4621
|
signal.orderSkipReason = skipReason;
|
|
4622
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
4623
|
+
status: "rejected",
|
|
4624
|
+
reason: skipReason
|
|
4625
|
+
});
|
|
4545
4626
|
}
|
|
4546
4627
|
return signal ?? skipReason;
|
|
4547
4628
|
}
|
|
4548
4629
|
if (backtestEntryDelayBars > 0) {
|
|
4630
|
+
if (signal) {
|
|
4631
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
4632
|
+
status: "approved",
|
|
4633
|
+
reason: "ENTRY_ADMITTED"
|
|
4634
|
+
});
|
|
4635
|
+
}
|
|
4549
4636
|
pendingBacktestEntry = {
|
|
4550
4637
|
delayBars: backtestEntryDelayBars,
|
|
4551
4638
|
delayBarsRemaining: backtestEntryDelayBars,
|
|
@@ -4559,6 +4646,12 @@ var createStrategyRuntime = ({
|
|
|
4559
4646
|
};
|
|
4560
4647
|
return `BACKTEST_ENTRY_DELAY_QUEUED:${backtestEntryDelayBars}`;
|
|
4561
4648
|
}
|
|
4649
|
+
if (signal) {
|
|
4650
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
4651
|
+
status: "approved",
|
|
4652
|
+
reason: "ENTRY_ADMITTED"
|
|
4653
|
+
});
|
|
4654
|
+
}
|
|
4562
4655
|
return executeEntryDecision({
|
|
4563
4656
|
connector,
|
|
4564
4657
|
symbol,
|
package/dist/registry.js
CHANGED
|
@@ -4965,6 +4965,68 @@ var buildAiHookContext = ({
|
|
|
4965
4965
|
};
|
|
4966
4966
|
};
|
|
4967
4967
|
|
|
4968
|
+
// src/strategy/runtimeDecisionTelemetry.ts
|
|
4969
|
+
var finitePositive = (value) => {
|
|
4970
|
+
const parsed = Number(value);
|
|
4971
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
4972
|
+
};
|
|
4973
|
+
var round = (value) => Number(value.toFixed(12));
|
|
4974
|
+
var assessRuntimeEntryRisk = ({
|
|
4975
|
+
qty,
|
|
4976
|
+
entryPrice,
|
|
4977
|
+
stopLossPrice,
|
|
4978
|
+
maxLossValue
|
|
4979
|
+
}) => {
|
|
4980
|
+
const normalizedQty = finitePositive(qty);
|
|
4981
|
+
const normalizedEntryPrice = finitePositive(entryPrice);
|
|
4982
|
+
const normalizedStopLossPrice = finitePositive(stopLossPrice);
|
|
4983
|
+
const normalizedMaxLossValue = finitePositive(maxLossValue);
|
|
4984
|
+
const plannedLossValue = normalizedQty != null && normalizedEntryPrice != null && normalizedStopLossPrice != null ? round(
|
|
4985
|
+
Math.abs(normalizedEntryPrice - normalizedStopLossPrice) * normalizedQty
|
|
4986
|
+
) : null;
|
|
4987
|
+
if (plannedLossValue == null) {
|
|
4988
|
+
return {
|
|
4989
|
+
stage: "order_plan",
|
|
4990
|
+
status: "unavailable",
|
|
4991
|
+
reason: "ORDER_PLAN_RISK_INPUTS_UNAVAILABLE",
|
|
4992
|
+
plannedLossValue: null,
|
|
4993
|
+
maxLossValue: normalizedMaxLossValue,
|
|
4994
|
+
limitUtilization: null,
|
|
4995
|
+
enforced: false
|
|
4996
|
+
};
|
|
4997
|
+
}
|
|
4998
|
+
if (normalizedMaxLossValue == null) {
|
|
4999
|
+
return {
|
|
5000
|
+
stage: "order_plan",
|
|
5001
|
+
status: "unavailable",
|
|
5002
|
+
reason: "MAX_LOSS_VALUE_UNAVAILABLE",
|
|
5003
|
+
plannedLossValue,
|
|
5004
|
+
maxLossValue: null,
|
|
5005
|
+
limitUtilization: null,
|
|
5006
|
+
enforced: false
|
|
5007
|
+
};
|
|
5008
|
+
}
|
|
5009
|
+
const limitUtilization = round(plannedLossValue / normalizedMaxLossValue);
|
|
5010
|
+
const withinLimit = plannedLossValue <= normalizedMaxLossValue * (1 + 1e-9);
|
|
5011
|
+
return {
|
|
5012
|
+
stage: "order_plan",
|
|
5013
|
+
status: withinLimit ? "approved" : "rejected",
|
|
5014
|
+
reason: withinLimit ? "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE" : "PLANNED_LOSS_EXCEEDS_MAX_LOSS_VALUE",
|
|
5015
|
+
plannedLossValue,
|
|
5016
|
+
maxLossValue: normalizedMaxLossValue,
|
|
5017
|
+
limitUtilization,
|
|
5018
|
+
enforced: false
|
|
5019
|
+
};
|
|
5020
|
+
};
|
|
5021
|
+
var buildRuntimeAdmissionDecision = ({
|
|
5022
|
+
status,
|
|
5023
|
+
reason
|
|
5024
|
+
}) => ({
|
|
5025
|
+
stage: "runtime_admission",
|
|
5026
|
+
status,
|
|
5027
|
+
reason
|
|
5028
|
+
});
|
|
5029
|
+
|
|
4968
5030
|
// src/strategy/runtimeHooks.ts
|
|
4969
5031
|
var normalizeConfigHookList = (value) => {
|
|
4970
5032
|
if (Array.isArray(value)) {
|
|
@@ -6088,6 +6150,12 @@ var createStrategyRuntime = ({
|
|
|
6088
6150
|
if (decisionHookCtx.policyProfileId) {
|
|
6089
6151
|
signal.policyProfileId = decisionHookCtx.policyProfileId;
|
|
6090
6152
|
}
|
|
6153
|
+
signal.riskDecision = assessRuntimeEntryRisk({
|
|
6154
|
+
qty: decision.orderPlan.qty,
|
|
6155
|
+
entryPrice: decision.entryContext.prices.currentPrice,
|
|
6156
|
+
stopLossPrice: decision.orderPlan.stopLossPrice,
|
|
6157
|
+
maxLossValue: runtimeLineage?.maxLossValue ?? config.MAX_LOSS_VALUE
|
|
6158
|
+
});
|
|
6091
6159
|
}
|
|
6092
6160
|
const entry = buildHookEntry({
|
|
6093
6161
|
decision,
|
|
@@ -6197,13 +6265,16 @@ var createStrategyRuntime = ({
|
|
|
6197
6265
|
signal.orderStatus = "skipped";
|
|
6198
6266
|
signal.orderSkipReason = skipReason;
|
|
6199
6267
|
signal.strategyRevision = strategyRevision;
|
|
6268
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6269
|
+
status: "rejected",
|
|
6270
|
+
reason: skipReason
|
|
6271
|
+
});
|
|
6200
6272
|
}
|
|
6201
6273
|
return signal ?? skipReason;
|
|
6202
6274
|
}
|
|
6203
6275
|
if (!shouldMakeOrder) {
|
|
6204
6276
|
if (signal) {
|
|
6205
|
-
|
|
6206
|
-
signal.orderSkipReason = getEntrySkipReason({
|
|
6277
|
+
const skipReason = getEntrySkipReason({
|
|
6207
6278
|
makeOrdersEnabled,
|
|
6208
6279
|
env,
|
|
6209
6280
|
ml,
|
|
@@ -6211,6 +6282,12 @@ var createStrategyRuntime = ({
|
|
|
6211
6282
|
quality,
|
|
6212
6283
|
minAiQuality
|
|
6213
6284
|
});
|
|
6285
|
+
signal.orderStatus = "skipped";
|
|
6286
|
+
signal.orderSkipReason = skipReason;
|
|
6287
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6288
|
+
status: "not_applicable",
|
|
6289
|
+
reason: `ENTRY_POLICY_REJECTED:${skipReason}`
|
|
6290
|
+
});
|
|
6214
6291
|
}
|
|
6215
6292
|
return signal ?? decision.code;
|
|
6216
6293
|
}
|
|
@@ -6233,10 +6310,20 @@ var createStrategyRuntime = ({
|
|
|
6233
6310
|
if (signal) {
|
|
6234
6311
|
signal.orderStatus = "skipped";
|
|
6235
6312
|
signal.orderSkipReason = skipReason;
|
|
6313
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6314
|
+
status: "rejected",
|
|
6315
|
+
reason: skipReason
|
|
6316
|
+
});
|
|
6236
6317
|
}
|
|
6237
6318
|
return signal ?? skipReason;
|
|
6238
6319
|
}
|
|
6239
6320
|
if (backtestEntryDelayBars > 0) {
|
|
6321
|
+
if (signal) {
|
|
6322
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6323
|
+
status: "approved",
|
|
6324
|
+
reason: "ENTRY_ADMITTED"
|
|
6325
|
+
});
|
|
6326
|
+
}
|
|
6240
6327
|
pendingBacktestEntry = {
|
|
6241
6328
|
delayBars: backtestEntryDelayBars,
|
|
6242
6329
|
delayBarsRemaining: backtestEntryDelayBars,
|
|
@@ -6250,6 +6337,12 @@ var createStrategyRuntime = ({
|
|
|
6250
6337
|
};
|
|
6251
6338
|
return `BACKTEST_ENTRY_DELAY_QUEUED:${backtestEntryDelayBars}`;
|
|
6252
6339
|
}
|
|
6340
|
+
if (signal) {
|
|
6341
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6342
|
+
status: "approved",
|
|
6343
|
+
reason: "ENTRY_ADMITTED"
|
|
6344
|
+
});
|
|
6345
|
+
}
|
|
6253
6346
|
return executeEntryDecision({
|
|
6254
6347
|
connector,
|
|
6255
6348
|
symbol,
|
package/dist/registry.mjs
CHANGED
package/dist/runtimeDashboard.js
CHANGED
|
@@ -5934,6 +5934,68 @@ var buildAiHookContext = ({
|
|
|
5934
5934
|
};
|
|
5935
5935
|
};
|
|
5936
5936
|
|
|
5937
|
+
// src/strategy/runtimeDecisionTelemetry.ts
|
|
5938
|
+
var finitePositive = (value) => {
|
|
5939
|
+
const parsed = Number(value);
|
|
5940
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
5941
|
+
};
|
|
5942
|
+
var round = (value) => Number(value.toFixed(12));
|
|
5943
|
+
var assessRuntimeEntryRisk = ({
|
|
5944
|
+
qty,
|
|
5945
|
+
entryPrice,
|
|
5946
|
+
stopLossPrice,
|
|
5947
|
+
maxLossValue
|
|
5948
|
+
}) => {
|
|
5949
|
+
const normalizedQty = finitePositive(qty);
|
|
5950
|
+
const normalizedEntryPrice = finitePositive(entryPrice);
|
|
5951
|
+
const normalizedStopLossPrice = finitePositive(stopLossPrice);
|
|
5952
|
+
const normalizedMaxLossValue = finitePositive(maxLossValue);
|
|
5953
|
+
const plannedLossValue = normalizedQty != null && normalizedEntryPrice != null && normalizedStopLossPrice != null ? round(
|
|
5954
|
+
Math.abs(normalizedEntryPrice - normalizedStopLossPrice) * normalizedQty
|
|
5955
|
+
) : null;
|
|
5956
|
+
if (plannedLossValue == null) {
|
|
5957
|
+
return {
|
|
5958
|
+
stage: "order_plan",
|
|
5959
|
+
status: "unavailable",
|
|
5960
|
+
reason: "ORDER_PLAN_RISK_INPUTS_UNAVAILABLE",
|
|
5961
|
+
plannedLossValue: null,
|
|
5962
|
+
maxLossValue: normalizedMaxLossValue,
|
|
5963
|
+
limitUtilization: null,
|
|
5964
|
+
enforced: false
|
|
5965
|
+
};
|
|
5966
|
+
}
|
|
5967
|
+
if (normalizedMaxLossValue == null) {
|
|
5968
|
+
return {
|
|
5969
|
+
stage: "order_plan",
|
|
5970
|
+
status: "unavailable",
|
|
5971
|
+
reason: "MAX_LOSS_VALUE_UNAVAILABLE",
|
|
5972
|
+
plannedLossValue,
|
|
5973
|
+
maxLossValue: null,
|
|
5974
|
+
limitUtilization: null,
|
|
5975
|
+
enforced: false
|
|
5976
|
+
};
|
|
5977
|
+
}
|
|
5978
|
+
const limitUtilization = round(plannedLossValue / normalizedMaxLossValue);
|
|
5979
|
+
const withinLimit = plannedLossValue <= normalizedMaxLossValue * (1 + 1e-9);
|
|
5980
|
+
return {
|
|
5981
|
+
stage: "order_plan",
|
|
5982
|
+
status: withinLimit ? "approved" : "rejected",
|
|
5983
|
+
reason: withinLimit ? "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE" : "PLANNED_LOSS_EXCEEDS_MAX_LOSS_VALUE",
|
|
5984
|
+
plannedLossValue,
|
|
5985
|
+
maxLossValue: normalizedMaxLossValue,
|
|
5986
|
+
limitUtilization,
|
|
5987
|
+
enforced: false
|
|
5988
|
+
};
|
|
5989
|
+
};
|
|
5990
|
+
var buildRuntimeAdmissionDecision = ({
|
|
5991
|
+
status,
|
|
5992
|
+
reason
|
|
5993
|
+
}) => ({
|
|
5994
|
+
stage: "runtime_admission",
|
|
5995
|
+
status,
|
|
5996
|
+
reason
|
|
5997
|
+
});
|
|
5998
|
+
|
|
5937
5999
|
// src/strategy/runtimeHooks.ts
|
|
5938
6000
|
var normalizeConfigHookList = (value) => {
|
|
5939
6001
|
if (Array.isArray(value)) {
|
|
@@ -7057,6 +7119,12 @@ var createStrategyRuntime = ({
|
|
|
7057
7119
|
if (decisionHookCtx.policyProfileId) {
|
|
7058
7120
|
signal.policyProfileId = decisionHookCtx.policyProfileId;
|
|
7059
7121
|
}
|
|
7122
|
+
signal.riskDecision = assessRuntimeEntryRisk({
|
|
7123
|
+
qty: decision.orderPlan.qty,
|
|
7124
|
+
entryPrice: decision.entryContext.prices.currentPrice,
|
|
7125
|
+
stopLossPrice: decision.orderPlan.stopLossPrice,
|
|
7126
|
+
maxLossValue: runtimeLineage?.maxLossValue ?? config.MAX_LOSS_VALUE
|
|
7127
|
+
});
|
|
7060
7128
|
}
|
|
7061
7129
|
const entry = buildHookEntry({
|
|
7062
7130
|
decision,
|
|
@@ -7166,13 +7234,16 @@ var createStrategyRuntime = ({
|
|
|
7166
7234
|
signal.orderStatus = "skipped";
|
|
7167
7235
|
signal.orderSkipReason = skipReason;
|
|
7168
7236
|
signal.strategyRevision = strategyRevision;
|
|
7237
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
7238
|
+
status: "rejected",
|
|
7239
|
+
reason: skipReason
|
|
7240
|
+
});
|
|
7169
7241
|
}
|
|
7170
7242
|
return signal ?? skipReason;
|
|
7171
7243
|
}
|
|
7172
7244
|
if (!shouldMakeOrder) {
|
|
7173
7245
|
if (signal) {
|
|
7174
|
-
|
|
7175
|
-
signal.orderSkipReason = getEntrySkipReason({
|
|
7246
|
+
const skipReason = getEntrySkipReason({
|
|
7176
7247
|
makeOrdersEnabled,
|
|
7177
7248
|
env,
|
|
7178
7249
|
ml,
|
|
@@ -7180,6 +7251,12 @@ var createStrategyRuntime = ({
|
|
|
7180
7251
|
quality,
|
|
7181
7252
|
minAiQuality
|
|
7182
7253
|
});
|
|
7254
|
+
signal.orderStatus = "skipped";
|
|
7255
|
+
signal.orderSkipReason = skipReason;
|
|
7256
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
7257
|
+
status: "not_applicable",
|
|
7258
|
+
reason: `ENTRY_POLICY_REJECTED:${skipReason}`
|
|
7259
|
+
});
|
|
7183
7260
|
}
|
|
7184
7261
|
return signal ?? decision.code;
|
|
7185
7262
|
}
|
|
@@ -7202,10 +7279,20 @@ var createStrategyRuntime = ({
|
|
|
7202
7279
|
if (signal) {
|
|
7203
7280
|
signal.orderStatus = "skipped";
|
|
7204
7281
|
signal.orderSkipReason = skipReason;
|
|
7282
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
7283
|
+
status: "rejected",
|
|
7284
|
+
reason: skipReason
|
|
7285
|
+
});
|
|
7205
7286
|
}
|
|
7206
7287
|
return signal ?? skipReason;
|
|
7207
7288
|
}
|
|
7208
7289
|
if (backtestEntryDelayBars > 0) {
|
|
7290
|
+
if (signal) {
|
|
7291
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
7292
|
+
status: "approved",
|
|
7293
|
+
reason: "ENTRY_ADMITTED"
|
|
7294
|
+
});
|
|
7295
|
+
}
|
|
7209
7296
|
pendingBacktestEntry = {
|
|
7210
7297
|
delayBars: backtestEntryDelayBars,
|
|
7211
7298
|
delayBarsRemaining: backtestEntryDelayBars,
|
|
@@ -7219,6 +7306,12 @@ var createStrategyRuntime = ({
|
|
|
7219
7306
|
};
|
|
7220
7307
|
return `BACKTEST_ENTRY_DELAY_QUEUED:${backtestEntryDelayBars}`;
|
|
7221
7308
|
}
|
|
7309
|
+
if (signal) {
|
|
7310
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
7311
|
+
status: "approved",
|
|
7312
|
+
reason: "ENTRY_ADMITTED"
|
|
7313
|
+
});
|
|
7314
|
+
}
|
|
7222
7315
|
return executeEntryDecision({
|
|
7223
7316
|
connector,
|
|
7224
7317
|
symbol,
|
|
@@ -4935,6 +4935,68 @@ var buildAiHookContext = ({
|
|
|
4935
4935
|
};
|
|
4936
4936
|
};
|
|
4937
4937
|
|
|
4938
|
+
// src/strategy/runtimeDecisionTelemetry.ts
|
|
4939
|
+
var finitePositive = (value) => {
|
|
4940
|
+
const parsed = Number(value);
|
|
4941
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
4942
|
+
};
|
|
4943
|
+
var round = (value) => Number(value.toFixed(12));
|
|
4944
|
+
var assessRuntimeEntryRisk = ({
|
|
4945
|
+
qty,
|
|
4946
|
+
entryPrice,
|
|
4947
|
+
stopLossPrice,
|
|
4948
|
+
maxLossValue
|
|
4949
|
+
}) => {
|
|
4950
|
+
const normalizedQty = finitePositive(qty);
|
|
4951
|
+
const normalizedEntryPrice = finitePositive(entryPrice);
|
|
4952
|
+
const normalizedStopLossPrice = finitePositive(stopLossPrice);
|
|
4953
|
+
const normalizedMaxLossValue = finitePositive(maxLossValue);
|
|
4954
|
+
const plannedLossValue = normalizedQty != null && normalizedEntryPrice != null && normalizedStopLossPrice != null ? round(
|
|
4955
|
+
Math.abs(normalizedEntryPrice - normalizedStopLossPrice) * normalizedQty
|
|
4956
|
+
) : null;
|
|
4957
|
+
if (plannedLossValue == null) {
|
|
4958
|
+
return {
|
|
4959
|
+
stage: "order_plan",
|
|
4960
|
+
status: "unavailable",
|
|
4961
|
+
reason: "ORDER_PLAN_RISK_INPUTS_UNAVAILABLE",
|
|
4962
|
+
plannedLossValue: null,
|
|
4963
|
+
maxLossValue: normalizedMaxLossValue,
|
|
4964
|
+
limitUtilization: null,
|
|
4965
|
+
enforced: false
|
|
4966
|
+
};
|
|
4967
|
+
}
|
|
4968
|
+
if (normalizedMaxLossValue == null) {
|
|
4969
|
+
return {
|
|
4970
|
+
stage: "order_plan",
|
|
4971
|
+
status: "unavailable",
|
|
4972
|
+
reason: "MAX_LOSS_VALUE_UNAVAILABLE",
|
|
4973
|
+
plannedLossValue,
|
|
4974
|
+
maxLossValue: null,
|
|
4975
|
+
limitUtilization: null,
|
|
4976
|
+
enforced: false
|
|
4977
|
+
};
|
|
4978
|
+
}
|
|
4979
|
+
const limitUtilization = round(plannedLossValue / normalizedMaxLossValue);
|
|
4980
|
+
const withinLimit = plannedLossValue <= normalizedMaxLossValue * (1 + 1e-9);
|
|
4981
|
+
return {
|
|
4982
|
+
stage: "order_plan",
|
|
4983
|
+
status: withinLimit ? "approved" : "rejected",
|
|
4984
|
+
reason: withinLimit ? "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE" : "PLANNED_LOSS_EXCEEDS_MAX_LOSS_VALUE",
|
|
4985
|
+
plannedLossValue,
|
|
4986
|
+
maxLossValue: normalizedMaxLossValue,
|
|
4987
|
+
limitUtilization,
|
|
4988
|
+
enforced: false
|
|
4989
|
+
};
|
|
4990
|
+
};
|
|
4991
|
+
var buildRuntimeAdmissionDecision = ({
|
|
4992
|
+
status,
|
|
4993
|
+
reason
|
|
4994
|
+
}) => ({
|
|
4995
|
+
stage: "runtime_admission",
|
|
4996
|
+
status,
|
|
4997
|
+
reason
|
|
4998
|
+
});
|
|
4999
|
+
|
|
4938
5000
|
// src/strategy/runtimeHooks.ts
|
|
4939
5001
|
var normalizeConfigHookList = (value) => {
|
|
4940
5002
|
if (Array.isArray(value)) {
|
|
@@ -6058,6 +6120,12 @@ var createStrategyRuntime = ({
|
|
|
6058
6120
|
if (decisionHookCtx.policyProfileId) {
|
|
6059
6121
|
signal.policyProfileId = decisionHookCtx.policyProfileId;
|
|
6060
6122
|
}
|
|
6123
|
+
signal.riskDecision = assessRuntimeEntryRisk({
|
|
6124
|
+
qty: decision.orderPlan.qty,
|
|
6125
|
+
entryPrice: decision.entryContext.prices.currentPrice,
|
|
6126
|
+
stopLossPrice: decision.orderPlan.stopLossPrice,
|
|
6127
|
+
maxLossValue: runtimeLineage?.maxLossValue ?? config.MAX_LOSS_VALUE
|
|
6128
|
+
});
|
|
6061
6129
|
}
|
|
6062
6130
|
const entry = buildHookEntry({
|
|
6063
6131
|
decision,
|
|
@@ -6167,13 +6235,16 @@ var createStrategyRuntime = ({
|
|
|
6167
6235
|
signal.orderStatus = "skipped";
|
|
6168
6236
|
signal.orderSkipReason = skipReason;
|
|
6169
6237
|
signal.strategyRevision = strategyRevision;
|
|
6238
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6239
|
+
status: "rejected",
|
|
6240
|
+
reason: skipReason
|
|
6241
|
+
});
|
|
6170
6242
|
}
|
|
6171
6243
|
return signal ?? skipReason;
|
|
6172
6244
|
}
|
|
6173
6245
|
if (!shouldMakeOrder) {
|
|
6174
6246
|
if (signal) {
|
|
6175
|
-
|
|
6176
|
-
signal.orderSkipReason = getEntrySkipReason({
|
|
6247
|
+
const skipReason = getEntrySkipReason({
|
|
6177
6248
|
makeOrdersEnabled,
|
|
6178
6249
|
env,
|
|
6179
6250
|
ml,
|
|
@@ -6181,6 +6252,12 @@ var createStrategyRuntime = ({
|
|
|
6181
6252
|
quality,
|
|
6182
6253
|
minAiQuality
|
|
6183
6254
|
});
|
|
6255
|
+
signal.orderStatus = "skipped";
|
|
6256
|
+
signal.orderSkipReason = skipReason;
|
|
6257
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6258
|
+
status: "not_applicable",
|
|
6259
|
+
reason: `ENTRY_POLICY_REJECTED:${skipReason}`
|
|
6260
|
+
});
|
|
6184
6261
|
}
|
|
6185
6262
|
return signal ?? decision.code;
|
|
6186
6263
|
}
|
|
@@ -6203,10 +6280,20 @@ var createStrategyRuntime = ({
|
|
|
6203
6280
|
if (signal) {
|
|
6204
6281
|
signal.orderStatus = "skipped";
|
|
6205
6282
|
signal.orderSkipReason = skipReason;
|
|
6283
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6284
|
+
status: "rejected",
|
|
6285
|
+
reason: skipReason
|
|
6286
|
+
});
|
|
6206
6287
|
}
|
|
6207
6288
|
return signal ?? skipReason;
|
|
6208
6289
|
}
|
|
6209
6290
|
if (backtestEntryDelayBars > 0) {
|
|
6291
|
+
if (signal) {
|
|
6292
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6293
|
+
status: "approved",
|
|
6294
|
+
reason: "ENTRY_ADMITTED"
|
|
6295
|
+
});
|
|
6296
|
+
}
|
|
6210
6297
|
pendingBacktestEntry = {
|
|
6211
6298
|
delayBars: backtestEntryDelayBars,
|
|
6212
6299
|
delayBarsRemaining: backtestEntryDelayBars,
|
|
@@ -6220,6 +6307,12 @@ var createStrategyRuntime = ({
|
|
|
6220
6307
|
};
|
|
6221
6308
|
return `BACKTEST_ENTRY_DELAY_QUEUED:${backtestEntryDelayBars}`;
|
|
6222
6309
|
}
|
|
6310
|
+
if (signal) {
|
|
6311
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6312
|
+
status: "approved",
|
|
6313
|
+
reason: "ENTRY_ADMITTED"
|
|
6314
|
+
});
|
|
6315
|
+
}
|
|
6223
6316
|
return executeEntryDecision({
|
|
6224
6317
|
connector,
|
|
6225
6318
|
symbol,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
resolveRuntimeComposition,
|
|
10
10
|
verifyRuntimeDeclaration
|
|
11
11
|
} from "./chunk-NQO2MFP6.mjs";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-XHNJ757K.mjs";
|
|
13
13
|
import "./chunk-IKRSNRP6.mjs";
|
|
14
14
|
import "./chunk-LZDXRXIU.mjs";
|
|
15
15
|
import "./chunk-Y6FXYEAI.mjs";
|
package/dist/strategies.js
CHANGED
|
@@ -5051,6 +5051,68 @@ var buildAiHookContext = ({
|
|
|
5051
5051
|
};
|
|
5052
5052
|
};
|
|
5053
5053
|
|
|
5054
|
+
// src/strategy/runtimeDecisionTelemetry.ts
|
|
5055
|
+
var finitePositive = (value) => {
|
|
5056
|
+
const parsed = Number(value);
|
|
5057
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
5058
|
+
};
|
|
5059
|
+
var round = (value) => Number(value.toFixed(12));
|
|
5060
|
+
var assessRuntimeEntryRisk = ({
|
|
5061
|
+
qty,
|
|
5062
|
+
entryPrice,
|
|
5063
|
+
stopLossPrice,
|
|
5064
|
+
maxLossValue
|
|
5065
|
+
}) => {
|
|
5066
|
+
const normalizedQty = finitePositive(qty);
|
|
5067
|
+
const normalizedEntryPrice = finitePositive(entryPrice);
|
|
5068
|
+
const normalizedStopLossPrice = finitePositive(stopLossPrice);
|
|
5069
|
+
const normalizedMaxLossValue = finitePositive(maxLossValue);
|
|
5070
|
+
const plannedLossValue = normalizedQty != null && normalizedEntryPrice != null && normalizedStopLossPrice != null ? round(
|
|
5071
|
+
Math.abs(normalizedEntryPrice - normalizedStopLossPrice) * normalizedQty
|
|
5072
|
+
) : null;
|
|
5073
|
+
if (plannedLossValue == null) {
|
|
5074
|
+
return {
|
|
5075
|
+
stage: "order_plan",
|
|
5076
|
+
status: "unavailable",
|
|
5077
|
+
reason: "ORDER_PLAN_RISK_INPUTS_UNAVAILABLE",
|
|
5078
|
+
plannedLossValue: null,
|
|
5079
|
+
maxLossValue: normalizedMaxLossValue,
|
|
5080
|
+
limitUtilization: null,
|
|
5081
|
+
enforced: false
|
|
5082
|
+
};
|
|
5083
|
+
}
|
|
5084
|
+
if (normalizedMaxLossValue == null) {
|
|
5085
|
+
return {
|
|
5086
|
+
stage: "order_plan",
|
|
5087
|
+
status: "unavailable",
|
|
5088
|
+
reason: "MAX_LOSS_VALUE_UNAVAILABLE",
|
|
5089
|
+
plannedLossValue,
|
|
5090
|
+
maxLossValue: null,
|
|
5091
|
+
limitUtilization: null,
|
|
5092
|
+
enforced: false
|
|
5093
|
+
};
|
|
5094
|
+
}
|
|
5095
|
+
const limitUtilization = round(plannedLossValue / normalizedMaxLossValue);
|
|
5096
|
+
const withinLimit = plannedLossValue <= normalizedMaxLossValue * (1 + 1e-9);
|
|
5097
|
+
return {
|
|
5098
|
+
stage: "order_plan",
|
|
5099
|
+
status: withinLimit ? "approved" : "rejected",
|
|
5100
|
+
reason: withinLimit ? "PLANNED_LOSS_WITHIN_MAX_LOSS_VALUE" : "PLANNED_LOSS_EXCEEDS_MAX_LOSS_VALUE",
|
|
5101
|
+
plannedLossValue,
|
|
5102
|
+
maxLossValue: normalizedMaxLossValue,
|
|
5103
|
+
limitUtilization,
|
|
5104
|
+
enforced: false
|
|
5105
|
+
};
|
|
5106
|
+
};
|
|
5107
|
+
var buildRuntimeAdmissionDecision = ({
|
|
5108
|
+
status,
|
|
5109
|
+
reason
|
|
5110
|
+
}) => ({
|
|
5111
|
+
stage: "runtime_admission",
|
|
5112
|
+
status,
|
|
5113
|
+
reason
|
|
5114
|
+
});
|
|
5115
|
+
|
|
5054
5116
|
// src/strategy/runtimeHooks.ts
|
|
5055
5117
|
var normalizeConfigHookList = (value) => {
|
|
5056
5118
|
if (Array.isArray(value)) {
|
|
@@ -6174,6 +6236,12 @@ var createStrategyRuntime = ({
|
|
|
6174
6236
|
if (decisionHookCtx.policyProfileId) {
|
|
6175
6237
|
signal.policyProfileId = decisionHookCtx.policyProfileId;
|
|
6176
6238
|
}
|
|
6239
|
+
signal.riskDecision = assessRuntimeEntryRisk({
|
|
6240
|
+
qty: decision.orderPlan.qty,
|
|
6241
|
+
entryPrice: decision.entryContext.prices.currentPrice,
|
|
6242
|
+
stopLossPrice: decision.orderPlan.stopLossPrice,
|
|
6243
|
+
maxLossValue: runtimeLineage?.maxLossValue ?? config.MAX_LOSS_VALUE
|
|
6244
|
+
});
|
|
6177
6245
|
}
|
|
6178
6246
|
const entry = buildHookEntry({
|
|
6179
6247
|
decision,
|
|
@@ -6283,13 +6351,16 @@ var createStrategyRuntime = ({
|
|
|
6283
6351
|
signal.orderStatus = "skipped";
|
|
6284
6352
|
signal.orderSkipReason = skipReason;
|
|
6285
6353
|
signal.strategyRevision = strategyRevision;
|
|
6354
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6355
|
+
status: "rejected",
|
|
6356
|
+
reason: skipReason
|
|
6357
|
+
});
|
|
6286
6358
|
}
|
|
6287
6359
|
return signal ?? skipReason;
|
|
6288
6360
|
}
|
|
6289
6361
|
if (!shouldMakeOrder) {
|
|
6290
6362
|
if (signal) {
|
|
6291
|
-
|
|
6292
|
-
signal.orderSkipReason = getEntrySkipReason({
|
|
6363
|
+
const skipReason = getEntrySkipReason({
|
|
6293
6364
|
makeOrdersEnabled,
|
|
6294
6365
|
env,
|
|
6295
6366
|
ml,
|
|
@@ -6297,6 +6368,12 @@ var createStrategyRuntime = ({
|
|
|
6297
6368
|
quality,
|
|
6298
6369
|
minAiQuality
|
|
6299
6370
|
});
|
|
6371
|
+
signal.orderStatus = "skipped";
|
|
6372
|
+
signal.orderSkipReason = skipReason;
|
|
6373
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6374
|
+
status: "not_applicable",
|
|
6375
|
+
reason: `ENTRY_POLICY_REJECTED:${skipReason}`
|
|
6376
|
+
});
|
|
6300
6377
|
}
|
|
6301
6378
|
return signal ?? decision.code;
|
|
6302
6379
|
}
|
|
@@ -6319,10 +6396,20 @@ var createStrategyRuntime = ({
|
|
|
6319
6396
|
if (signal) {
|
|
6320
6397
|
signal.orderStatus = "skipped";
|
|
6321
6398
|
signal.orderSkipReason = skipReason;
|
|
6399
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6400
|
+
status: "rejected",
|
|
6401
|
+
reason: skipReason
|
|
6402
|
+
});
|
|
6322
6403
|
}
|
|
6323
6404
|
return signal ?? skipReason;
|
|
6324
6405
|
}
|
|
6325
6406
|
if (backtestEntryDelayBars > 0) {
|
|
6407
|
+
if (signal) {
|
|
6408
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6409
|
+
status: "approved",
|
|
6410
|
+
reason: "ENTRY_ADMITTED"
|
|
6411
|
+
});
|
|
6412
|
+
}
|
|
6326
6413
|
pendingBacktestEntry = {
|
|
6327
6414
|
delayBars: backtestEntryDelayBars,
|
|
6328
6415
|
delayBarsRemaining: backtestEntryDelayBars,
|
|
@@ -6336,6 +6423,12 @@ var createStrategyRuntime = ({
|
|
|
6336
6423
|
};
|
|
6337
6424
|
return `BACKTEST_ENTRY_DELAY_QUEUED:${backtestEntryDelayBars}`;
|
|
6338
6425
|
}
|
|
6426
|
+
if (signal) {
|
|
6427
|
+
signal.allocatorDecision = buildRuntimeAdmissionDecision({
|
|
6428
|
+
status: "approved",
|
|
6429
|
+
reason: "ENTRY_ADMITTED"
|
|
6430
|
+
});
|
|
6431
|
+
}
|
|
6339
6432
|
return executeEntryDecision({
|
|
6340
6433
|
connector,
|
|
6341
6434
|
symbol,
|
package/dist/strategies.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/node",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.27-beta.245",
|
|
4
4
|
"description": "Node-only runtime for the TradeJS TypeScript framework: strategies, backtests, Pine strategy loading, and plugin registries.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -89,9 +89,9 @@
|
|
|
89
89
|
"dependencies": {
|
|
90
90
|
"@langchain/core": "^1.2.3",
|
|
91
91
|
"@langchain/openai": "^1.5.5",
|
|
92
|
-
"@tradejs/core": "^3.1.
|
|
93
|
-
"@tradejs/infra": "^3.1.
|
|
94
|
-
"@tradejs/types": "^3.1.
|
|
92
|
+
"@tradejs/core": "^3.1.27-beta.245",
|
|
93
|
+
"@tradejs/infra": "^3.1.27-beta.245",
|
|
94
|
+
"@tradejs/types": "^3.1.27-beta.245",
|
|
95
95
|
"@types/node": "^24",
|
|
96
96
|
"chalk": "4.1.2",
|
|
97
97
|
"ioredis": "5.11.1",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"typescript": "^5.9"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
|
-
"@tradejs/indicators": "^3.1.
|
|
107
|
+
"@tradejs/indicators": "^3.1.27-beta.245",
|
|
108
108
|
"@tradejs/strategy-adaptive-momentum-ribbon": "3.0.2",
|
|
109
109
|
"@tradejs/strategy-hyperliquid-consensus": "3.0.2",
|
|
110
110
|
"@tradejs/strategy-kit": "3.0.4",
|