@tradejs/node 1.0.6 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.js +274 -126
- package/dist/ai.mjs +3 -3
- package/dist/backtest.js +345 -42
- package/dist/backtest.mjs +98 -16
- package/dist/chunk-2JKX3DM7.mjs +619 -0
- package/dist/{chunk-XW5L327F.mjs → chunk-JMDYEKIO.mjs} +1 -1
- package/dist/chunk-JRRG3YQG.mjs +154 -0
- package/dist/{chunk-CGJ2UU6H.mjs → chunk-JU77QVJ3.mjs} +8 -1
- package/dist/{chunk-SCMBUEGK.mjs → chunk-KMJQQ53K.mjs} +1 -1
- package/dist/{chunk-GKDBAF3A.mjs → chunk-KZDHZ56N.mjs} +25 -7
- package/dist/{chunk-EOZSJKUM.mjs → chunk-WGOYR6AB.mjs} +1 -1
- package/dist/cli.d.mts +20 -2
- package/dist/cli.d.ts +20 -2
- package/dist/cli.js +456 -183
- package/dist/cli.mjs +155 -49
- package/dist/connectors.js +6 -1
- package/dist/connectors.mjs +2 -2
- package/dist/constants.js +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/registry.js +6 -1
- package/dist/registry.mjs +2 -2
- package/dist/strategies.d.mts +24 -9
- package/dist/strategies.d.ts +24 -9
- package/dist/strategies.js +7465 -6467
- package/dist/strategies.mjs +865 -140
- package/package.json +6 -6
- package/dist/chunk-72FKXJ2I.mjs +0 -473
- package/dist/chunk-PQH5PAFC.mjs +0 -49
package/dist/cli.mjs
CHANGED
|
@@ -2,17 +2,18 @@ import {
|
|
|
2
2
|
AI_CONCURRENCY_LIMIT,
|
|
3
3
|
KLINE_CONCURRENCY_LIMIT,
|
|
4
4
|
SCREENSHOT_CONCURRENCY_LIMIT
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-KMJQQ53K.mjs";
|
|
6
6
|
import {
|
|
7
7
|
require_lodash
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KZDHZ56N.mjs";
|
|
9
9
|
import {
|
|
10
10
|
askAI
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-2JKX3DM7.mjs";
|
|
12
|
+
import "./chunk-WGOYR6AB.mjs";
|
|
13
13
|
import {
|
|
14
|
-
getTradejsProjectCwd
|
|
15
|
-
|
|
14
|
+
getTradejsProjectCwd,
|
|
15
|
+
loadTradejsConfig
|
|
16
|
+
} from "./chunk-JU77QVJ3.mjs";
|
|
16
17
|
import {
|
|
17
18
|
__toESM
|
|
18
19
|
} from "./chunk-6DZX6EAA.mjs";
|
|
@@ -43,7 +44,7 @@ import path from "path";
|
|
|
43
44
|
import puppeteer from "puppeteer";
|
|
44
45
|
import { delay } from "@tradejs/core/async";
|
|
45
46
|
import { logger } from "@tradejs/infra/logger";
|
|
46
|
-
import {
|
|
47
|
+
import { createScreenshotSessionToken } from "@tradejs/infra/redis";
|
|
47
48
|
var { APP_URL } = process.env;
|
|
48
49
|
var SCREENSHOT_NAVIGATION_ATTEMPTS = 3;
|
|
49
50
|
var SCREENSHOT_NAVIGATION_RETRY_DELAY_MS = 2e3;
|
|
@@ -62,7 +63,7 @@ var SCREENSHOT_VIEWPORT = {
|
|
|
62
63
|
};
|
|
63
64
|
var getProjectRoot = (projectRoot) => path.resolve(getTradejsProjectCwd(projectRoot));
|
|
64
65
|
var getScreenshotsDir = (projectRoot) => path.join(getProjectRoot(projectRoot), "data", "screenshots");
|
|
65
|
-
var maskTokenInUrl = (url) => url.replace(/([?&]
|
|
66
|
+
var maskTokenInUrl = (url) => url.replace(/([?&]screenshotToken=)[^&]+/i, "$1<hidden>");
|
|
66
67
|
var getErrorFields = (value) => {
|
|
67
68
|
if (!value || typeof value !== "object") {
|
|
68
69
|
return [];
|
|
@@ -146,10 +147,13 @@ var screenDashboard = async (signal, projectRoot, userName = "root") => {
|
|
|
146
147
|
const { symbol, signalId, interval } = signal;
|
|
147
148
|
const screenshotBaseUrl = getScreenshotRenderBaseUrl();
|
|
148
149
|
const screenshotPath = getScreenshotPath(signal, projectRoot);
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
const screenshotToken = await createScreenshotSessionToken(userName);
|
|
151
|
+
if (!screenshotToken) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Failed to create screenshot session token for ${userName}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
const dashboardUrl = `${screenshotBaseUrl}/routes/dashboard/bybit/${symbol}/${interval}/?signalId=${signalId}&autoZoom=true&screenshot=1&screenshotToken=${encodeURIComponent(screenshotToken)}`;
|
|
153
157
|
const maskedDashboardUrl = maskTokenInUrl(dashboardUrl);
|
|
154
158
|
logger.info(
|
|
155
159
|
"screenshot start: %s %sm url=%s path=%s",
|
|
@@ -405,7 +409,7 @@ var screenDashboard = async (signal, projectRoot, userName = "root") => {
|
|
|
405
409
|
import { delay as delay2 } from "@tradejs/core/async";
|
|
406
410
|
import { formatNumber } from "@tradejs/core/math";
|
|
407
411
|
import { logger as logger2 } from "@tradejs/infra/logger";
|
|
408
|
-
import { getUserSettings
|
|
412
|
+
import { getUserSettings } from "@tradejs/infra/userSettings";
|
|
409
413
|
var escapeHtml = (s) => {
|
|
410
414
|
if (!s) return "";
|
|
411
415
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -457,11 +461,51 @@ var describeErrorValue2 = (value) => {
|
|
|
457
461
|
return String(value);
|
|
458
462
|
};
|
|
459
463
|
var normalizeQuality = (value) => typeof value === "number" ? Math.max(1, Math.min(5, Math.round(value))) : null;
|
|
464
|
+
var formatAnalysisLevel = (value) => {
|
|
465
|
+
if (value == null || !Number.isFinite(value)) return null;
|
|
466
|
+
if (Math.abs(value) >= 1e3) {
|
|
467
|
+
return value.toFixed(0);
|
|
468
|
+
}
|
|
469
|
+
const digits = Math.abs(value) < 1 ? 8 : 6;
|
|
470
|
+
return value.toFixed(digits).replace(/\.?0+$/, "");
|
|
471
|
+
};
|
|
472
|
+
var normalizeAnalysisText = (value) => {
|
|
473
|
+
if (typeof value !== "string") return null;
|
|
474
|
+
const clean = value.replace(/\s+/g, " ").trim();
|
|
475
|
+
return clean || null;
|
|
476
|
+
};
|
|
477
|
+
var getReadableAnalysisComment = (value) => {
|
|
478
|
+
const clean = normalizeAnalysisText(value);
|
|
479
|
+
if (!clean) return null;
|
|
480
|
+
if (/^(ok|approved|approved by ai|historical approval|historical reject)$/i.test(
|
|
481
|
+
clean
|
|
482
|
+
)) {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
return clean;
|
|
486
|
+
};
|
|
487
|
+
var takeUniqueAnalysisText = (usedValues, ...values) => {
|
|
488
|
+
for (const value of values) {
|
|
489
|
+
const clean = normalizeAnalysisText(value);
|
|
490
|
+
if (!clean) continue;
|
|
491
|
+
const key = clean.toLowerCase();
|
|
492
|
+
if (usedValues.has(key)) continue;
|
|
493
|
+
usedValues.add(key);
|
|
494
|
+
return clean;
|
|
495
|
+
}
|
|
496
|
+
return null;
|
|
497
|
+
};
|
|
460
498
|
var formatOrderSkipReason = (reason) => {
|
|
461
499
|
if (!reason) return "";
|
|
462
500
|
if (reason.startsWith("AI_QUALITY_BELOW_MIN")) {
|
|
463
501
|
return "AI_QUALITY_BELOW_MIN";
|
|
464
502
|
}
|
|
503
|
+
if (reason.startsWith("ML_THRESHOLD_NOT_MET")) {
|
|
504
|
+
return "ML_THRESHOLD_NOT_MET";
|
|
505
|
+
}
|
|
506
|
+
if (reason === "ML_RESULT_UNAVAILABLE") {
|
|
507
|
+
return "ML_RESULT_UNAVAILABLE";
|
|
508
|
+
}
|
|
465
509
|
return reason;
|
|
466
510
|
};
|
|
467
511
|
var getLastNumber = (value) => {
|
|
@@ -534,7 +578,7 @@ var parseTelegramResponse = async (response) => {
|
|
|
534
578
|
}
|
|
535
579
|
};
|
|
536
580
|
var getTelegramSettings = async (userName = "root") => {
|
|
537
|
-
const settings = await
|
|
581
|
+
const settings = await getUserSettings(userName);
|
|
538
582
|
const token = settings.TG_BOT_TOKEN;
|
|
539
583
|
const chatId = settings.TG_CHAT_ID;
|
|
540
584
|
if (!token || !chatId) {
|
|
@@ -598,6 +642,15 @@ var sendTelegramMessage = async ({
|
|
|
598
642
|
);
|
|
599
643
|
return data;
|
|
600
644
|
};
|
|
645
|
+
var sendTextToTG = async (message, options = {}) => {
|
|
646
|
+
const { token, chatId } = await getTelegramSettings(options.userName);
|
|
647
|
+
return sendTelegramMessage({
|
|
648
|
+
message,
|
|
649
|
+
markup: options.markup,
|
|
650
|
+
token,
|
|
651
|
+
chatId
|
|
652
|
+
});
|
|
653
|
+
};
|
|
601
654
|
var formatMessage = (signal, analysis) => {
|
|
602
655
|
const {
|
|
603
656
|
symbol,
|
|
@@ -770,43 +823,78 @@ Reason: <code>${escapeHtml(reason)}</code>`,
|
|
|
770
823
|
};
|
|
771
824
|
var formatAnalysisMessage = (signal, analysis) => {
|
|
772
825
|
const lines = [];
|
|
773
|
-
const blocks = [];
|
|
774
826
|
const quality = normalizeQuality(analysis.quality);
|
|
827
|
+
const readableComment = getReadableAnalysisComment(analysis.comment);
|
|
828
|
+
const approvedDirection = analysis.direction != null && analysis.direction === signal.direction && analysis.needRetest !== true;
|
|
829
|
+
const oppositeDirection = analysis.direction != null && analysis.direction !== signal.direction;
|
|
830
|
+
const verdict = approvedDirection ? `Approved ${signal.direction}` : oppositeDirection ? `Not approved: AI prefers ${analysis.direction}` : analysis.needRetest ? "Not approved yet" : "Not approved";
|
|
831
|
+
const summary = approvedDirection ? `AI approves this ${signal.direction} setup right now.` : oppositeDirection ? `AI does not approve this ${signal.direction} setup and currently leans ${analysis.direction}.` : analysis.needRetest ? `The ${signal.direction} setup is visible, but confirmation is still missing before entry.` : `AI does not approve this ${signal.direction} setup right now.`;
|
|
832
|
+
const usedValues = /* @__PURE__ */ new Set();
|
|
775
833
|
lines.push(`<b>AI analysis ${signal.symbol}</b>`);
|
|
776
|
-
lines.push(`
|
|
777
|
-
lines.push(
|
|
834
|
+
lines.push(`Verdict: <b>${escapeHtml(verdict)}</b>`);
|
|
835
|
+
lines.push(escapeHtml(summary));
|
|
778
836
|
if (quality) {
|
|
779
837
|
lines.push(`Quality: <b>${quality}/5</b>`);
|
|
780
838
|
}
|
|
781
|
-
if (
|
|
782
|
-
lines.push(
|
|
839
|
+
if (analysis.gateDecision && analysis.llmDecision) {
|
|
840
|
+
lines.push(
|
|
841
|
+
`Gate vs LLM: <b>${analysis.gateContradictsLlm ? "conflict" : "aligned"}</b> (gate ${analysis.gateDecision}, LLM ${analysis.llmDecision})`
|
|
842
|
+
);
|
|
783
843
|
}
|
|
784
|
-
|
|
785
|
-
|
|
844
|
+
const happeningText = takeUniqueAnalysisText(
|
|
845
|
+
usedValues,
|
|
846
|
+
analysis.setup,
|
|
847
|
+
readableComment
|
|
848
|
+
);
|
|
849
|
+
if (happeningText) {
|
|
850
|
+
lines.push(`What's happening: ${escapeHtml(happeningText)}`);
|
|
851
|
+
}
|
|
852
|
+
const reasonText = approvedDirection ? takeUniqueAnalysisText(
|
|
853
|
+
usedValues,
|
|
854
|
+
analysis.qualityReason,
|
|
855
|
+
analysis.confirmations,
|
|
856
|
+
readableComment
|
|
857
|
+
) : takeUniqueAnalysisText(
|
|
858
|
+
usedValues,
|
|
859
|
+
analysis.qualityReason,
|
|
860
|
+
analysis.confirmations,
|
|
861
|
+
readableComment,
|
|
862
|
+
analysis.btcContext
|
|
863
|
+
);
|
|
864
|
+
if (reasonText) {
|
|
865
|
+
lines.push(
|
|
866
|
+
`${approvedDirection ? "Why approved" : "Why not approved"}: ${escapeHtml(reasonText)}`
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
const nextText = analysis.needRetest ? takeUniqueAnalysisText(
|
|
870
|
+
usedValues,
|
|
871
|
+
analysis.retestPlan,
|
|
872
|
+
analysis.triggerInvalidation,
|
|
873
|
+
typeof analysis.retestPrice === "number" ? `Wait for confirmation around ${formatAnalysisLevel(analysis.retestPrice)}.` : null
|
|
874
|
+
) : takeUniqueAnalysisText(
|
|
875
|
+
usedValues,
|
|
876
|
+
analysis.triggerInvalidation,
|
|
877
|
+
analysis.retestPlan
|
|
878
|
+
);
|
|
879
|
+
if (nextText) {
|
|
880
|
+
lines.push(`Next: ${escapeHtml(nextText)}`);
|
|
786
881
|
}
|
|
882
|
+
const btcText = takeUniqueAnalysisText(usedValues, analysis.btcContext);
|
|
883
|
+
if (btcText) {
|
|
884
|
+
lines.push(`BTC context: ${escapeHtml(btcText)}`);
|
|
885
|
+
}
|
|
886
|
+
const levels = [];
|
|
787
887
|
if (typeof analysis.takeProfitPrice === "number") {
|
|
788
|
-
|
|
888
|
+
levels.push(`TP <b>${formatAnalysisLevel(analysis.takeProfitPrice)}</b>`);
|
|
789
889
|
}
|
|
790
890
|
if (typeof analysis.stopLossPrice === "number") {
|
|
791
|
-
|
|
891
|
+
levels.push(`SL <b>${formatAnalysisLevel(analysis.stopLossPrice)}</b>`);
|
|
792
892
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
${escapeHtml(clean)}`);
|
|
799
|
-
};
|
|
800
|
-
pushBlock("Setup", analysis.setup);
|
|
801
|
-
pushBlock("Confirmations", analysis.confirmations);
|
|
802
|
-
pushBlock("BTC", analysis.btcContext);
|
|
803
|
-
pushBlock("Retest", analysis.retestPlan);
|
|
804
|
-
pushBlock("Risk/Levels", analysis.riskLevels);
|
|
805
|
-
pushBlock("Why Quality", analysis.qualityReason);
|
|
806
|
-
pushBlock("Trigger/Invalidation", analysis.triggerInvalidation);
|
|
807
|
-
if (blocks.length > 0) {
|
|
808
|
-
lines.push("");
|
|
809
|
-
lines.push(blocks.join("\n\n"));
|
|
893
|
+
if (typeof analysis.retestPrice === "number") {
|
|
894
|
+
levels.push(`Retest <b>${formatAnalysisLevel(analysis.retestPrice)}</b>`);
|
|
895
|
+
}
|
|
896
|
+
if (levels.length > 0) {
|
|
897
|
+
lines.push(`Levels: ${levels.join(" | ")}`);
|
|
810
898
|
}
|
|
811
899
|
return lines.join("\n");
|
|
812
900
|
};
|
|
@@ -889,9 +977,18 @@ var cleanRedis = async (area) => {
|
|
|
889
977
|
}
|
|
890
978
|
logger3.info("");
|
|
891
979
|
};
|
|
892
|
-
var update = async (connector, interval, tickers, preloadDays = PRELOAD_DAYS) => {
|
|
893
|
-
const
|
|
894
|
-
|
|
980
|
+
var update = async (connector, interval, tickers, preloadDays = PRELOAD_DAYS, options = {}) => {
|
|
981
|
+
const preloadStart = Math.trunc(
|
|
982
|
+
options.preloadStart ?? getTimestamp(preloadDays)
|
|
983
|
+
);
|
|
984
|
+
const preloadEnd = Math.trunc(options.preloadEnd ?? getTimestamp());
|
|
985
|
+
const connectorLabel = String(options.connectorLabel || "").trim();
|
|
986
|
+
const preloadLabel = options.preloadStart != null || options.preloadEnd != null ? `preloadStart=${preloadStart}, preloadEnd=${preloadEnd}` : `preloadDays=${preloadDays}`;
|
|
987
|
+
if (preloadStart >= preloadEnd) {
|
|
988
|
+
throw new Error(
|
|
989
|
+
`Invalid update preload window: start (${preloadStart}) must be less than end (${preloadEnd})`
|
|
990
|
+
);
|
|
991
|
+
}
|
|
895
992
|
const bar = new ProgressBar(
|
|
896
993
|
":current/:total [:bar][:percent] :eta(s) :symbol",
|
|
897
994
|
{
|
|
@@ -901,7 +998,7 @@ var update = async (connector, interval, tickers, preloadDays = PRELOAD_DAYS) =>
|
|
|
901
998
|
);
|
|
902
999
|
logger3.info(
|
|
903
1000
|
chalk.yellow(
|
|
904
|
-
`update: ${tickers.length} (klineConcurrency=${KLINE_CONCURRENCY_LIMIT},
|
|
1001
|
+
`update: ${tickers.length} (connector=${connectorLabel || "unknown"}, klineConcurrency=${KLINE_CONCURRENCY_LIMIT}, ${preloadLabel})`
|
|
905
1002
|
)
|
|
906
1003
|
);
|
|
907
1004
|
const queue = tickers.slice();
|
|
@@ -912,8 +1009,8 @@ var update = async (connector, interval, tickers, preloadDays = PRELOAD_DAYS) =>
|
|
|
912
1009
|
try {
|
|
913
1010
|
await connector.kline({
|
|
914
1011
|
symbol,
|
|
915
|
-
start:
|
|
916
|
-
end:
|
|
1012
|
+
start: preloadStart,
|
|
1013
|
+
end: preloadEnd,
|
|
917
1014
|
interval,
|
|
918
1015
|
silent: true,
|
|
919
1016
|
warmOnly: true
|
|
@@ -1019,15 +1116,22 @@ var sendToAI = async (signals, userName = "root") => {
|
|
|
1019
1116
|
logger3.info("");
|
|
1020
1117
|
};
|
|
1021
1118
|
var sendToTG = async (signals, imgInterval, userName = "root") => {
|
|
1119
|
+
const deliverableSignals = signals.filter(
|
|
1120
|
+
(signal) => signal.orderStatus !== "skipped" && signal.orderStatus !== "canceled"
|
|
1121
|
+
);
|
|
1122
|
+
logger3.info(chalk.yellow("messages:", deliverableSignals.length));
|
|
1123
|
+
if (!deliverableSignals.length) {
|
|
1124
|
+
logger3.info("");
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1022
1127
|
const bar = new ProgressBar(
|
|
1023
1128
|
":current/:total [:bar][:percent] :eta(s) :symbol",
|
|
1024
1129
|
{
|
|
1025
|
-
total:
|
|
1130
|
+
total: deliverableSignals.length,
|
|
1026
1131
|
width: 30
|
|
1027
1132
|
}
|
|
1028
1133
|
);
|
|
1029
|
-
|
|
1030
|
-
await runWithConcurrency(signals, 1, async (signal) => {
|
|
1134
|
+
await runWithConcurrency(deliverableSignals, 1, async (signal) => {
|
|
1031
1135
|
try {
|
|
1032
1136
|
const analysis = await getData(
|
|
1033
1137
|
redisKeys.analysis(signal.symbol, signal.signalId),
|
|
@@ -1054,7 +1158,9 @@ export {
|
|
|
1054
1158
|
cleanRedis,
|
|
1055
1159
|
drawStatInCLI,
|
|
1056
1160
|
getTickers,
|
|
1161
|
+
loadTradejsConfig,
|
|
1057
1162
|
makeScreenshots,
|
|
1163
|
+
sendTextToTG,
|
|
1058
1164
|
sendToAI,
|
|
1059
1165
|
sendToTG,
|
|
1060
1166
|
update
|
package/dist/connectors.js
CHANGED
|
@@ -52,6 +52,7 @@ var import_fs = __toESM(require("fs"));
|
|
|
52
52
|
var import_path = __toESM(require("path"));
|
|
53
53
|
var import_module = require("module");
|
|
54
54
|
var import_url = require("url");
|
|
55
|
+
var import_config = require("@tradejs/core/config");
|
|
55
56
|
var import_logger = require("@tradejs/infra/logger");
|
|
56
57
|
var CONFIG_FILE_NAMES = [
|
|
57
58
|
"tradejs.config.ts",
|
|
@@ -84,10 +85,14 @@ var normalizeConfig = (rawConfig) => {
|
|
|
84
85
|
const strategies = Array.isArray(config.strategies) ? config.strategies.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
85
86
|
const indicators = Array.isArray(config.indicators) ? config.indicators.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
86
87
|
const connectors = Array.isArray(config.connectors) ? config.connectors.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
88
|
+
const hooks = (0, import_config.normalizeTradejsConfigHooks)(
|
|
89
|
+
config.hooks
|
|
90
|
+
);
|
|
87
91
|
return {
|
|
88
92
|
strategies,
|
|
89
93
|
indicators,
|
|
90
|
-
connectors
|
|
94
|
+
connectors,
|
|
95
|
+
...hooks ? { hooks } : {}
|
|
91
96
|
};
|
|
92
97
|
};
|
|
93
98
|
var getRequireFn = (cwd = getTradejsProjectCwd()) => (0, import_module.createRequire)(import_path.default.join(import_path.default.resolve(cwd), "__tradejs_loader__.js"));
|
package/dist/connectors.mjs
CHANGED
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
registerConnectorEntries,
|
|
11
11
|
resetConnectorRegistryCache,
|
|
12
12
|
resolveConnectorName
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-JMDYEKIO.mjs";
|
|
14
|
+
import "./chunk-JU77QVJ3.mjs";
|
|
15
15
|
import "./chunk-6DZX6EAA.mjs";
|
|
16
16
|
export {
|
|
17
17
|
BUILTIN_CONNECTOR_NAMES,
|
package/dist/constants.js
CHANGED
|
@@ -32,7 +32,7 @@ var getPositiveIntegerEnv = (name, fallback) => {
|
|
|
32
32
|
const parsedValue = Number(rawValue);
|
|
33
33
|
return Number.isInteger(parsedValue) && parsedValue > 0 ? parsedValue : fallback;
|
|
34
34
|
};
|
|
35
|
-
var DEFAULT_KLINE_CONCURRENCY_LIMIT = NODE_ENV === "production" ?
|
|
35
|
+
var DEFAULT_KLINE_CONCURRENCY_LIMIT = NODE_ENV === "production" ? 5 : 10;
|
|
36
36
|
var KLINE_CONCURRENCY_LIMIT = getPositiveIntegerEnv(
|
|
37
37
|
"KLINE_CONCURRENCY_LIMIT",
|
|
38
38
|
DEFAULT_KLINE_CONCURRENCY_LIMIT
|
package/dist/constants.mjs
CHANGED
package/dist/registry.js
CHANGED
|
@@ -53,6 +53,7 @@ var import_fs = __toESM(require("fs"));
|
|
|
53
53
|
var import_path = __toESM(require("path"));
|
|
54
54
|
var import_module = require("module");
|
|
55
55
|
var import_url = require("url");
|
|
56
|
+
var import_config = require("@tradejs/core/config");
|
|
56
57
|
var import_logger = require("@tradejs/infra/logger");
|
|
57
58
|
var CONFIG_FILE_NAMES = [
|
|
58
59
|
"tradejs.config.ts",
|
|
@@ -85,10 +86,14 @@ var normalizeConfig = (rawConfig) => {
|
|
|
85
86
|
const strategies2 = Array.isArray(config.strategies) ? config.strategies.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
86
87
|
const indicators = Array.isArray(config.indicators) ? config.indicators.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
87
88
|
const connectors = Array.isArray(config.connectors) ? config.connectors.map((value) => String(value || "").trim()).filter(Boolean) : [];
|
|
89
|
+
const hooks = (0, import_config.normalizeTradejsConfigHooks)(
|
|
90
|
+
config.hooks
|
|
91
|
+
);
|
|
88
92
|
return {
|
|
89
93
|
strategies: strategies2,
|
|
90
94
|
indicators,
|
|
91
|
-
connectors
|
|
95
|
+
connectors,
|
|
96
|
+
...hooks ? { hooks } : {}
|
|
92
97
|
};
|
|
93
98
|
};
|
|
94
99
|
var getRequireFn = (cwd = getTradejsProjectCwd()) => (0, import_module.createRequire)(import_path.default.join(import_path.default.resolve(cwd), "__tradejs_loader__.js"));
|
package/dist/registry.mjs
CHANGED
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
registerStrategyEntries,
|
|
12
12
|
resetStrategyRegistryCache,
|
|
13
13
|
strategies
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-WGOYR6AB.mjs";
|
|
15
|
+
import "./chunk-JU77QVJ3.mjs";
|
|
16
16
|
import "./chunk-6DZX6EAA.mjs";
|
|
17
17
|
export {
|
|
18
18
|
ensureIndicatorPluginsLoaded,
|
package/dist/strategies.d.mts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import { Connector, StrategyEntrySignalContext, StrategyConfig, CreateStrategyCore, StrategyManifest, StrategyCreator, Signal, Direction, StrategyRuntimeMlOptions, StrategyRuntimeAiOptions, Tp } from '@tradejs/types';
|
|
2
1
|
export * from '@tradejs/core/strategies';
|
|
3
2
|
export { DEFAULT_AI_MODEL, MAX_AI_SERIES_POINTS, askAI, buildAiHumanPrompt, buildAiPayload, buildAiPrompts, buildAiSystemPrompt, ensureAiStrategyPluginsLoaded, getDeterministicAiGateContext, getOpenRouterModelKwargs, resetAiRuntimeCache, runAiPrompt, runAiPromptLocal, trimSeriesDeep } from './ai.mjs';
|
|
4
3
|
export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies } from './registry.mjs';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
connector: Connector;
|
|
8
|
-
entryContext: StrategyEntrySignalContext;
|
|
9
|
-
};
|
|
10
|
-
declare const closeOppositePositionsBeforeOpen: ({ connector, entryContext, }: CloseOppositePositionsBeforeOpenOptions) => Promise<void>;
|
|
4
|
+
import { StrategyConfig, CreateStrategyCore, StrategyManifest, StrategyCreator, Signal, Direction, StrategyRuntimeMlOptions, StrategyRuntimeAiOptions, Connector, Tp, StrategyEntrySignalContext } from '@tradejs/types';
|
|
5
|
+
import { TradejsConfigOnBarHook, TradejsConfigBeforeSignalsHook } from '@tradejs/core/config';
|
|
11
6
|
|
|
12
7
|
interface CreateStrategyRuntimeParams<TConfig extends StrategyConfig> {
|
|
13
8
|
strategyName: string;
|
|
@@ -44,6 +39,7 @@ declare const enrichSignalWithAi: ({ signal, symbol, userName, direction, env, a
|
|
|
44
39
|
declare const enrichSignalWithMlAi: ({ signal, userName, symbol, direction, env, ml, ai, }: EnrichSignalWithMlAiParams) => Promise<number | undefined>;
|
|
45
40
|
interface ExecuteEntryOrderParams {
|
|
46
41
|
connector: Connector;
|
|
42
|
+
userName?: string;
|
|
47
43
|
symbol: string;
|
|
48
44
|
direction: Direction;
|
|
49
45
|
qty: number;
|
|
@@ -53,13 +49,32 @@ interface ExecuteEntryOrderParams {
|
|
|
53
49
|
stopLossPrice: number | null;
|
|
54
50
|
signal: Signal;
|
|
55
51
|
beforePlaceOrder?: () => Promise<void>;
|
|
52
|
+
recordRuntimeTrade?: boolean;
|
|
56
53
|
}
|
|
57
|
-
declare const executeEntryOrder: ({ connector, symbol, direction, qty, currentPrice, timestamp, takeProfits, stopLossPrice, signal, beforePlaceOrder, }: ExecuteEntryOrderParams) => Promise<number>;
|
|
54
|
+
declare const executeEntryOrder: ({ connector, userName, symbol, direction, qty, currentPrice, timestamp, takeProfits, stopLossPrice, signal, beforePlaceOrder, recordRuntimeTrade, }: ExecuteEntryOrderParams) => Promise<number>;
|
|
58
55
|
|
|
56
|
+
type CloseOppositePositionsBeforeOpenOptions = {
|
|
57
|
+
connector: Connector;
|
|
58
|
+
entryContext: StrategyEntrySignalContext;
|
|
59
|
+
};
|
|
59
60
|
type BeforePlaceOrderHook = NonNullable<NonNullable<StrategyManifest['hooks']>['beforePlaceOrder']>;
|
|
60
61
|
interface CreateCloseOppositeBeforePlaceOrderHookParams {
|
|
61
62
|
isEnabled: (config: StrategyConfig) => boolean;
|
|
62
63
|
}
|
|
64
|
+
declare const closeOppositePositionsBeforeOpen: ({ connector, entryContext, }: CloseOppositePositionsBeforeOpenOptions) => Promise<void>;
|
|
63
65
|
declare const createCloseOppositeBeforePlaceOrderHook: ({ isEnabled, }: CreateCloseOppositeBeforePlaceOrderHookParams) => BeforePlaceOrderHook;
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
interface CreateMoveStopToBreakEvenOnBarHookParams {
|
|
68
|
+
isEnabled?: (config: StrategyConfig) => boolean;
|
|
69
|
+
triggerRiskMultiplier?: number;
|
|
70
|
+
}
|
|
71
|
+
declare const createMoveStopToBreakEvenOnBarHook: ({ isEnabled, triggerRiskMultiplier, }?: CreateMoveStopToBreakEvenOnBarHookParams) => TradejsConfigOnBarHook;
|
|
72
|
+
declare const createMoveStopToBreakEvenAfterCoreDecisionHook: ({ isEnabled, triggerRiskMultiplier, }?: CreateMoveStopToBreakEvenOnBarHookParams) => TradejsConfigOnBarHook;
|
|
73
|
+
|
|
74
|
+
interface CreateCloseAllOnGlobalProfitBeforeSignalsHookParams {
|
|
75
|
+
getStrategyDefaultConfig?: (strategyName: string) => StrategyConfig | undefined;
|
|
76
|
+
profitRiskMultiplier?: number;
|
|
77
|
+
}
|
|
78
|
+
declare const createCloseAllOnGlobalProfitBeforeSignalsHook: ({ getStrategyDefaultConfig, profitRiskMultiplier, }?: CreateCloseAllOnGlobalProfitBeforeSignalsHookParams) => TradejsConfigBeforeSignalsHook;
|
|
79
|
+
|
|
80
|
+
export { closeOppositePositionsBeforeOpen, createCloseAllOnGlobalProfitBeforeSignalsHook, createCloseOppositeBeforePlaceOrderHook, createMoveStopToBreakEvenAfterCoreDecisionHook, createMoveStopToBreakEvenOnBarHook, createStrategyRuntime, enrichSignalWithAi, enrichSignalWithMl, enrichSignalWithMlAi, executeEntryOrder, resolveStrategyConfig };
|
package/dist/strategies.d.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import { Connector, StrategyEntrySignalContext, StrategyConfig, CreateStrategyCore, StrategyManifest, StrategyCreator, Signal, Direction, StrategyRuntimeMlOptions, StrategyRuntimeAiOptions, Tp } from '@tradejs/types';
|
|
2
1
|
export * from '@tradejs/core/strategies';
|
|
3
2
|
export { DEFAULT_AI_MODEL, MAX_AI_SERIES_POINTS, askAI, buildAiHumanPrompt, buildAiPayload, buildAiPrompts, buildAiSystemPrompt, ensureAiStrategyPluginsLoaded, getDeterministicAiGateContext, getOpenRouterModelKwargs, resetAiRuntimeCache, runAiPrompt, runAiPromptLocal, trimSeriesDeep } from './ai.js';
|
|
4
3
|
export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies } from './registry.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
connector: Connector;
|
|
8
|
-
entryContext: StrategyEntrySignalContext;
|
|
9
|
-
};
|
|
10
|
-
declare const closeOppositePositionsBeforeOpen: ({ connector, entryContext, }: CloseOppositePositionsBeforeOpenOptions) => Promise<void>;
|
|
4
|
+
import { StrategyConfig, CreateStrategyCore, StrategyManifest, StrategyCreator, Signal, Direction, StrategyRuntimeMlOptions, StrategyRuntimeAiOptions, Connector, Tp, StrategyEntrySignalContext } from '@tradejs/types';
|
|
5
|
+
import { TradejsConfigOnBarHook, TradejsConfigBeforeSignalsHook } from '@tradejs/core/config';
|
|
11
6
|
|
|
12
7
|
interface CreateStrategyRuntimeParams<TConfig extends StrategyConfig> {
|
|
13
8
|
strategyName: string;
|
|
@@ -44,6 +39,7 @@ declare const enrichSignalWithAi: ({ signal, symbol, userName, direction, env, a
|
|
|
44
39
|
declare const enrichSignalWithMlAi: ({ signal, userName, symbol, direction, env, ml, ai, }: EnrichSignalWithMlAiParams) => Promise<number | undefined>;
|
|
45
40
|
interface ExecuteEntryOrderParams {
|
|
46
41
|
connector: Connector;
|
|
42
|
+
userName?: string;
|
|
47
43
|
symbol: string;
|
|
48
44
|
direction: Direction;
|
|
49
45
|
qty: number;
|
|
@@ -53,13 +49,32 @@ interface ExecuteEntryOrderParams {
|
|
|
53
49
|
stopLossPrice: number | null;
|
|
54
50
|
signal: Signal;
|
|
55
51
|
beforePlaceOrder?: () => Promise<void>;
|
|
52
|
+
recordRuntimeTrade?: boolean;
|
|
56
53
|
}
|
|
57
|
-
declare const executeEntryOrder: ({ connector, symbol, direction, qty, currentPrice, timestamp, takeProfits, stopLossPrice, signal, beforePlaceOrder, }: ExecuteEntryOrderParams) => Promise<number>;
|
|
54
|
+
declare const executeEntryOrder: ({ connector, userName, symbol, direction, qty, currentPrice, timestamp, takeProfits, stopLossPrice, signal, beforePlaceOrder, recordRuntimeTrade, }: ExecuteEntryOrderParams) => Promise<number>;
|
|
58
55
|
|
|
56
|
+
type CloseOppositePositionsBeforeOpenOptions = {
|
|
57
|
+
connector: Connector;
|
|
58
|
+
entryContext: StrategyEntrySignalContext;
|
|
59
|
+
};
|
|
59
60
|
type BeforePlaceOrderHook = NonNullable<NonNullable<StrategyManifest['hooks']>['beforePlaceOrder']>;
|
|
60
61
|
interface CreateCloseOppositeBeforePlaceOrderHookParams {
|
|
61
62
|
isEnabled: (config: StrategyConfig) => boolean;
|
|
62
63
|
}
|
|
64
|
+
declare const closeOppositePositionsBeforeOpen: ({ connector, entryContext, }: CloseOppositePositionsBeforeOpenOptions) => Promise<void>;
|
|
63
65
|
declare const createCloseOppositeBeforePlaceOrderHook: ({ isEnabled, }: CreateCloseOppositeBeforePlaceOrderHookParams) => BeforePlaceOrderHook;
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
interface CreateMoveStopToBreakEvenOnBarHookParams {
|
|
68
|
+
isEnabled?: (config: StrategyConfig) => boolean;
|
|
69
|
+
triggerRiskMultiplier?: number;
|
|
70
|
+
}
|
|
71
|
+
declare const createMoveStopToBreakEvenOnBarHook: ({ isEnabled, triggerRiskMultiplier, }?: CreateMoveStopToBreakEvenOnBarHookParams) => TradejsConfigOnBarHook;
|
|
72
|
+
declare const createMoveStopToBreakEvenAfterCoreDecisionHook: ({ isEnabled, triggerRiskMultiplier, }?: CreateMoveStopToBreakEvenOnBarHookParams) => TradejsConfigOnBarHook;
|
|
73
|
+
|
|
74
|
+
interface CreateCloseAllOnGlobalProfitBeforeSignalsHookParams {
|
|
75
|
+
getStrategyDefaultConfig?: (strategyName: string) => StrategyConfig | undefined;
|
|
76
|
+
profitRiskMultiplier?: number;
|
|
77
|
+
}
|
|
78
|
+
declare const createCloseAllOnGlobalProfitBeforeSignalsHook: ({ getStrategyDefaultConfig, profitRiskMultiplier, }?: CreateCloseAllOnGlobalProfitBeforeSignalsHookParams) => TradejsConfigBeforeSignalsHook;
|
|
79
|
+
|
|
80
|
+
export { closeOppositePositionsBeforeOpen, createCloseAllOnGlobalProfitBeforeSignalsHook, createCloseOppositeBeforePlaceOrderHook, createMoveStopToBreakEvenAfterCoreDecisionHook, createMoveStopToBreakEvenOnBarHook, createStrategyRuntime, enrichSignalWithAi, enrichSignalWithMl, enrichSignalWithMlAi, executeEntryOrder, resolveStrategyConfig };
|