@tradejs/node 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ai-NNJ3RLLL.mjs → ai-G7ATN4YL.mjs} +3 -3
- package/dist/backtest.d.mts +1 -1
- package/dist/backtest.d.ts +1 -1
- package/dist/backtest.js +253 -137
- package/dist/backtest.mjs +52 -25
- package/dist/{chunk-OB4CSYDJ.mjs → chunk-7ICOZAKA.mjs} +0 -4
- package/dist/chunk-CIY64D57.mjs +271 -0
- package/dist/{chunk-ZIMX3JX2.mjs → chunk-LMAKIC3C.mjs} +1 -1
- package/dist/{chunk-DE7ADBIR.mjs → chunk-P2ZUWONT.mjs} +30 -2
- package/dist/{chunk-PXJJPAQT.mjs → chunk-RBE4PZER.mjs} +1 -1
- package/dist/chunk-ZY6ULOWK.mjs +246 -0
- package/dist/cli.js +140 -102
- package/dist/cli.mjs +26 -18
- package/dist/connectors.d.mts +9 -9
- package/dist/connectors.d.ts +9 -9
- package/dist/connectors.js +144 -74
- package/dist/connectors.mjs +2 -2
- package/dist/pine.d.mts +0 -1
- package/dist/pine.d.ts +0 -1
- package/dist/pine.js +0 -4
- package/dist/pine.mjs +1 -1
- package/dist/registry.d.mts +10 -10
- package/dist/registry.d.ts +10 -10
- package/dist/registry.js +156 -85
- package/dist/registry.mjs +2 -2
- package/dist/strategies.js +452 -166
- package/dist/strategies.mjs +300 -85
- package/package.json +6 -5
- package/dist/chunk-E2QNOA5M.mjs +0 -227
- package/dist/chunk-MHCXPD2B.mjs +0 -201
package/dist/strategies.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildMlPayload
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RBE4PZER.mjs";
|
|
4
4
|
import {
|
|
5
5
|
require_lodash
|
|
6
6
|
} from "./chunk-GKDBAF3A.mjs";
|
|
7
7
|
import {
|
|
8
8
|
createLoadPineScript
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-7ICOZAKA.mjs";
|
|
10
10
|
import "./chunk-5YNMSWL3.mjs";
|
|
11
11
|
import {
|
|
12
12
|
MAX_AI_SERIES_POINTS,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
buildAiPayload,
|
|
16
16
|
buildAiSystemPrompt,
|
|
17
17
|
trimSeriesDeep
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-LMAKIC3C.mjs";
|
|
19
19
|
import {
|
|
20
20
|
ensureIndicatorPluginsLoaded,
|
|
21
21
|
ensureStrategyPluginsLoaded,
|
|
@@ -28,8 +28,10 @@ import {
|
|
|
28
28
|
registerStrategyEntries,
|
|
29
29
|
resetStrategyRegistryCache,
|
|
30
30
|
strategies
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import
|
|
31
|
+
} from "./chunk-ZY6ULOWK.mjs";
|
|
32
|
+
import {
|
|
33
|
+
getTradejsProjectCwd
|
|
34
|
+
} from "./chunk-P2ZUWONT.mjs";
|
|
33
35
|
import {
|
|
34
36
|
__toESM
|
|
35
37
|
} from "./chunk-6DZX6EAA.mjs";
|
|
@@ -185,7 +187,8 @@ var enrichSignalWithMl = async ({
|
|
|
185
187
|
const mlResult = await fetchMlThreshold({
|
|
186
188
|
strategy,
|
|
187
189
|
features,
|
|
188
|
-
threshold: ml.mlThreshold
|
|
190
|
+
threshold: ml.mlThreshold,
|
|
191
|
+
projectRoot: getTradejsProjectCwd()
|
|
189
192
|
});
|
|
190
193
|
if (mlResult) {
|
|
191
194
|
signal.ml = mlResult;
|
|
@@ -203,7 +206,7 @@ var enrichSignalWithAi = async ({
|
|
|
203
206
|
return void 0;
|
|
204
207
|
}
|
|
205
208
|
try {
|
|
206
|
-
const { askAI: askAI2 } = await import("./ai-
|
|
209
|
+
const { askAI: askAI2 } = await import("./ai-G7ATN4YL.mjs");
|
|
207
210
|
const analysis = await askAI2(signal);
|
|
208
211
|
if (typeof analysis?.quality === "number") {
|
|
209
212
|
const normalizedQuality = Math.round(analysis.quality);
|
|
@@ -350,10 +353,151 @@ var getEntrySkipReason = ({
|
|
|
350
353
|
}
|
|
351
354
|
return "ENTRY_POLICY_BLOCKED";
|
|
352
355
|
};
|
|
356
|
+
var buildHookCtx = ({
|
|
357
|
+
connector,
|
|
358
|
+
strategyName,
|
|
359
|
+
userName,
|
|
360
|
+
symbol,
|
|
361
|
+
strategyConfig,
|
|
362
|
+
env,
|
|
363
|
+
isConfigFromBacktest
|
|
364
|
+
}) => ({
|
|
365
|
+
connector,
|
|
366
|
+
strategyName,
|
|
367
|
+
userName,
|
|
368
|
+
symbol,
|
|
369
|
+
strategyConfig,
|
|
370
|
+
env,
|
|
371
|
+
isConfigFromBacktest
|
|
372
|
+
});
|
|
373
|
+
var buildHookEntry = ({
|
|
374
|
+
decision,
|
|
375
|
+
runtime
|
|
376
|
+
}) => ({
|
|
377
|
+
context: decision.entryContext,
|
|
378
|
+
orderPlan: decision.orderPlan,
|
|
379
|
+
signal: decision.signal,
|
|
380
|
+
runtime: {
|
|
381
|
+
raw: decision.runtime,
|
|
382
|
+
resolved: runtime
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
var buildHookPolicy = ({
|
|
386
|
+
quality,
|
|
387
|
+
makeOrdersEnabled,
|
|
388
|
+
minAiQuality
|
|
389
|
+
}) => ({
|
|
390
|
+
aiQuality: quality,
|
|
391
|
+
makeOrdersEnabled,
|
|
392
|
+
minAiQuality
|
|
393
|
+
});
|
|
394
|
+
var buildMlHookContext = ({
|
|
395
|
+
signal,
|
|
396
|
+
env,
|
|
397
|
+
ml
|
|
398
|
+
}) => {
|
|
399
|
+
if (env === "BACKTEST") {
|
|
400
|
+
return {
|
|
401
|
+
config: ml,
|
|
402
|
+
attempted: false,
|
|
403
|
+
applied: false,
|
|
404
|
+
skippedReason: "BACKTEST"
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
if (!ml) {
|
|
408
|
+
return {
|
|
409
|
+
attempted: false,
|
|
410
|
+
applied: false,
|
|
411
|
+
skippedReason: "NO_RUNTIME"
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
if (ml.enabled === false) {
|
|
415
|
+
return {
|
|
416
|
+
config: ml,
|
|
417
|
+
attempted: false,
|
|
418
|
+
applied: false,
|
|
419
|
+
skippedReason: "DISABLED"
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
if (!ml.strategyConfig) {
|
|
423
|
+
return {
|
|
424
|
+
config: ml,
|
|
425
|
+
attempted: false,
|
|
426
|
+
applied: false,
|
|
427
|
+
skippedReason: "NO_STRATEGY_CONFIG"
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
if (typeof ml.mlThreshold !== "number") {
|
|
431
|
+
return {
|
|
432
|
+
config: ml,
|
|
433
|
+
attempted: false,
|
|
434
|
+
applied: false,
|
|
435
|
+
skippedReason: "NO_THRESHOLD"
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
if (signal.ml) {
|
|
439
|
+
return {
|
|
440
|
+
config: ml,
|
|
441
|
+
attempted: true,
|
|
442
|
+
applied: true,
|
|
443
|
+
result: signal.ml
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
config: ml,
|
|
448
|
+
attempted: true,
|
|
449
|
+
applied: false,
|
|
450
|
+
skippedReason: "NO_RESULT"
|
|
451
|
+
};
|
|
452
|
+
};
|
|
453
|
+
var buildAiHookContext = ({
|
|
454
|
+
env,
|
|
455
|
+
ai,
|
|
456
|
+
quality
|
|
457
|
+
}) => {
|
|
458
|
+
if (env === "BACKTEST") {
|
|
459
|
+
return {
|
|
460
|
+
config: ai,
|
|
461
|
+
attempted: false,
|
|
462
|
+
applied: false,
|
|
463
|
+
skippedReason: "BACKTEST"
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
if (!ai) {
|
|
467
|
+
return {
|
|
468
|
+
attempted: false,
|
|
469
|
+
applied: false,
|
|
470
|
+
skippedReason: "NO_RUNTIME"
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
if (ai.enabled === false) {
|
|
474
|
+
return {
|
|
475
|
+
config: ai,
|
|
476
|
+
attempted: false,
|
|
477
|
+
applied: false,
|
|
478
|
+
skippedReason: "DISABLED"
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
if (typeof quality === "number") {
|
|
482
|
+
return {
|
|
483
|
+
config: ai,
|
|
484
|
+
attempted: true,
|
|
485
|
+
applied: true,
|
|
486
|
+
quality
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
return {
|
|
490
|
+
config: ai,
|
|
491
|
+
attempted: true,
|
|
492
|
+
applied: false,
|
|
493
|
+
skippedReason: "NO_QUALITY"
|
|
494
|
+
};
|
|
495
|
+
};
|
|
353
496
|
var handleExitDecision = async ({
|
|
354
497
|
connector,
|
|
355
498
|
symbol,
|
|
356
499
|
decision,
|
|
500
|
+
market,
|
|
357
501
|
onRuntimeError
|
|
358
502
|
}) => {
|
|
359
503
|
try {
|
|
@@ -367,7 +511,8 @@ var handleExitDecision = async ({
|
|
|
367
511
|
await onRuntimeError?.({
|
|
368
512
|
stage: "closePosition",
|
|
369
513
|
error: err,
|
|
370
|
-
decision
|
|
514
|
+
decision,
|
|
515
|
+
market
|
|
371
516
|
});
|
|
372
517
|
logger3.error("close order error: %s %s", symbol, err);
|
|
373
518
|
return "ORDER_ERROR";
|
|
@@ -380,7 +525,12 @@ var executeEntryDecision = async ({
|
|
|
380
525
|
decision,
|
|
381
526
|
runtime,
|
|
382
527
|
manifest,
|
|
383
|
-
|
|
528
|
+
hookCtx,
|
|
529
|
+
market,
|
|
530
|
+
entry,
|
|
531
|
+
policy,
|
|
532
|
+
ml,
|
|
533
|
+
ai,
|
|
384
534
|
invokeHook,
|
|
385
535
|
notifyRuntimeError
|
|
386
536
|
}) => {
|
|
@@ -390,13 +540,15 @@ var executeEntryDecision = async ({
|
|
|
390
540
|
"beforePlaceOrder",
|
|
391
541
|
manifest?.hooks?.beforePlaceOrder,
|
|
392
542
|
{
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
runtime,
|
|
543
|
+
ctx: hookCtx,
|
|
544
|
+
market,
|
|
396
545
|
decision,
|
|
397
|
-
|
|
546
|
+
entry,
|
|
547
|
+
policy,
|
|
548
|
+
ml,
|
|
549
|
+
ai
|
|
398
550
|
},
|
|
399
|
-
{ decision,
|
|
551
|
+
{ decision, entry, market }
|
|
400
552
|
);
|
|
401
553
|
try {
|
|
402
554
|
await runtime.beforePlaceOrder?.();
|
|
@@ -405,7 +557,8 @@ var executeEntryDecision = async ({
|
|
|
405
557
|
stage: "runtime.beforePlaceOrder",
|
|
406
558
|
error,
|
|
407
559
|
decision,
|
|
408
|
-
|
|
560
|
+
entry,
|
|
561
|
+
market
|
|
409
562
|
});
|
|
410
563
|
throw error;
|
|
411
564
|
}
|
|
@@ -428,13 +581,18 @@ var executeEntryDecision = async ({
|
|
|
428
581
|
"afterPlaceOrder",
|
|
429
582
|
manifest?.hooks?.afterPlaceOrder,
|
|
430
583
|
{
|
|
431
|
-
|
|
584
|
+
ctx: hookCtx,
|
|
585
|
+
market,
|
|
432
586
|
decision,
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
587
|
+
entry,
|
|
588
|
+
policy,
|
|
589
|
+
ml,
|
|
590
|
+
ai,
|
|
591
|
+
order: {
|
|
592
|
+
result: signal
|
|
593
|
+
}
|
|
436
594
|
},
|
|
437
|
-
{ decision,
|
|
595
|
+
{ decision, entry, market }
|
|
438
596
|
);
|
|
439
597
|
return signal;
|
|
440
598
|
}
|
|
@@ -454,13 +612,18 @@ var executeEntryDecision = async ({
|
|
|
454
612
|
"afterPlaceOrder",
|
|
455
613
|
manifest?.hooks?.afterPlaceOrder,
|
|
456
614
|
{
|
|
457
|
-
|
|
615
|
+
ctx: hookCtx,
|
|
616
|
+
market,
|
|
458
617
|
decision,
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
618
|
+
entry,
|
|
619
|
+
policy,
|
|
620
|
+
ml,
|
|
621
|
+
ai,
|
|
622
|
+
order: {
|
|
623
|
+
result: decision.code
|
|
624
|
+
}
|
|
462
625
|
},
|
|
463
|
-
{ decision,
|
|
626
|
+
{ decision, entry, market }
|
|
464
627
|
);
|
|
465
628
|
} catch (err) {
|
|
466
629
|
if (signal) {
|
|
@@ -470,7 +633,8 @@ var executeEntryDecision = async ({
|
|
|
470
633
|
stage: "placeOrder",
|
|
471
634
|
error: err,
|
|
472
635
|
decision,
|
|
473
|
-
|
|
636
|
+
entry,
|
|
637
|
+
market
|
|
474
638
|
});
|
|
475
639
|
logger3.error("order error: %s %s", symbol, err);
|
|
476
640
|
return signal ?? "ORDER_ERROR";
|
|
@@ -484,6 +648,7 @@ var createStrategyRuntime = ({
|
|
|
484
648
|
manifest: staticManifest,
|
|
485
649
|
strategyDirectory
|
|
486
650
|
}) => {
|
|
651
|
+
const projectRoot = getTradejsProjectCwd();
|
|
487
652
|
const resolveManifest = (name) => {
|
|
488
653
|
if (!name) {
|
|
489
654
|
return void 0;
|
|
@@ -491,11 +656,11 @@ var createStrategyRuntime = ({
|
|
|
491
656
|
if (staticManifest?.name === name) {
|
|
492
657
|
return staticManifest;
|
|
493
658
|
}
|
|
494
|
-
return getStrategyManifest(name);
|
|
659
|
+
return getStrategyManifest(name, projectRoot);
|
|
495
660
|
};
|
|
496
661
|
const loadPineScript = createLoadPineScript(
|
|
497
662
|
strategyDirectory ? path.resolve(strategyDirectory) : path.resolve(
|
|
498
|
-
|
|
663
|
+
projectRoot,
|
|
499
664
|
"packages",
|
|
500
665
|
"strategies",
|
|
501
666
|
"src",
|
|
@@ -526,33 +691,37 @@ var createStrategyRuntime = ({
|
|
|
526
691
|
strategyName,
|
|
527
692
|
userName,
|
|
528
693
|
symbol,
|
|
529
|
-
config,
|
|
694
|
+
strategyConfig: config,
|
|
530
695
|
env,
|
|
531
696
|
isConfigFromBacktest
|
|
532
697
|
};
|
|
698
|
+
const getHookCtx = (name = strategyName) => buildHookCtx({
|
|
699
|
+
...hookBase,
|
|
700
|
+
strategyName: name
|
|
701
|
+
});
|
|
533
702
|
const notifyRuntimeError = async ({
|
|
534
703
|
stage,
|
|
535
704
|
error,
|
|
536
705
|
decision,
|
|
537
|
-
|
|
706
|
+
entry,
|
|
707
|
+
market
|
|
538
708
|
}) => {
|
|
539
709
|
const errorStrategyName = decision?.kind === "entry" ? decision.entryContext.strategy : strategyName;
|
|
540
710
|
const errorManifest = resolveManifest(errorStrategyName) ?? strategyManifest;
|
|
541
|
-
const errorHookBase = {
|
|
542
|
-
...hookBase,
|
|
543
|
-
strategyName: errorStrategyName
|
|
544
|
-
};
|
|
545
711
|
const onRuntimeError = errorManifest?.hooks?.onRuntimeError;
|
|
546
712
|
if (!onRuntimeError) {
|
|
547
713
|
return;
|
|
548
714
|
}
|
|
549
715
|
try {
|
|
550
716
|
await onRuntimeError({
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
error,
|
|
717
|
+
ctx: getHookCtx(errorStrategyName),
|
|
718
|
+
market,
|
|
554
719
|
decision,
|
|
555
|
-
|
|
720
|
+
entry,
|
|
721
|
+
error: {
|
|
722
|
+
stage,
|
|
723
|
+
cause: error
|
|
724
|
+
}
|
|
556
725
|
});
|
|
557
726
|
} catch (hookError) {
|
|
558
727
|
logger3.error(
|
|
@@ -579,7 +748,8 @@ var createStrategyRuntime = ({
|
|
|
579
748
|
stage,
|
|
580
749
|
error,
|
|
581
750
|
decision: errorContext.decision,
|
|
582
|
-
|
|
751
|
+
entry: errorContext.entry,
|
|
752
|
+
market: errorContext.market
|
|
583
753
|
});
|
|
584
754
|
return void 0;
|
|
585
755
|
}
|
|
@@ -590,7 +760,8 @@ var createStrategyRuntime = ({
|
|
|
590
760
|
btcData,
|
|
591
761
|
btcBinanceData,
|
|
592
762
|
btcCoinbaseData,
|
|
593
|
-
periods: buildDefaultIndicatorPeriods(config)
|
|
763
|
+
periods: buildDefaultIndicatorPeriods(config),
|
|
764
|
+
pluginRegistryScope: projectRoot
|
|
594
765
|
});
|
|
595
766
|
const strategyApi = createStrategyAPI({
|
|
596
767
|
strategy: strategyName,
|
|
@@ -617,39 +788,45 @@ var createStrategyRuntime = ({
|
|
|
617
788
|
indicatorsState
|
|
618
789
|
});
|
|
619
790
|
await invokeHook("onInit", strategyManifest?.hooks?.onInit, {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
791
|
+
ctx: getHookCtx(),
|
|
792
|
+
market: {
|
|
793
|
+
data,
|
|
794
|
+
btcData
|
|
795
|
+
}
|
|
623
796
|
});
|
|
624
797
|
return async (candle, btcCandle) => {
|
|
625
798
|
data.push(candle);
|
|
626
799
|
btcData.push(btcCandle);
|
|
627
800
|
indicatorsState.setCurrentBar(candle, btcCandle);
|
|
801
|
+
const market = {
|
|
802
|
+
candle,
|
|
803
|
+
btcCandle
|
|
804
|
+
};
|
|
628
805
|
const decision = await core(candle, btcCandle);
|
|
629
806
|
const decisionStrategyName = decision.kind === "entry" ? decision.entryContext.strategy : strategyName;
|
|
630
807
|
const decisionManifest = resolveManifest(decisionStrategyName) ?? strategyManifest;
|
|
631
|
-
const
|
|
632
|
-
...hookBase,
|
|
633
|
-
strategyName: decisionStrategyName
|
|
634
|
-
};
|
|
808
|
+
const decisionHookCtx = getHookCtx(decisionStrategyName);
|
|
635
809
|
await invokeHook(
|
|
636
810
|
"afterCoreDecision",
|
|
637
811
|
decisionManifest?.hooks?.afterCoreDecision,
|
|
638
812
|
{
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
btcCandle
|
|
813
|
+
ctx: decisionHookCtx,
|
|
814
|
+
market,
|
|
815
|
+
decision
|
|
643
816
|
},
|
|
644
|
-
{ decision }
|
|
817
|
+
{ decision, market }
|
|
645
818
|
);
|
|
646
819
|
if (decision.kind === "skip") {
|
|
647
|
-
await invokeHook(
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
820
|
+
await invokeHook(
|
|
821
|
+
"onSkip",
|
|
822
|
+
decisionManifest?.hooks?.onSkip,
|
|
823
|
+
{
|
|
824
|
+
ctx: decisionHookCtx,
|
|
825
|
+
market,
|
|
826
|
+
decision
|
|
827
|
+
},
|
|
828
|
+
{ decision, market }
|
|
829
|
+
);
|
|
653
830
|
return decision.code;
|
|
654
831
|
}
|
|
655
832
|
const makeOrdersEnabled = typeof config.MAKE_ORDERS === "boolean" ? config.MAKE_ORDERS : true;
|
|
@@ -661,10 +838,11 @@ var createStrategyRuntime = ({
|
|
|
661
838
|
"beforeClosePosition",
|
|
662
839
|
decisionManifest?.hooks?.beforeClosePosition,
|
|
663
840
|
{
|
|
664
|
-
|
|
841
|
+
ctx: decisionHookCtx,
|
|
842
|
+
market,
|
|
665
843
|
decision
|
|
666
844
|
},
|
|
667
|
-
{ decision }
|
|
845
|
+
{ decision, market }
|
|
668
846
|
);
|
|
669
847
|
if (closeGate?.allow === false) {
|
|
670
848
|
return closeGate.reason ? `CLOSE_BLOCKED_BY_HOOK:${closeGate.reason}` : "CLOSE_BLOCKED_BY_HOOK";
|
|
@@ -673,11 +851,18 @@ var createStrategyRuntime = ({
|
|
|
673
851
|
connector,
|
|
674
852
|
symbol,
|
|
675
853
|
decision,
|
|
676
|
-
|
|
854
|
+
market,
|
|
855
|
+
onRuntimeError: async ({
|
|
856
|
+
stage,
|
|
857
|
+
error,
|
|
858
|
+
decision: exitDecision,
|
|
859
|
+
market: errorMarket
|
|
860
|
+
}) => {
|
|
677
861
|
await notifyRuntimeError({
|
|
678
862
|
stage,
|
|
679
863
|
error,
|
|
680
|
-
decision: exitDecision
|
|
864
|
+
decision: exitDecision,
|
|
865
|
+
market: errorMarket
|
|
681
866
|
});
|
|
682
867
|
}
|
|
683
868
|
});
|
|
@@ -688,6 +873,11 @@ var createStrategyRuntime = ({
|
|
|
688
873
|
manifest: decisionManifest
|
|
689
874
|
});
|
|
690
875
|
const signal = decision.signal;
|
|
876
|
+
const entry = buildHookEntry({
|
|
877
|
+
decision,
|
|
878
|
+
runtime
|
|
879
|
+
});
|
|
880
|
+
let ml;
|
|
691
881
|
if (signal) {
|
|
692
882
|
try {
|
|
693
883
|
await enrichSignalWithMl({
|
|
@@ -700,23 +890,31 @@ var createStrategyRuntime = ({
|
|
|
700
890
|
stage: "enrichSignalWithMl",
|
|
701
891
|
error,
|
|
702
892
|
decision,
|
|
703
|
-
|
|
893
|
+
entry,
|
|
894
|
+
market
|
|
704
895
|
});
|
|
705
896
|
throw error;
|
|
706
897
|
}
|
|
898
|
+
ml = buildMlHookContext({
|
|
899
|
+
signal,
|
|
900
|
+
env,
|
|
901
|
+
ml: runtime.ml
|
|
902
|
+
});
|
|
707
903
|
await invokeHook(
|
|
708
904
|
"afterEnrichMl",
|
|
709
905
|
decisionManifest?.hooks?.afterEnrichMl,
|
|
710
906
|
{
|
|
711
|
-
|
|
907
|
+
ctx: decisionHookCtx,
|
|
908
|
+
market,
|
|
712
909
|
decision,
|
|
713
|
-
|
|
714
|
-
|
|
910
|
+
entry,
|
|
911
|
+
ml
|
|
715
912
|
},
|
|
716
|
-
{ decision,
|
|
913
|
+
{ decision, entry, market }
|
|
717
914
|
);
|
|
718
915
|
}
|
|
719
916
|
let quality;
|
|
917
|
+
let ai;
|
|
720
918
|
if (signal) {
|
|
721
919
|
try {
|
|
722
920
|
quality = await enrichSignalWithAi({
|
|
@@ -731,24 +929,36 @@ var createStrategyRuntime = ({
|
|
|
731
929
|
stage: "enrichSignalWithAi",
|
|
732
930
|
error,
|
|
733
931
|
decision,
|
|
734
|
-
|
|
932
|
+
entry,
|
|
933
|
+
market
|
|
735
934
|
});
|
|
736
935
|
throw error;
|
|
737
936
|
}
|
|
937
|
+
ai = buildAiHookContext({
|
|
938
|
+
env,
|
|
939
|
+
ai: runtime.ai,
|
|
940
|
+
quality
|
|
941
|
+
});
|
|
738
942
|
await invokeHook(
|
|
739
943
|
"afterEnrichAi",
|
|
740
944
|
decisionManifest?.hooks?.afterEnrichAi,
|
|
741
945
|
{
|
|
742
|
-
|
|
946
|
+
ctx: decisionHookCtx,
|
|
947
|
+
market,
|
|
743
948
|
decision,
|
|
744
|
-
|
|
745
|
-
signal,
|
|
746
|
-
|
|
949
|
+
entry,
|
|
950
|
+
ml: ml ?? buildMlHookContext({ signal, env, ml: runtime.ml }),
|
|
951
|
+
ai
|
|
747
952
|
},
|
|
748
|
-
{ decision,
|
|
953
|
+
{ decision, entry, market }
|
|
749
954
|
);
|
|
750
955
|
}
|
|
751
956
|
const minAiQuality = runtime.ai?.minQuality ?? 4;
|
|
957
|
+
const policy = buildHookPolicy({
|
|
958
|
+
quality,
|
|
959
|
+
makeOrdersEnabled,
|
|
960
|
+
minAiQuality
|
|
961
|
+
});
|
|
752
962
|
const shouldMakeOrder = shouldExecuteEntryDecision({
|
|
753
963
|
makeOrdersEnabled,
|
|
754
964
|
env,
|
|
@@ -772,15 +982,15 @@ var createStrategyRuntime = ({
|
|
|
772
982
|
"beforeEntryGate",
|
|
773
983
|
decisionManifest?.hooks?.beforeEntryGate,
|
|
774
984
|
{
|
|
775
|
-
|
|
985
|
+
ctx: decisionHookCtx,
|
|
986
|
+
market,
|
|
776
987
|
decision,
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
minAiQuality
|
|
988
|
+
entry,
|
|
989
|
+
policy,
|
|
990
|
+
ml,
|
|
991
|
+
ai
|
|
782
992
|
},
|
|
783
|
-
{ decision,
|
|
993
|
+
{ decision, entry, market }
|
|
784
994
|
);
|
|
785
995
|
if (entryGate?.allow === false) {
|
|
786
996
|
const skipReason = entryGate.reason ? `HOOK_BEFORE_ENTRY_GATE:${entryGate.reason}` : "HOOK_BEFORE_ENTRY_GATE";
|
|
@@ -796,7 +1006,12 @@ var createStrategyRuntime = ({
|
|
|
796
1006
|
decision,
|
|
797
1007
|
runtime,
|
|
798
1008
|
manifest: decisionManifest,
|
|
799
|
-
|
|
1009
|
+
hookCtx: decisionHookCtx,
|
|
1010
|
+
market,
|
|
1011
|
+
entry,
|
|
1012
|
+
policy,
|
|
1013
|
+
ml,
|
|
1014
|
+
ai,
|
|
800
1015
|
invokeHook,
|
|
801
1016
|
notifyRuntimeError
|
|
802
1017
|
});
|
|
@@ -808,13 +1023,13 @@ var createStrategyRuntime = ({
|
|
|
808
1023
|
var createCloseOppositeBeforePlaceOrderHook = ({
|
|
809
1024
|
isEnabled
|
|
810
1025
|
}) => {
|
|
811
|
-
return async ({
|
|
812
|
-
if (!isEnabled(
|
|
1026
|
+
return async ({ ctx, entry }) => {
|
|
1027
|
+
if (!isEnabled(ctx.strategyConfig)) {
|
|
813
1028
|
return;
|
|
814
1029
|
}
|
|
815
1030
|
await closeOppositePositionsBeforeOpen({
|
|
816
|
-
connector,
|
|
817
|
-
entryContext
|
|
1031
|
+
connector: ctx.connector,
|
|
1032
|
+
entryContext: entry.context
|
|
818
1033
|
});
|
|
819
1034
|
};
|
|
820
1035
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/node",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Node-only TradeJS runtime for strategies, backtests, Pine loading, and plugin registries.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -54,15 +54,16 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@langchain/core": "^0.3.68",
|
|
56
56
|
"@langchain/openai": "^0.6.11",
|
|
57
|
-
"@tradejs/core": "^1.0.
|
|
58
|
-
"@tradejs/infra": "^1.0.
|
|
59
|
-
"@tradejs/types": "^1.0.
|
|
57
|
+
"@tradejs/core": "^1.0.4",
|
|
58
|
+
"@tradejs/infra": "^1.0.4",
|
|
59
|
+
"@tradejs/types": "^1.0.4",
|
|
60
60
|
"chalk": "4.1.2",
|
|
61
61
|
"ioredis": "5.8.0",
|
|
62
62
|
"pinets": "0.8.12",
|
|
63
63
|
"progress": "^2.0.3",
|
|
64
64
|
"puppeteer": "24.15.0",
|
|
65
|
-
"ts-node": "^10.9.2"
|
|
65
|
+
"ts-node": "^10.9.2",
|
|
66
|
+
"tsconfig-paths": "^4.2.0"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
69
|
"@types/node": "^20",
|