@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/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-SCMBUEGK.mjs";
5
+ } from "./chunk-KMJQQ53K.mjs";
6
6
  import {
7
7
  require_lodash
8
- } from "./chunk-GKDBAF3A.mjs";
8
+ } from "./chunk-KZDHZ56N.mjs";
9
9
  import {
10
10
  askAI
11
- } from "./chunk-72FKXJ2I.mjs";
12
- import "./chunk-EOZSJKUM.mjs";
11
+ } from "./chunk-2JKX3DM7.mjs";
12
+ import "./chunk-WGOYR6AB.mjs";
13
13
  import {
14
- getTradejsProjectCwd
15
- } from "./chunk-CGJ2UU6H.mjs";
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 { getUserSettings } from "@tradejs/infra/userSettings";
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(/([?&]token=)[^&]+/i, "$1<hidden>");
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 settings = await getUserSettings(userName);
150
- const token = settings.token;
151
- const tokenParam = typeof token === "string" && token.length > 0 ? `&token=${encodeURIComponent(token)}` : "";
152
- const dashboardUrl = `${screenshotBaseUrl}/routes/dashboard/bybit/${symbol}/${interval}/?signalId=${signalId}&autoZoom=true&screenshot=1${tokenParam}`;
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 as getUserSettings2 } from "@tradejs/infra/userSettings";
412
+ import { getUserSettings } from "@tradejs/infra/userSettings";
409
413
  var escapeHtml = (s) => {
410
414
  if (!s) return "";
411
415
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -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 getUserSettings2(userName);
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(`Signal direction: <b>${signal.direction}</b>`);
777
- lines.push(`AI direction: <b>${analysis.direction ?? "NO TRADE"}</b>`);
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 (typeof analysis.needRetest === "boolean") {
782
- lines.push(`Need retest: <b>${analysis.needRetest ? "YES" : "NO"}</b>`);
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
- if (typeof analysis.retestPrice === "number") {
785
- lines.push(`Retest price: <b>${formatNumber(analysis.retestPrice)}</b>`);
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
- lines.push(`AI TP: <b>${formatNumber(analysis.takeProfitPrice)}</b>`);
888
+ levels.push(`TP <b>${formatAnalysisLevel(analysis.takeProfitPrice)}</b>`);
789
889
  }
790
890
  if (typeof analysis.stopLossPrice === "number") {
791
- lines.push(`AI SL: <b>${formatNumber(analysis.stopLossPrice)}</b>`);
891
+ levels.push(`SL <b>${formatAnalysisLevel(analysis.stopLossPrice)}</b>`);
792
892
  }
793
- const pushBlock = (title, value) => {
794
- if (!value) return;
795
- const clean = value.trim();
796
- if (!clean) return;
797
- blocks.push(`<b>${title}:</b>
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 PRELOAD_START = getTimestamp(preloadDays);
894
- const PRELOAD_END = getTimestamp();
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}, preloadDays=${preloadDays})`
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: PRELOAD_START,
916
- end: PRELOAD_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: signals.length,
1130
+ total: deliverableSignals.length,
1026
1131
  width: 30
1027
1132
  }
1028
1133
  );
1029
- logger3.info(chalk.yellow("messages:", signals.length));
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
@@ -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"));
@@ -10,8 +10,8 @@ import {
10
10
  registerConnectorEntries,
11
11
  resetConnectorRegistryCache,
12
12
  resolveConnectorName
13
- } from "./chunk-XW5L327F.mjs";
14
- import "./chunk-CGJ2UU6H.mjs";
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" ? 1 : 10;
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
@@ -3,7 +3,7 @@ import {
3
3
  KLINE_CONCURRENCY_LIMIT,
4
4
  SCREENSHOT_CONCURRENCY_LIMIT,
5
5
  TG_CONCURRENCY_LIMIT
6
- } from "./chunk-SCMBUEGK.mjs";
6
+ } from "./chunk-KMJQQ53K.mjs";
7
7
  import "./chunk-6DZX6EAA.mjs";
8
8
  export {
9
9
  AI_CONCURRENCY_LIMIT,
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-EOZSJKUM.mjs";
15
- import "./chunk-CGJ2UU6H.mjs";
14
+ } from "./chunk-WGOYR6AB.mjs";
15
+ import "./chunk-JU77QVJ3.mjs";
16
16
  import "./chunk-6DZX6EAA.mjs";
17
17
  export {
18
18
  ensureIndicatorPluginsLoaded,
@@ -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
- type CloseOppositePositionsBeforeOpenOptions = {
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
- export { closeOppositePositionsBeforeOpen, createCloseOppositeBeforePlaceOrderHook, createStrategyRuntime, enrichSignalWithAi, enrichSignalWithMl, enrichSignalWithMlAi, executeEntryOrder, resolveStrategyConfig };
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 };
@@ -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
- type CloseOppositePositionsBeforeOpenOptions = {
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
- export { closeOppositePositionsBeforeOpen, createCloseOppositeBeforePlaceOrderHook, createStrategyRuntime, enrichSignalWithAi, enrichSignalWithMl, enrichSignalWithMlAi, executeEntryOrder, resolveStrategyConfig };
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 };