backtest-kit 6.14.0 → 6.15.0

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/build/index.cjs CHANGED
@@ -7983,6 +7983,40 @@ class ClientStrategy {
7983
7983
  }
7984
7984
  return Math.floor((timestamp - this._pendingSignal._peak.timestamp) / 60000);
7985
7985
  }
7986
+ /**
7987
+ * Returns the number of minutes the position has been active since it opened.
7988
+ *
7989
+ * Computed as elapsed minutes since `pendingAt` (the moment the signal was activated).
7990
+ * Returns null if no pending signal exists.
7991
+ *
7992
+ * @param symbol - Trading pair symbol
7993
+ * @param timestamp - Current Unix timestamp in milliseconds
7994
+ * @returns Promise resolving to active minutes (≥ 0) or null
7995
+ */
7996
+ async getPositionActiveMinutes(symbol, timestamp) {
7997
+ this.params.logger.debug("ClientStrategy getPositionActiveMinutes", { symbol });
7998
+ if (!this._pendingSignal) {
7999
+ return null;
8000
+ }
8001
+ return Math.floor((timestamp - this._pendingSignal.pendingAt) / 60000);
8002
+ }
8003
+ /**
8004
+ * Returns the number of minutes the scheduled signal has been waiting for activation.
8005
+ *
8006
+ * Computed as elapsed minutes since `scheduledAt` (the moment the scheduled signal was created).
8007
+ * Returns null if no scheduled signal exists.
8008
+ *
8009
+ * @param symbol - Trading pair symbol
8010
+ * @param timestamp - Current Unix timestamp in milliseconds
8011
+ * @returns Promise resolving to waiting minutes (≥ 0) or null
8012
+ */
8013
+ async getPositionWaitingMinutes(symbol, timestamp) {
8014
+ this.params.logger.debug("ClientStrategy getPositionWaitingMinutes", { symbol });
8015
+ if (!this._scheduledSignal) {
8016
+ return null;
8017
+ }
8018
+ return Math.floor((timestamp - this._scheduledSignal.scheduledAt) / 60000);
8019
+ }
7986
8020
  /**
7987
8021
  * Returns the number of minutes elapsed since the highest profit price was recorded.
7988
8022
  *
@@ -11084,6 +11118,46 @@ class StrategyConnectionService {
11084
11118
  const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
11085
11119
  return await strategy.getPositionCountdownMinutes(symbol, timestamp);
11086
11120
  };
11121
+ /**
11122
+ * Returns the number of minutes the position has been active since it opened.
11123
+ *
11124
+ * Delegates to ClientStrategy.getPositionActiveMinutes().
11125
+ * Returns null if no pending signal exists.
11126
+ *
11127
+ * @param backtest - Whether running in backtest mode
11128
+ * @param symbol - Trading pair symbol
11129
+ * @param context - Execution context with strategyName, exchangeName, frameName
11130
+ * @returns Promise resolving to active minutes (≥ 0) or null
11131
+ */
11132
+ this.getPositionActiveMinutes = async (backtest, symbol, context) => {
11133
+ this.loggerService.log("strategyConnectionService getPositionActiveMinutes", {
11134
+ symbol,
11135
+ context,
11136
+ });
11137
+ const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
11138
+ const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
11139
+ return await strategy.getPositionActiveMinutes(symbol, timestamp);
11140
+ };
11141
+ /**
11142
+ * Returns the number of minutes the scheduled signal has been waiting for activation.
11143
+ *
11144
+ * Delegates to ClientStrategy.getPositionWaitingMinutes().
11145
+ * Returns null if no scheduled signal exists.
11146
+ *
11147
+ * @param backtest - Whether running in backtest mode
11148
+ * @param symbol - Trading pair symbol
11149
+ * @param context - Execution context with strategyName, exchangeName, frameName
11150
+ * @returns Promise resolving to waiting minutes (≥ 0) or null
11151
+ */
11152
+ this.getPositionWaitingMinutes = async (backtest, symbol, context) => {
11153
+ this.loggerService.log("strategyConnectionService getPositionWaitingMinutes", {
11154
+ symbol,
11155
+ context,
11156
+ });
11157
+ const strategy = this.getStrategy(symbol, context.strategyName, context.exchangeName, context.frameName, backtest);
11158
+ const timestamp = await this.timeMetaService.getTimestamp(symbol, context, backtest);
11159
+ return await strategy.getPositionWaitingMinutes(symbol, timestamp);
11160
+ };
11087
11161
  /**
11088
11162
  * Returns the best price reached in the profit direction during this position's life.
11089
11163
  *
@@ -15404,6 +15478,38 @@ class StrategyCoreService {
15404
15478
  await this.validate(context);
15405
15479
  return await this.strategyConnectionService.getPositionCountdownMinutes(backtest, symbol, context);
15406
15480
  };
15481
+ /**
15482
+ * Returns the number of minutes the position has been active since it opened.
15483
+ *
15484
+ * @param backtest - Whether running in backtest mode
15485
+ * @param symbol - Trading pair symbol
15486
+ * @param context - Execution context with strategyName, exchangeName, frameName
15487
+ * @returns Promise resolving to active minutes (≥ 0) or null
15488
+ */
15489
+ this.getPositionActiveMinutes = async (backtest, symbol, context) => {
15490
+ this.loggerService.log("strategyCoreService getPositionActiveMinutes", {
15491
+ symbol,
15492
+ context,
15493
+ });
15494
+ await this.validate(context);
15495
+ return await this.strategyConnectionService.getPositionActiveMinutes(backtest, symbol, context);
15496
+ };
15497
+ /**
15498
+ * Returns the number of minutes the scheduled signal has been waiting for activation.
15499
+ *
15500
+ * @param backtest - Whether running in backtest mode
15501
+ * @param symbol - Trading pair symbol
15502
+ * @param context - Execution context with strategyName, exchangeName, frameName
15503
+ * @returns Promise resolving to waiting minutes (≥ 0) or null
15504
+ */
15505
+ this.getPositionWaitingMinutes = async (backtest, symbol, context) => {
15506
+ this.loggerService.log("strategyCoreService getPositionWaitingMinutes", {
15507
+ symbol,
15508
+ context,
15509
+ });
15510
+ await this.validate(context);
15511
+ return await this.strategyConnectionService.getPositionWaitingMinutes(backtest, symbol, context);
15512
+ };
15407
15513
  /**
15408
15514
  * Returns the best price reached in the profit direction during this position's life.
15409
15515
  *
@@ -32410,7 +32516,7 @@ class NotificationHelperService {
32410
32516
  const pendingSignal = await this.strategyCoreService.getPendingSignal(backtest, symbol, currentPrice, {
32411
32517
  strategyName: context.strategyName,
32412
32518
  exchangeName: context.exchangeName,
32413
- frameName: "",
32519
+ frameName: context.frameName,
32414
32520
  });
32415
32521
  if (!pendingSignal) {
32416
32522
  throw new Error(`SignalUtils notify No pending signal found symbol=${symbol} `);
@@ -35550,6 +35656,8 @@ const GET_POSITION_PARTIALS_METHOD_NAME = "strategy.getPositionPartials";
35550
35656
  const GET_POSITION_ENTRIES_METHOD_NAME = "strategy.getPositionEntries";
35551
35657
  const GET_POSITION_ESTIMATE_MINUTES_METHOD_NAME = "strategy.getPositionEstimateMinutes";
35552
35658
  const GET_POSITION_COUNTDOWN_MINUTES_METHOD_NAME = "strategy.getPositionCountdownMinutes";
35659
+ const GET_POSITION_ACTIVE_MINUTES_METHOD_NAME = "strategy.getPositionActiveMinutes";
35660
+ const GET_POSITION_WAITING_MINUTES_METHOD_NAME = "strategy.getPositionWaitingMinutes";
35553
35661
  const GET_POSITION_HIGHEST_PROFIT_PRICE_METHOD_NAME = "strategy.getPositionHighestProfitPrice";
35554
35662
  const GET_POSITION_HIGHEST_PROFIT_TIMESTAMP_METHOD_NAME = "strategy.getPositionHighestProfitTimestamp";
35555
35663
  const GET_POSITION_HIGHEST_PNL_PERCENTAGE_METHOD_NAME = "strategy.getPositionHighestPnlPercentage";
@@ -36850,6 +36958,62 @@ async function getPositionCountdownMinutes(symbol) {
36850
36958
  const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
36851
36959
  return await backtest.strategyCoreService.getPositionCountdownMinutes(isBacktest, symbol, { exchangeName, frameName, strategyName });
36852
36960
  }
36961
+ /**
36962
+ * Returns the number of minutes the position has been active since it opened.
36963
+ *
36964
+ * Returns null if no pending signal exists.
36965
+ *
36966
+ * @param symbol - Trading pair symbol
36967
+ * @returns Promise resolving to active minutes (≥ 0) or null
36968
+ *
36969
+ * @example
36970
+ * ```typescript
36971
+ * import { getPositionActiveMinutes } from "backtest-kit";
36972
+ *
36973
+ * const minutes = await getPositionActiveMinutes("BTCUSDT");
36974
+ * // e.g. 120 (position has been open for 2 hours)
36975
+ * ```
36976
+ */
36977
+ async function getPositionActiveMinutes(symbol) {
36978
+ backtest.loggerService.info(GET_POSITION_ACTIVE_MINUTES_METHOD_NAME, { symbol });
36979
+ if (!ExecutionContextService.hasContext()) {
36980
+ throw new Error("getPositionActiveMinutes requires an execution context");
36981
+ }
36982
+ if (!MethodContextService.hasContext()) {
36983
+ throw new Error("getPositionActiveMinutes requires a method context");
36984
+ }
36985
+ const { backtest: isBacktest } = backtest.executionContextService.context;
36986
+ const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
36987
+ return await backtest.strategyCoreService.getPositionActiveMinutes(isBacktest, symbol, { exchangeName, frameName, strategyName });
36988
+ }
36989
+ /**
36990
+ * Returns the number of minutes the scheduled signal has been waiting for activation.
36991
+ *
36992
+ * Returns null if no scheduled signal exists.
36993
+ *
36994
+ * @param symbol - Trading pair symbol
36995
+ * @returns Promise resolving to waiting minutes (≥ 0) or null
36996
+ *
36997
+ * @example
36998
+ * ```typescript
36999
+ * import { getPositionWaitingMinutes } from "backtest-kit";
37000
+ *
37001
+ * const minutes = await getPositionWaitingMinutes("BTCUSDT");
37002
+ * // e.g. 15 (scheduled signal has been waiting 15 minutes for activation)
37003
+ * ```
37004
+ */
37005
+ async function getPositionWaitingMinutes(symbol) {
37006
+ backtest.loggerService.info(GET_POSITION_WAITING_MINUTES_METHOD_NAME, { symbol });
37007
+ if (!ExecutionContextService.hasContext()) {
37008
+ throw new Error("getPositionWaitingMinutes requires an execution context");
37009
+ }
37010
+ if (!MethodContextService.hasContext()) {
37011
+ throw new Error("getPositionWaitingMinutes requires a method context");
37012
+ }
37013
+ const { backtest: isBacktest } = backtest.executionContextService.context;
37014
+ const { exchangeName, frameName, strategyName } = backtest.methodContextService.context;
37015
+ return await backtest.strategyCoreService.getPositionWaitingMinutes(isBacktest, symbol, { exchangeName, frameName, strategyName });
37016
+ }
36853
37017
  /**
36854
37018
  * Returns the best price reached in the profit direction during this position's life.
36855
37019
  *
@@ -39120,6 +39284,8 @@ const BACKTEST_METHOD_NAME_GET_POSITION_PARTIALS = "BacktestUtils.getPositionPar
39120
39284
  const BACKTEST_METHOD_NAME_GET_POSITION_ENTRIES = "BacktestUtils.getPositionEntries";
39121
39285
  const BACKTEST_METHOD_NAME_GET_POSITION_ESTIMATE_MINUTES = "BacktestUtils.getPositionEstimateMinutes";
39122
39286
  const BACKTEST_METHOD_NAME_GET_POSITION_COUNTDOWN_MINUTES = "BacktestUtils.getPositionCountdownMinutes";
39287
+ const BACKTEST_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES = "BacktestUtils.getPositionActiveMinutes";
39288
+ const BACKTEST_METHOD_NAME_GET_POSITION_WAITING_MINUTES = "BacktestUtils.getPositionWaitingMinutes";
39123
39289
  const BACKTEST_METHOD_NAME_GET_POSITION_HIGHEST_PROFIT_PRICE = "BacktestUtils.getPositionHighestProfitPrice";
39124
39290
  const BACKTEST_METHOD_NAME_GET_POSITION_HIGHEST_PROFIT_TIMESTAMP = "BacktestUtils.getPositionHighestProfitTimestamp";
39125
39291
  const BACKTEST_METHOD_NAME_GET_POSITION_HIGHEST_PNL_PERCENTAGE = "BacktestUtils.getPositionHighestPnlPercentage";
@@ -40075,6 +40241,60 @@ class BacktestUtils {
40075
40241
  }
40076
40242
  return await backtest.strategyCoreService.getPositionCountdownMinutes(true, symbol, context);
40077
40243
  };
40244
+ /**
40245
+ * Returns the number of minutes the position has been active since it opened.
40246
+ *
40247
+ * Returns null if no pending signal exists.
40248
+ *
40249
+ * @param symbol - Trading pair symbol
40250
+ * @param context - Execution context with strategyName, exchangeName, and frameName
40251
+ * @returns Active minutes (≥ 0), or null if no active position
40252
+ */
40253
+ this.getPositionActiveMinutes = async (symbol, context) => {
40254
+ backtest.loggerService.info(BACKTEST_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES, {
40255
+ symbol,
40256
+ context,
40257
+ });
40258
+ backtest.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
40259
+ backtest.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
40260
+ {
40261
+ const { riskName, riskList, actions } = backtest.strategySchemaService.get(context.strategyName);
40262
+ riskName &&
40263
+ backtest.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
40264
+ riskList &&
40265
+ riskList.forEach((riskName) => backtest.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES));
40266
+ actions &&
40267
+ actions.forEach((actionName) => backtest.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES));
40268
+ }
40269
+ return await backtest.strategyCoreService.getPositionActiveMinutes(true, symbol, context);
40270
+ };
40271
+ /**
40272
+ * Returns the number of minutes the scheduled signal has been waiting for activation.
40273
+ *
40274
+ * Returns null if no scheduled signal exists.
40275
+ *
40276
+ * @param symbol - Trading pair symbol
40277
+ * @param context - Execution context with strategyName, exchangeName, and frameName
40278
+ * @returns Waiting minutes (≥ 0), or null if no scheduled signal
40279
+ */
40280
+ this.getPositionWaitingMinutes = async (symbol, context) => {
40281
+ backtest.loggerService.info(BACKTEST_METHOD_NAME_GET_POSITION_WAITING_MINUTES, {
40282
+ symbol,
40283
+ context,
40284
+ });
40285
+ backtest.strategyValidationService.validate(context.strategyName, BACKTEST_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
40286
+ backtest.exchangeValidationService.validate(context.exchangeName, BACKTEST_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
40287
+ {
40288
+ const { riskName, riskList, actions } = backtest.strategySchemaService.get(context.strategyName);
40289
+ riskName &&
40290
+ backtest.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
40291
+ riskList &&
40292
+ riskList.forEach((riskName) => backtest.riskValidationService.validate(riskName, BACKTEST_METHOD_NAME_GET_POSITION_WAITING_MINUTES));
40293
+ actions &&
40294
+ actions.forEach((actionName) => backtest.actionValidationService.validate(actionName, BACKTEST_METHOD_NAME_GET_POSITION_WAITING_MINUTES));
40295
+ }
40296
+ return await backtest.strategyCoreService.getPositionWaitingMinutes(true, symbol, context);
40297
+ };
40078
40298
  /**
40079
40299
  * Returns the best price reached in the profit direction during this position's life.
40080
40300
  *
@@ -41716,6 +41936,8 @@ const LIVE_METHOD_NAME_GET_POSITION_PARTIALS = "LiveUtils.getPositionPartials";
41716
41936
  const LIVE_METHOD_NAME_GET_POSITION_ENTRIES = "LiveUtils.getPositionEntries";
41717
41937
  const LIVE_METHOD_NAME_GET_POSITION_ESTIMATE_MINUTES = "LiveUtils.getPositionEstimateMinutes";
41718
41938
  const LIVE_METHOD_NAME_GET_POSITION_COUNTDOWN_MINUTES = "LiveUtils.getPositionCountdownMinutes";
41939
+ const LIVE_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES = "LiveUtils.getPositionActiveMinutes";
41940
+ const LIVE_METHOD_NAME_GET_POSITION_WAITING_MINUTES = "LiveUtils.getPositionWaitingMinutes";
41719
41941
  const LIVE_METHOD_NAME_GET_POSITION_HIGHEST_PROFIT_PRICE = "LiveUtils.getPositionHighestProfitPrice";
41720
41942
  const LIVE_METHOD_NAME_GET_POSITION_HIGHEST_PROFIT_TIMESTAMP = "LiveUtils.getPositionHighestProfitTimestamp";
41721
41943
  const LIVE_METHOD_NAME_GET_POSITION_HIGHEST_PNL_PERCENTAGE = "LiveUtils.getPositionHighestPnlPercentage";
@@ -42750,6 +42972,68 @@ class LiveUtils {
42750
42972
  frameName: "",
42751
42973
  });
42752
42974
  };
42975
+ /**
42976
+ * Returns the number of minutes the position has been active since it opened.
42977
+ *
42978
+ * Returns null if no pending signal exists.
42979
+ *
42980
+ * @param symbol - Trading pair symbol
42981
+ * @param context - Execution context with strategyName and exchangeName
42982
+ * @returns Active minutes (≥ 0), or null if no active position
42983
+ */
42984
+ this.getPositionActiveMinutes = async (symbol, context) => {
42985
+ backtest.loggerService.info(LIVE_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES, {
42986
+ symbol,
42987
+ context,
42988
+ });
42989
+ backtest.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
42990
+ backtest.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
42991
+ {
42992
+ const { riskName, riskList, actions } = backtest.strategySchemaService.get(context.strategyName);
42993
+ riskName &&
42994
+ backtest.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
42995
+ riskList &&
42996
+ riskList.forEach((riskName) => backtest.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES));
42997
+ actions &&
42998
+ actions.forEach((actionName) => backtest.actionValidationService.validate(actionName, LIVE_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES));
42999
+ }
43000
+ return await backtest.strategyCoreService.getPositionActiveMinutes(false, symbol, {
43001
+ strategyName: context.strategyName,
43002
+ exchangeName: context.exchangeName,
43003
+ frameName: "",
43004
+ });
43005
+ };
43006
+ /**
43007
+ * Returns the number of minutes the scheduled signal has been waiting for activation.
43008
+ *
43009
+ * Returns null if no scheduled signal exists.
43010
+ *
43011
+ * @param symbol - Trading pair symbol
43012
+ * @param context - Execution context with strategyName and exchangeName
43013
+ * @returns Waiting minutes (≥ 0), or null if no scheduled signal
43014
+ */
43015
+ this.getPositionWaitingMinutes = async (symbol, context) => {
43016
+ backtest.loggerService.info(LIVE_METHOD_NAME_GET_POSITION_WAITING_MINUTES, {
43017
+ symbol,
43018
+ context,
43019
+ });
43020
+ backtest.strategyValidationService.validate(context.strategyName, LIVE_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
43021
+ backtest.exchangeValidationService.validate(context.exchangeName, LIVE_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
43022
+ {
43023
+ const { riskName, riskList, actions } = backtest.strategySchemaService.get(context.strategyName);
43024
+ riskName &&
43025
+ backtest.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
43026
+ riskList &&
43027
+ riskList.forEach((riskName) => backtest.riskValidationService.validate(riskName, LIVE_METHOD_NAME_GET_POSITION_WAITING_MINUTES));
43028
+ actions &&
43029
+ actions.forEach((actionName) => backtest.actionValidationService.validate(actionName, LIVE_METHOD_NAME_GET_POSITION_WAITING_MINUTES));
43030
+ }
43031
+ return await backtest.strategyCoreService.getPositionWaitingMinutes(false, symbol, {
43032
+ strategyName: context.strategyName,
43033
+ exchangeName: context.exchangeName,
43034
+ frameName: "",
43035
+ });
43036
+ };
42753
43037
  /**
42754
43038
  * Returns the best price reached in the profit direction during this position's life.
42755
43039
  *
@@ -48203,7 +48487,7 @@ const LOGGER_SERVICE$2 = new LoggerService();
48203
48487
  * Default configuration that enables all report services.
48204
48488
  * Used when no specific configuration is provided to enable().
48205
48489
  */
48206
- const WILDCARD_TARGET$1 = {
48490
+ const WILDCARD_TARGET$2 = {
48207
48491
  backtest: true,
48208
48492
  strategy: true,
48209
48493
  breakeven: true,
@@ -48254,7 +48538,7 @@ class ReportUtils {
48254
48538
  *
48255
48539
  * @returns Cleanup function that unsubscribes from all enabled services
48256
48540
  */
48257
- this.enable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, strategy = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
48541
+ this.enable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, strategy = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$2) => {
48258
48542
  LOGGER_SERVICE$2.debug(REPORT_UTILS_METHOD_NAME_ENABLE, {
48259
48543
  backtest: bt,
48260
48544
  breakeven,
@@ -48346,7 +48630,7 @@ class ReportUtils {
48346
48630
  * Report.disable();
48347
48631
  * ```
48348
48632
  */
48349
- this.disable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, strategy = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
48633
+ this.disable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, strategy = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$2) => {
48350
48634
  LOGGER_SERVICE$2.debug(REPORT_UTILS_METHOD_NAME_DISABLE, {
48351
48635
  backtest: bt,
48352
48636
  breakeven,
@@ -48470,7 +48754,7 @@ const LOGGER_SERVICE$1 = new LoggerService();
48470
48754
  * Default configuration that enables all markdown services.
48471
48755
  * Used when no specific configuration is provided to `enable()`.
48472
48756
  */
48473
- const WILDCARD_TARGET = {
48757
+ const WILDCARD_TARGET$1 = {
48474
48758
  backtest: true,
48475
48759
  breakeven: true,
48476
48760
  heat: true,
@@ -48521,7 +48805,7 @@ class MarkdownUtils {
48521
48805
  *
48522
48806
  * @returns Cleanup function that unsubscribes from all enabled services
48523
48807
  */
48524
- this.enable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, strategy = false, risk = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET) => {
48808
+ this.enable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, strategy = false, risk = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
48525
48809
  LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_ENABLE, {
48526
48810
  backtest: bt,
48527
48811
  breakeven,
@@ -48615,7 +48899,7 @@ class MarkdownUtils {
48615
48899
  * Markdown.disable();
48616
48900
  * ```
48617
48901
  */
48618
- this.disable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET) => {
48902
+ this.disable = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
48619
48903
  LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_DISABLE, {
48620
48904
  backtest: bt,
48621
48905
  breakeven,
@@ -48696,7 +48980,7 @@ class MarkdownUtils {
48696
48980
  * @param config.highest_profit - Clear highest profit report data
48697
48981
  * @param config.max_drawdown - Clear max drawdown report data
48698
48982
  */
48699
- this.clear = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET) => {
48983
+ this.clear = ({ backtest: bt = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, strategy = false, schedule = false, walker = false, sync = false, highest_profit = false, max_drawdown = false, } = WILDCARD_TARGET$1) => {
48700
48984
  LOGGER_SERVICE$1.debug(MARKDOWN_METHOD_NAME_CLEAR, {
48701
48985
  backtest: bt,
48702
48986
  breakeven,
@@ -51108,6 +51392,8 @@ const REFLECT_METHOD_NAME_GET_POSITION_HIGHEST_PROFIT_TIMESTAMP = "ReflectUtils.
51108
51392
  const REFLECT_METHOD_NAME_GET_POSITION_HIGHEST_PNL_PERCENTAGE = "ReflectUtils.getPositionHighestPnlPercentage";
51109
51393
  const REFLECT_METHOD_NAME_GET_POSITION_HIGHEST_PNL_COST = "ReflectUtils.getPositionHighestPnlCost";
51110
51394
  const REFLECT_METHOD_NAME_GET_POSITION_HIGHEST_PROFIT_BREAKEVEN = "ReflectUtils.getPositionHighestProfitBreakeven";
51395
+ const REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES = "ReflectUtils.getPositionActiveMinutes";
51396
+ const REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES = "ReflectUtils.getPositionWaitingMinutes";
51111
51397
  const REFLECT_METHOD_NAME_GET_POSITION_DRAWDOWN_MINUTES = "ReflectUtils.getPositionDrawdownMinutes";
51112
51398
  const REFLECT_METHOD_NAME_GET_POSITION_HIGHEST_PROFIT_MINUTES = "ReflectUtils.getPositionHighestProfitMinutes";
51113
51399
  const REFLECT_METHOD_NAME_GET_POSITION_MAX_DRAWDOWN_MINUTES = "ReflectUtils.getPositionMaxDrawdownMinutes";
@@ -51382,6 +51668,52 @@ class ReflectUtils {
51382
51668
  }
51383
51669
  return await backtest.strategyCoreService.getPositionHighestProfitBreakeven(backtest$1, symbol, context);
51384
51670
  };
51671
+ /**
51672
+ * Returns the number of minutes the position has been active since it opened.
51673
+ *
51674
+ * Returns null if no pending signal exists.
51675
+ *
51676
+ * @param symbol - Trading pair symbol
51677
+ * @param context - Execution context with strategyName, exchangeName and frameName
51678
+ * @param backtest - True if backtest mode, false if live mode (default: false)
51679
+ * @returns Promise resolving to active minutes (≥ 0) or null
51680
+ */
51681
+ this.getPositionActiveMinutes = async (symbol, context, backtest$1 = false) => {
51682
+ backtest.loggerService.info(REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES, { symbol, context });
51683
+ backtest.strategyValidationService.validate(context.strategyName, REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
51684
+ backtest.exchangeValidationService.validate(context.exchangeName, REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
51685
+ context.frameName && backtest.frameValidationService.validate(context.frameName, REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
51686
+ {
51687
+ const { riskName, riskList, actions } = backtest.strategySchemaService.get(context.strategyName);
51688
+ riskName && backtest.riskValidationService.validate(riskName, REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES);
51689
+ riskList && riskList.forEach((riskName) => backtest.riskValidationService.validate(riskName, REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES));
51690
+ actions && actions.forEach((actionName) => backtest.actionValidationService.validate(actionName, REFLECT_METHOD_NAME_GET_POSITION_ACTIVE_MINUTES));
51691
+ }
51692
+ return await backtest.strategyCoreService.getPositionActiveMinutes(backtest$1, symbol, context);
51693
+ };
51694
+ /**
51695
+ * Returns the number of minutes the scheduled signal has been waiting for activation.
51696
+ *
51697
+ * Returns null if no scheduled signal exists.
51698
+ *
51699
+ * @param symbol - Trading pair symbol
51700
+ * @param context - Execution context with strategyName, exchangeName and frameName
51701
+ * @param backtest - True if backtest mode, false if live mode (default: false)
51702
+ * @returns Promise resolving to waiting minutes (≥ 0) or null
51703
+ */
51704
+ this.getPositionWaitingMinutes = async (symbol, context, backtest$1 = false) => {
51705
+ backtest.loggerService.info(REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES, { symbol, context });
51706
+ backtest.strategyValidationService.validate(context.strategyName, REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
51707
+ backtest.exchangeValidationService.validate(context.exchangeName, REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
51708
+ context.frameName && backtest.frameValidationService.validate(context.frameName, REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
51709
+ {
51710
+ const { riskName, riskList, actions } = backtest.strategySchemaService.get(context.strategyName);
51711
+ riskName && backtest.riskValidationService.validate(riskName, REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES);
51712
+ riskList && riskList.forEach((riskName) => backtest.riskValidationService.validate(riskName, REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES));
51713
+ actions && actions.forEach((actionName) => backtest.actionValidationService.validate(actionName, REFLECT_METHOD_NAME_GET_POSITION_WAITING_MINUTES));
51714
+ }
51715
+ return await backtest.strategyCoreService.getPositionWaitingMinutes(backtest$1, symbol, context);
51716
+ };
51385
51717
  /**
51386
51718
  * Returns the number of minutes elapsed since the highest profit price was recorded.
51387
51719
  *
@@ -53658,6 +53990,23 @@ const StorageLive = new StorageLiveAdapter();
53658
53990
  */
53659
53991
  const StorageBacktest = new StorageBacktestAdapter();
53660
53992
 
53993
+ /**
53994
+ * Default configuration that enables all notification types.
53995
+ * Used when no specific configuration is provided to enable().
53996
+ */
53997
+ const WILDCARD_TARGET = {
53998
+ signal: true,
53999
+ partial_profit: true,
54000
+ partial_loss: true,
54001
+ breakeven: true,
54002
+ strategy_commit: true,
54003
+ signal_sync: true,
54004
+ risk: true,
54005
+ info: true,
54006
+ common_error: true,
54007
+ critical_error: true,
54008
+ validation_error: true,
54009
+ };
53661
54010
  /**
53662
54011
  * Generates a unique key for notification identification.
53663
54012
  * @returns Random string identifier
@@ -55713,64 +56062,152 @@ class NotificationAdapter {
55713
56062
  *
55714
56063
  * @returns Cleanup function that unsubscribes from all emitters
55715
56064
  */
55716
- this.enable = functoolsKit.singleshot(() => {
56065
+ this.enable = functoolsKit.singleshot(({ signal = false, info = false, partial_profit = false, partial_loss = false, breakeven = false, strategy_commit = false, signal_sync = false, risk = false, common_error = false, critical_error = false, validation_error = false, } = WILDCARD_TARGET) => {
55717
56066
  backtest.loggerService.info(NOTIFICATION_ADAPTER_METHOD_NAME_ENABLE);
55718
56067
  let unLive;
55719
56068
  let unBacktest;
55720
56069
  {
55721
- const unBacktestSignal = signalBacktestEmitter.subscribe((data) => NotificationBacktest.handleSignal(data));
56070
+ const unBacktestSignal = signalBacktestEmitter.subscribe(async (data) => {
56071
+ if (signal) {
56072
+ await NotificationBacktest.handleSignal(data);
56073
+ }
56074
+ });
55722
56075
  const unBacktestPartialProfit = partialProfitSubject
55723
56076
  .filter(({ backtest }) => backtest)
55724
- .connect((data) => NotificationBacktest.handlePartialProfit(data));
56077
+ .connect(async (data) => {
56078
+ if (partial_profit) {
56079
+ await NotificationBacktest.handlePartialProfit(data);
56080
+ }
56081
+ });
55725
56082
  const unBacktestPartialLoss = partialLossSubject
55726
56083
  .filter(({ backtest }) => backtest)
55727
- .connect((data) => NotificationBacktest.handlePartialLoss(data));
56084
+ .connect(async (data) => {
56085
+ if (partial_loss) {
56086
+ await NotificationBacktest.handlePartialLoss(data);
56087
+ }
56088
+ });
55728
56089
  const unBacktestBreakeven = breakevenSubject
55729
56090
  .filter(({ backtest }) => backtest)
55730
- .connect((data) => NotificationBacktest.handleBreakeven(data));
56091
+ .connect(async (data) => {
56092
+ if (breakeven) {
56093
+ await NotificationBacktest.handleBreakeven(data);
56094
+ }
56095
+ });
55731
56096
  const unBacktestStrategyCommit = strategyCommitSubject
55732
56097
  .filter(({ backtest }) => backtest)
55733
- .connect((data) => NotificationBacktest.handleStrategyCommit(data));
56098
+ .connect(async (data) => {
56099
+ if (strategy_commit) {
56100
+ await NotificationBacktest.handleStrategyCommit(data);
56101
+ }
56102
+ });
55734
56103
  const unBacktestSync = syncSubject
55735
56104
  .filter(({ backtest }) => backtest)
55736
- .connect((data) => NotificationBacktest.handleSync(data));
56105
+ .connect(async (data) => {
56106
+ if (signal_sync) {
56107
+ await NotificationBacktest.handleSync(data);
56108
+ }
56109
+ });
55737
56110
  const unBacktestRisk = riskSubject
55738
56111
  .filter(({ backtest }) => backtest)
55739
- .connect((data) => NotificationBacktest.handleRisk(data));
55740
- const unBacktestError = errorEmitter.subscribe((error) => NotificationBacktest.handleError(error));
55741
- const unBacktestExit = exitEmitter.subscribe((error) => NotificationBacktest.handleCriticalError(error));
55742
- const unBacktestValidation = validationSubject.subscribe((error) => NotificationBacktest.handleValidationError(error));
56112
+ .connect(async (data) => {
56113
+ if (risk) {
56114
+ await NotificationBacktest.handleRisk(data);
56115
+ }
56116
+ });
56117
+ const unBacktestError = errorEmitter.subscribe(async (error) => {
56118
+ if (common_error) {
56119
+ await NotificationBacktest.handleError(error);
56120
+ }
56121
+ });
56122
+ const unBacktestExit = exitEmitter.subscribe(async (error) => {
56123
+ if (critical_error) {
56124
+ await NotificationBacktest.handleCriticalError(error);
56125
+ }
56126
+ });
56127
+ const unBacktestValidation = validationSubject.subscribe(async (error) => {
56128
+ if (validation_error) {
56129
+ await NotificationBacktest.handleValidationError(error);
56130
+ }
56131
+ });
55743
56132
  const unBacktestSignalNotify = signalNotifySubject
55744
56133
  .filter(({ backtest }) => backtest)
55745
- .connect((data) => NotificationBacktest.handleSignalNotify(data));
56134
+ .connect(async (data) => {
56135
+ if (info) {
56136
+ await NotificationBacktest.handleSignalNotify(data);
56137
+ }
56138
+ });
55746
56139
  unBacktest = functoolsKit.compose(() => unBacktestSignal(), () => unBacktestPartialProfit(), () => unBacktestPartialLoss(), () => unBacktestBreakeven(), () => unBacktestStrategyCommit(), () => unBacktestSync(), () => unBacktestRisk(), () => unBacktestError(), () => unBacktestExit(), () => unBacktestValidation(), () => unBacktestSignalNotify());
55747
56140
  }
55748
56141
  {
55749
- const unLiveSignal = signalLiveEmitter.subscribe((data) => NotificationLive.handleSignal(data));
56142
+ const unLiveSignal = signalLiveEmitter.subscribe(async (data) => {
56143
+ if (signal) {
56144
+ await NotificationLive.handleSignal(data);
56145
+ }
56146
+ });
55750
56147
  const unLivePartialProfit = partialProfitSubject
55751
56148
  .filter(({ backtest }) => !backtest)
55752
- .connect((data) => NotificationLive.handlePartialProfit(data));
56149
+ .connect(async (data) => {
56150
+ if (partial_profit) {
56151
+ await NotificationLive.handlePartialProfit(data);
56152
+ }
56153
+ });
55753
56154
  const unLivePartialLoss = partialLossSubject
55754
56155
  .filter(({ backtest }) => !backtest)
55755
- .connect((data) => NotificationLive.handlePartialLoss(data));
56156
+ .connect(async (data) => {
56157
+ if (partial_loss) {
56158
+ await NotificationLive.handlePartialLoss(data);
56159
+ }
56160
+ });
55756
56161
  const unLiveBreakeven = breakevenSubject
55757
56162
  .filter(({ backtest }) => !backtest)
55758
- .connect((data) => NotificationLive.handleBreakeven(data));
56163
+ .connect(async (data) => {
56164
+ if (breakeven) {
56165
+ await NotificationLive.handleBreakeven(data);
56166
+ }
56167
+ });
55759
56168
  const unLiveStrategyCommit = strategyCommitSubject
55760
56169
  .filter(({ backtest }) => !backtest)
55761
- .connect((data) => NotificationLive.handleStrategyCommit(data));
56170
+ .connect(async (data) => {
56171
+ if (strategy_commit) {
56172
+ await NotificationLive.handleStrategyCommit(data);
56173
+ }
56174
+ });
55762
56175
  const unLiveSync = syncSubject
55763
56176
  .filter(({ backtest }) => !backtest)
55764
- .connect((data) => NotificationLive.handleSync(data));
56177
+ .connect(async (data) => {
56178
+ if (signal_sync) {
56179
+ await NotificationLive.handleSync(data);
56180
+ }
56181
+ });
55765
56182
  const unLiveRisk = riskSubject
55766
56183
  .filter(({ backtest }) => !backtest)
55767
- .connect((data) => NotificationLive.handleRisk(data));
55768
- const unLiveError = errorEmitter.subscribe((error) => NotificationLive.handleError(error));
55769
- const unLiveExit = exitEmitter.subscribe((error) => NotificationLive.handleCriticalError(error));
55770
- const unLiveValidation = validationSubject.subscribe((error) => NotificationLive.handleValidationError(error));
56184
+ .connect(async (data) => {
56185
+ if (risk) {
56186
+ await NotificationLive.handleRisk(data);
56187
+ }
56188
+ });
56189
+ const unLiveError = errorEmitter.subscribe(async (error) => {
56190
+ if (common_error) {
56191
+ await NotificationLive.handleError(error);
56192
+ }
56193
+ });
56194
+ const unLiveExit = exitEmitter.subscribe(async (error) => {
56195
+ if (critical_error) {
56196
+ await NotificationLive.handleCriticalError(error);
56197
+ }
56198
+ });
56199
+ const unLiveValidation = validationSubject.subscribe(async (error) => {
56200
+ if (validation_error) {
56201
+ await NotificationLive.handleValidationError(error);
56202
+ }
56203
+ });
55771
56204
  const unLiveSignalNotify = signalNotifySubject
55772
56205
  .filter(({ backtest }) => !backtest)
55773
- .connect((data) => NotificationLive.handleSignalNotify(data));
56206
+ .connect(async (data) => {
56207
+ if (info) {
56208
+ await NotificationLive.handleSignalNotify(data);
56209
+ }
56210
+ });
55774
56211
  unLive = functoolsKit.compose(() => unLiveSignal(), () => unLivePartialProfit(), () => unLivePartialLoss(), () => unLiveBreakeven(), () => unLiveStrategyCommit(), () => unLiveSync(), () => unLiveRisk(), () => unLiveError(), () => unLiveExit(), () => unLiveValidation(), () => unLiveSignalNotify());
55775
56212
  }
55776
56213
  return () => {
@@ -58275,6 +58712,7 @@ exports.getMode = getMode;
58275
58712
  exports.getNextCandles = getNextCandles;
58276
58713
  exports.getOrderBook = getOrderBook;
58277
58714
  exports.getPendingSignal = getPendingSignal;
58715
+ exports.getPositionActiveMinutes = getPositionActiveMinutes;
58278
58716
  exports.getPositionCountdownMinutes = getPositionCountdownMinutes;
58279
58717
  exports.getPositionDrawdownMinutes = getPositionDrawdownMinutes;
58280
58718
  exports.getPositionEffectivePrice = getPositionEffectivePrice;
@@ -58303,6 +58741,7 @@ exports.getPositionPartialOverlap = getPositionPartialOverlap;
58303
58741
  exports.getPositionPartials = getPositionPartials;
58304
58742
  exports.getPositionPnlCost = getPositionPnlCost;
58305
58743
  exports.getPositionPnlPercent = getPositionPnlPercent;
58744
+ exports.getPositionWaitingMinutes = getPositionWaitingMinutes;
58306
58745
  exports.getRawCandles = getRawCandles;
58307
58746
  exports.getRiskSchema = getRiskSchema;
58308
58747
  exports.getScheduledSignal = getScheduledSignal;