backtest-kit 1.3.0 → 1.3.2

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
@@ -1430,6 +1430,11 @@ const walkerEmitter = new functoolsKit.Subject();
1430
1430
  * Emits when all strategies have been tested and final results are available.
1431
1431
  */
1432
1432
  const walkerCompleteSubject = new functoolsKit.Subject();
1433
+ /**
1434
+ * Walker stop emitter for walker cancellation events.
1435
+ * Emits when a walker comparison is stopped/cancelled.
1436
+ */
1437
+ const walkerStopSubject = new functoolsKit.Subject();
1433
1438
  /**
1434
1439
  * Validation emitter for risk validation errors.
1435
1440
  * Emits when risk validation functions throw errors during signal checking.
@@ -1449,7 +1454,8 @@ var emitters = /*#__PURE__*/Object.freeze({
1449
1454
  signalLiveEmitter: signalLiveEmitter,
1450
1455
  validationSubject: validationSubject,
1451
1456
  walkerCompleteSubject: walkerCompleteSubject,
1452
- walkerEmitter: walkerEmitter
1457
+ walkerEmitter: walkerEmitter,
1458
+ walkerStopSubject: walkerStopSubject
1453
1459
  });
1454
1460
 
1455
1461
  const INTERVAL_MINUTES$1 = {
@@ -1625,6 +1631,9 @@ const GET_SIGNAL_FN = functoolsKit.trycatch(async (self) => {
1625
1631
  if (!signal) {
1626
1632
  return null;
1627
1633
  }
1634
+ if (self._isStopped) {
1635
+ return null;
1636
+ }
1628
1637
  // Если priceOpen указан - проверяем нужно ли ждать активации или открыть сразу
1629
1638
  if (signal.priceOpen !== undefined) {
1630
1639
  // КРИТИЧЕСКАЯ ПРОВЕРКА: достигнут ли priceOpen?
@@ -2351,6 +2360,14 @@ class ClientStrategy {
2351
2360
  }
2352
2361
  await PersistSignalAdapter.writeSignalData(this._pendingSignal, this.params.strategyName, this.params.execution.context.symbol);
2353
2362
  }
2363
+ /**
2364
+ * Retrieves the current pending signal.
2365
+ * If no signal is pending, returns null.
2366
+ * @returns Promise resolving to the pending signal or null.
2367
+ */
2368
+ async getPendingSignal() {
2369
+ return this._pendingSignal;
2370
+ }
2354
2371
  /**
2355
2372
  * Performs a single tick of strategy execution.
2356
2373
  *
@@ -2656,6 +2673,20 @@ class StrategyConnectionService {
2656
2673
  callbacks,
2657
2674
  });
2658
2675
  });
2676
+ /**
2677
+ * Retrieves the currently active pending signal for the strategy.
2678
+ * If no active signal exists, returns null.
2679
+ * Used internally for monitoring TP/SL and time expiration.
2680
+ *
2681
+ * @param strategyName - Name of strategy to get pending signal for
2682
+ *
2683
+ * @returns Promise resolving to pending signal or null
2684
+ */
2685
+ this.getPendingSignal = async (strategyName) => {
2686
+ this.loggerService.log("strategyConnectionService getPendingSignal");
2687
+ const strategy = await this.getStrategy(strategyName);
2688
+ return await strategy.getPendingSignal();
2689
+ };
2659
2690
  /**
2660
2691
  * Executes live trading tick for current strategy.
2661
2692
  *
@@ -3558,6 +3589,23 @@ class StrategyGlobalService {
3558
3589
  riskName &&
3559
3590
  this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
3560
3591
  });
3592
+ /**
3593
+ * Retrieves the currently active pending signal for the symbol.
3594
+ * If no active signal exists, returns null.
3595
+ * Used internally for monitoring TP/SL and time expiration.
3596
+ *
3597
+ * @param symbol - Trading pair symbol
3598
+ * @param when - Timestamp for tick evaluation
3599
+ * @param backtest - Whether running in backtest mode
3600
+ * @returns Promise resolving to pending signal or null
3601
+ */
3602
+ this.getPendingSignal = async (strategyName) => {
3603
+ this.loggerService.log("strategyGlobalService getPendingSignal", {
3604
+ strategyName,
3605
+ });
3606
+ await this.validate(this.methodContextService.context.strategyName);
3607
+ return await this.strategyConnectionService.getPendingSignal(strategyName);
3608
+ };
3561
3609
  /**
3562
3610
  * Checks signal status at a specific timestamp.
3563
3611
  *
@@ -4560,6 +4608,7 @@ class LiveLogicPrivateService {
4560
4608
  }
4561
4609
  }
4562
4610
 
4611
+ const CANCEL_SYMBOL = Symbol("CANCEL_SYMBOL");
4563
4612
  /**
4564
4613
  * Private service for walker orchestration (strategy comparison).
4565
4614
  *
@@ -4617,6 +4666,10 @@ class WalkerLogicPrivateService {
4617
4666
  let strategiesTested = 0;
4618
4667
  let bestMetric = null;
4619
4668
  let bestStrategy = null;
4669
+ const listenStop = walkerStopSubject
4670
+ .filter((walkerName) => walkerName === context.walkerName)
4671
+ .map(() => CANCEL_SYMBOL)
4672
+ .toPromise();
4620
4673
  // Run backtest for each strategy
4621
4674
  for (const strategyName of strategies) {
4622
4675
  // Call onStrategyStart callback if provided
@@ -4632,7 +4685,16 @@ class WalkerLogicPrivateService {
4632
4685
  exchangeName: context.exchangeName,
4633
4686
  frameName: context.frameName,
4634
4687
  });
4635
- await functoolsKit.resolveDocuments(iterator);
4688
+ const result = await Promise.race([
4689
+ await functoolsKit.resolveDocuments(iterator),
4690
+ listenStop,
4691
+ ]);
4692
+ if (result === CANCEL_SYMBOL) {
4693
+ this.loggerService.info("walkerLogicPrivateService received stop signal, cancelling walker", {
4694
+ context,
4695
+ });
4696
+ break;
4697
+ }
4636
4698
  this.loggerService.info("walkerLogicPrivateService backtest complete", {
4637
4699
  strategyName,
4638
4700
  symbol,
@@ -9296,22 +9358,42 @@ class BacktestUtils {
9296
9358
  context,
9297
9359
  });
9298
9360
  let isStopped = false;
9361
+ let isDone = false;
9299
9362
  const task = async () => {
9300
9363
  for await (const _ of this.run(symbol, context)) {
9301
9364
  if (isStopped) {
9302
9365
  break;
9303
9366
  }
9304
9367
  }
9305
- await doneBacktestSubject.next({
9306
- exchangeName: context.exchangeName,
9307
- strategyName: context.strategyName,
9308
- backtest: true,
9309
- symbol,
9310
- });
9368
+ if (!isDone) {
9369
+ await doneBacktestSubject.next({
9370
+ exchangeName: context.exchangeName,
9371
+ strategyName: context.strategyName,
9372
+ backtest: true,
9373
+ symbol,
9374
+ });
9375
+ }
9376
+ isDone = true;
9311
9377
  };
9312
9378
  task().catch((error) => errorEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
9313
9379
  return () => {
9314
9380
  backtest$1.strategyGlobalService.stop(context.strategyName);
9381
+ backtest$1.strategyGlobalService
9382
+ .getPendingSignal(context.strategyName)
9383
+ .then(async (pendingSignal) => {
9384
+ if (pendingSignal) {
9385
+ return;
9386
+ }
9387
+ if (!isDone) {
9388
+ await doneBacktestSubject.next({
9389
+ exchangeName: context.exchangeName,
9390
+ strategyName: context.strategyName,
9391
+ backtest: true,
9392
+ symbol,
9393
+ });
9394
+ }
9395
+ isDone = true;
9396
+ });
9315
9397
  isStopped = true;
9316
9398
  };
9317
9399
  };
@@ -9485,22 +9567,42 @@ class LiveUtils {
9485
9567
  context,
9486
9568
  });
9487
9569
  let isStopped = false;
9570
+ let isDone = false;
9488
9571
  const task = async () => {
9489
9572
  for await (const signal of this.run(symbol, context)) {
9490
9573
  if (signal?.action === "closed" && isStopped) {
9491
9574
  break;
9492
9575
  }
9493
9576
  }
9494
- await doneLiveSubject.next({
9495
- exchangeName: context.exchangeName,
9496
- strategyName: context.strategyName,
9497
- backtest: false,
9498
- symbol,
9499
- });
9577
+ if (!isDone) {
9578
+ await doneLiveSubject.next({
9579
+ exchangeName: context.exchangeName,
9580
+ strategyName: context.strategyName,
9581
+ backtest: false,
9582
+ symbol,
9583
+ });
9584
+ }
9585
+ isDone = true;
9500
9586
  };
9501
9587
  task().catch((error) => errorEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
9502
9588
  return () => {
9503
9589
  backtest$1.strategyGlobalService.stop(context.strategyName);
9590
+ backtest$1.strategyGlobalService
9591
+ .getPendingSignal(context.strategyName)
9592
+ .then(async (pendingSignal) => {
9593
+ if (pendingSignal) {
9594
+ return;
9595
+ }
9596
+ if (!isDone) {
9597
+ await doneLiveSubject.next({
9598
+ exchangeName: context.exchangeName,
9599
+ strategyName: context.strategyName,
9600
+ backtest: false,
9601
+ symbol,
9602
+ });
9603
+ }
9604
+ isDone = true;
9605
+ });
9504
9606
  isStopped = true;
9505
9607
  };
9506
9608
  };
@@ -9926,25 +10028,39 @@ class WalkerUtils {
9926
10028
  });
9927
10029
  const walkerSchema = backtest$1.walkerSchemaService.get(context.walkerName);
9928
10030
  let isStopped = false;
10031
+ let isDone = false;
9929
10032
  const task = async () => {
9930
10033
  for await (const _ of this.run(symbol, context)) {
9931
10034
  if (isStopped) {
9932
10035
  break;
9933
10036
  }
9934
10037
  }
9935
- await doneWalkerSubject.next({
9936
- exchangeName: walkerSchema.exchangeName,
9937
- strategyName: context.walkerName,
9938
- backtest: true,
9939
- symbol,
9940
- });
10038
+ if (!isDone) {
10039
+ await doneWalkerSubject.next({
10040
+ exchangeName: walkerSchema.exchangeName,
10041
+ strategyName: context.walkerName,
10042
+ backtest: true,
10043
+ symbol,
10044
+ });
10045
+ }
10046
+ isDone = true;
9941
10047
  };
9942
10048
  task().catch((error) => errorEmitter.next(new Error(functoolsKit.getErrorMessage(error))));
9943
10049
  return () => {
9944
- isStopped = true;
9945
10050
  for (const strategyName of walkerSchema.strategies) {
9946
10051
  backtest$1.strategyGlobalService.stop(strategyName);
9947
10052
  }
10053
+ walkerStopSubject.next(context.walkerName);
10054
+ if (!isDone) {
10055
+ doneWalkerSubject.next({
10056
+ exchangeName: walkerSchema.exchangeName,
10057
+ strategyName: context.walkerName,
10058
+ backtest: true,
10059
+ symbol,
10060
+ });
10061
+ }
10062
+ isDone = true;
10063
+ isStopped = true;
9948
10064
  };
9949
10065
  };
9950
10066
  /**
package/build/index.mjs CHANGED
@@ -1428,6 +1428,11 @@ const walkerEmitter = new Subject();
1428
1428
  * Emits when all strategies have been tested and final results are available.
1429
1429
  */
1430
1430
  const walkerCompleteSubject = new Subject();
1431
+ /**
1432
+ * Walker stop emitter for walker cancellation events.
1433
+ * Emits when a walker comparison is stopped/cancelled.
1434
+ */
1435
+ const walkerStopSubject = new Subject();
1431
1436
  /**
1432
1437
  * Validation emitter for risk validation errors.
1433
1438
  * Emits when risk validation functions throw errors during signal checking.
@@ -1447,7 +1452,8 @@ var emitters = /*#__PURE__*/Object.freeze({
1447
1452
  signalLiveEmitter: signalLiveEmitter,
1448
1453
  validationSubject: validationSubject,
1449
1454
  walkerCompleteSubject: walkerCompleteSubject,
1450
- walkerEmitter: walkerEmitter
1455
+ walkerEmitter: walkerEmitter,
1456
+ walkerStopSubject: walkerStopSubject
1451
1457
  });
1452
1458
 
1453
1459
  const INTERVAL_MINUTES$1 = {
@@ -1623,6 +1629,9 @@ const GET_SIGNAL_FN = trycatch(async (self) => {
1623
1629
  if (!signal) {
1624
1630
  return null;
1625
1631
  }
1632
+ if (self._isStopped) {
1633
+ return null;
1634
+ }
1626
1635
  // Если priceOpen указан - проверяем нужно ли ждать активации или открыть сразу
1627
1636
  if (signal.priceOpen !== undefined) {
1628
1637
  // КРИТИЧЕСКАЯ ПРОВЕРКА: достигнут ли priceOpen?
@@ -2349,6 +2358,14 @@ class ClientStrategy {
2349
2358
  }
2350
2359
  await PersistSignalAdapter.writeSignalData(this._pendingSignal, this.params.strategyName, this.params.execution.context.symbol);
2351
2360
  }
2361
+ /**
2362
+ * Retrieves the current pending signal.
2363
+ * If no signal is pending, returns null.
2364
+ * @returns Promise resolving to the pending signal or null.
2365
+ */
2366
+ async getPendingSignal() {
2367
+ return this._pendingSignal;
2368
+ }
2352
2369
  /**
2353
2370
  * Performs a single tick of strategy execution.
2354
2371
  *
@@ -2654,6 +2671,20 @@ class StrategyConnectionService {
2654
2671
  callbacks,
2655
2672
  });
2656
2673
  });
2674
+ /**
2675
+ * Retrieves the currently active pending signal for the strategy.
2676
+ * If no active signal exists, returns null.
2677
+ * Used internally for monitoring TP/SL and time expiration.
2678
+ *
2679
+ * @param strategyName - Name of strategy to get pending signal for
2680
+ *
2681
+ * @returns Promise resolving to pending signal or null
2682
+ */
2683
+ this.getPendingSignal = async (strategyName) => {
2684
+ this.loggerService.log("strategyConnectionService getPendingSignal");
2685
+ const strategy = await this.getStrategy(strategyName);
2686
+ return await strategy.getPendingSignal();
2687
+ };
2657
2688
  /**
2658
2689
  * Executes live trading tick for current strategy.
2659
2690
  *
@@ -3556,6 +3587,23 @@ class StrategyGlobalService {
3556
3587
  riskName &&
3557
3588
  this.riskValidationService.validate(riskName, METHOD_NAME_VALIDATE);
3558
3589
  });
3590
+ /**
3591
+ * Retrieves the currently active pending signal for the symbol.
3592
+ * If no active signal exists, returns null.
3593
+ * Used internally for monitoring TP/SL and time expiration.
3594
+ *
3595
+ * @param symbol - Trading pair symbol
3596
+ * @param when - Timestamp for tick evaluation
3597
+ * @param backtest - Whether running in backtest mode
3598
+ * @returns Promise resolving to pending signal or null
3599
+ */
3600
+ this.getPendingSignal = async (strategyName) => {
3601
+ this.loggerService.log("strategyGlobalService getPendingSignal", {
3602
+ strategyName,
3603
+ });
3604
+ await this.validate(this.methodContextService.context.strategyName);
3605
+ return await this.strategyConnectionService.getPendingSignal(strategyName);
3606
+ };
3559
3607
  /**
3560
3608
  * Checks signal status at a specific timestamp.
3561
3609
  *
@@ -4558,6 +4606,7 @@ class LiveLogicPrivateService {
4558
4606
  }
4559
4607
  }
4560
4608
 
4609
+ const CANCEL_SYMBOL = Symbol("CANCEL_SYMBOL");
4561
4610
  /**
4562
4611
  * Private service for walker orchestration (strategy comparison).
4563
4612
  *
@@ -4615,6 +4664,10 @@ class WalkerLogicPrivateService {
4615
4664
  let strategiesTested = 0;
4616
4665
  let bestMetric = null;
4617
4666
  let bestStrategy = null;
4667
+ const listenStop = walkerStopSubject
4668
+ .filter((walkerName) => walkerName === context.walkerName)
4669
+ .map(() => CANCEL_SYMBOL)
4670
+ .toPromise();
4618
4671
  // Run backtest for each strategy
4619
4672
  for (const strategyName of strategies) {
4620
4673
  // Call onStrategyStart callback if provided
@@ -4630,7 +4683,16 @@ class WalkerLogicPrivateService {
4630
4683
  exchangeName: context.exchangeName,
4631
4684
  frameName: context.frameName,
4632
4685
  });
4633
- await resolveDocuments(iterator);
4686
+ const result = await Promise.race([
4687
+ await resolveDocuments(iterator),
4688
+ listenStop,
4689
+ ]);
4690
+ if (result === CANCEL_SYMBOL) {
4691
+ this.loggerService.info("walkerLogicPrivateService received stop signal, cancelling walker", {
4692
+ context,
4693
+ });
4694
+ break;
4695
+ }
4634
4696
  this.loggerService.info("walkerLogicPrivateService backtest complete", {
4635
4697
  strategyName,
4636
4698
  symbol,
@@ -9294,22 +9356,42 @@ class BacktestUtils {
9294
9356
  context,
9295
9357
  });
9296
9358
  let isStopped = false;
9359
+ let isDone = false;
9297
9360
  const task = async () => {
9298
9361
  for await (const _ of this.run(symbol, context)) {
9299
9362
  if (isStopped) {
9300
9363
  break;
9301
9364
  }
9302
9365
  }
9303
- await doneBacktestSubject.next({
9304
- exchangeName: context.exchangeName,
9305
- strategyName: context.strategyName,
9306
- backtest: true,
9307
- symbol,
9308
- });
9366
+ if (!isDone) {
9367
+ await doneBacktestSubject.next({
9368
+ exchangeName: context.exchangeName,
9369
+ strategyName: context.strategyName,
9370
+ backtest: true,
9371
+ symbol,
9372
+ });
9373
+ }
9374
+ isDone = true;
9309
9375
  };
9310
9376
  task().catch((error) => errorEmitter.next(new Error(getErrorMessage(error))));
9311
9377
  return () => {
9312
9378
  backtest$1.strategyGlobalService.stop(context.strategyName);
9379
+ backtest$1.strategyGlobalService
9380
+ .getPendingSignal(context.strategyName)
9381
+ .then(async (pendingSignal) => {
9382
+ if (pendingSignal) {
9383
+ return;
9384
+ }
9385
+ if (!isDone) {
9386
+ await doneBacktestSubject.next({
9387
+ exchangeName: context.exchangeName,
9388
+ strategyName: context.strategyName,
9389
+ backtest: true,
9390
+ symbol,
9391
+ });
9392
+ }
9393
+ isDone = true;
9394
+ });
9313
9395
  isStopped = true;
9314
9396
  };
9315
9397
  };
@@ -9483,22 +9565,42 @@ class LiveUtils {
9483
9565
  context,
9484
9566
  });
9485
9567
  let isStopped = false;
9568
+ let isDone = false;
9486
9569
  const task = async () => {
9487
9570
  for await (const signal of this.run(symbol, context)) {
9488
9571
  if (signal?.action === "closed" && isStopped) {
9489
9572
  break;
9490
9573
  }
9491
9574
  }
9492
- await doneLiveSubject.next({
9493
- exchangeName: context.exchangeName,
9494
- strategyName: context.strategyName,
9495
- backtest: false,
9496
- symbol,
9497
- });
9575
+ if (!isDone) {
9576
+ await doneLiveSubject.next({
9577
+ exchangeName: context.exchangeName,
9578
+ strategyName: context.strategyName,
9579
+ backtest: false,
9580
+ symbol,
9581
+ });
9582
+ }
9583
+ isDone = true;
9498
9584
  };
9499
9585
  task().catch((error) => errorEmitter.next(new Error(getErrorMessage(error))));
9500
9586
  return () => {
9501
9587
  backtest$1.strategyGlobalService.stop(context.strategyName);
9588
+ backtest$1.strategyGlobalService
9589
+ .getPendingSignal(context.strategyName)
9590
+ .then(async (pendingSignal) => {
9591
+ if (pendingSignal) {
9592
+ return;
9593
+ }
9594
+ if (!isDone) {
9595
+ await doneLiveSubject.next({
9596
+ exchangeName: context.exchangeName,
9597
+ strategyName: context.strategyName,
9598
+ backtest: false,
9599
+ symbol,
9600
+ });
9601
+ }
9602
+ isDone = true;
9603
+ });
9502
9604
  isStopped = true;
9503
9605
  };
9504
9606
  };
@@ -9924,25 +10026,39 @@ class WalkerUtils {
9924
10026
  });
9925
10027
  const walkerSchema = backtest$1.walkerSchemaService.get(context.walkerName);
9926
10028
  let isStopped = false;
10029
+ let isDone = false;
9927
10030
  const task = async () => {
9928
10031
  for await (const _ of this.run(symbol, context)) {
9929
10032
  if (isStopped) {
9930
10033
  break;
9931
10034
  }
9932
10035
  }
9933
- await doneWalkerSubject.next({
9934
- exchangeName: walkerSchema.exchangeName,
9935
- strategyName: context.walkerName,
9936
- backtest: true,
9937
- symbol,
9938
- });
10036
+ if (!isDone) {
10037
+ await doneWalkerSubject.next({
10038
+ exchangeName: walkerSchema.exchangeName,
10039
+ strategyName: context.walkerName,
10040
+ backtest: true,
10041
+ symbol,
10042
+ });
10043
+ }
10044
+ isDone = true;
9939
10045
  };
9940
10046
  task().catch((error) => errorEmitter.next(new Error(getErrorMessage(error))));
9941
10047
  return () => {
9942
- isStopped = true;
9943
10048
  for (const strategyName of walkerSchema.strategies) {
9944
10049
  backtest$1.strategyGlobalService.stop(strategyName);
9945
10050
  }
10051
+ walkerStopSubject.next(context.walkerName);
10052
+ if (!isDone) {
10053
+ doneWalkerSubject.next({
10054
+ exchangeName: walkerSchema.exchangeName,
10055
+ strategyName: context.walkerName,
10056
+ backtest: true,
10057
+ symbol,
10058
+ });
10059
+ }
10060
+ isDone = true;
10061
+ isStopped = true;
9946
10062
  };
9947
10063
  };
9948
10064
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -825,6 +825,15 @@ interface IStrategy {
825
825
  * @returns Promise resolving to tick result (idle | opened | active | closed)
826
826
  */
827
827
  tick: (symbol: string) => Promise<IStrategyTickResult>;
828
+ /**
829
+ * Retrieves the currently active pending signal for the symbol.
830
+ * If no active signal exists, returns null.
831
+ * Used internally for monitoring TP/SL and time expiration.
832
+ *
833
+ * @param symbol
834
+ * @returns
835
+ */
836
+ getPendingSignal: (symbol: string) => Promise<ISignalRow | null>;
828
837
  /**
829
838
  * Fast backtest using historical candles.
830
839
  * Iterates through candles, calculates VWAP, checks TP/SL on each candle.
@@ -4437,6 +4446,11 @@ declare const walkerEmitter: Subject<WalkerContract>;
4437
4446
  * Emits when all strategies have been tested and final results are available.
4438
4447
  */
4439
4448
  declare const walkerCompleteSubject: Subject<IWalkerResults>;
4449
+ /**
4450
+ * Walker stop emitter for walker cancellation events.
4451
+ * Emits when a walker comparison is stopped/cancelled.
4452
+ */
4453
+ declare const walkerStopSubject: Subject<string>;
4440
4454
  /**
4441
4455
  * Validation emitter for risk validation errors.
4442
4456
  * Emits when risk validation functions throw errors during signal checking.
@@ -4455,8 +4469,9 @@ declare const emitters_signalLiveEmitter: typeof signalLiveEmitter;
4455
4469
  declare const emitters_validationSubject: typeof validationSubject;
4456
4470
  declare const emitters_walkerCompleteSubject: typeof walkerCompleteSubject;
4457
4471
  declare const emitters_walkerEmitter: typeof walkerEmitter;
4472
+ declare const emitters_walkerStopSubject: typeof walkerStopSubject;
4458
4473
  declare namespace emitters {
4459
- export { emitters_doneBacktestSubject as doneBacktestSubject, emitters_doneLiveSubject as doneLiveSubject, emitters_doneWalkerSubject as doneWalkerSubject, emitters_errorEmitter as errorEmitter, emitters_performanceEmitter as performanceEmitter, emitters_progressEmitter as progressEmitter, emitters_signalBacktestEmitter as signalBacktestEmitter, emitters_signalEmitter as signalEmitter, emitters_signalLiveEmitter as signalLiveEmitter, emitters_validationSubject as validationSubject, emitters_walkerCompleteSubject as walkerCompleteSubject, emitters_walkerEmitter as walkerEmitter };
4474
+ export { emitters_doneBacktestSubject as doneBacktestSubject, emitters_doneLiveSubject as doneLiveSubject, emitters_doneWalkerSubject as doneWalkerSubject, emitters_errorEmitter as errorEmitter, emitters_performanceEmitter as performanceEmitter, emitters_progressEmitter as progressEmitter, emitters_signalBacktestEmitter as signalBacktestEmitter, emitters_signalEmitter as signalEmitter, emitters_signalLiveEmitter as signalLiveEmitter, emitters_validationSubject as validationSubject, emitters_walkerCompleteSubject as walkerCompleteSubject, emitters_walkerEmitter as walkerEmitter, emitters_walkerStopSubject as walkerStopSubject };
4460
4475
  }
4461
4476
 
4462
4477
  /**
@@ -4718,6 +4733,16 @@ declare class StrategyConnectionService implements IStrategy {
4718
4733
  * @returns Configured ClientStrategy instance
4719
4734
  */
4720
4735
  private getStrategy;
4736
+ /**
4737
+ * Retrieves the currently active pending signal for the strategy.
4738
+ * If no active signal exists, returns null.
4739
+ * Used internally for monitoring TP/SL and time expiration.
4740
+ *
4741
+ * @param strategyName - Name of strategy to get pending signal for
4742
+ *
4743
+ * @returns Promise resolving to pending signal or null
4744
+ */
4745
+ getPendingSignal: (strategyName: StrategyName) => Promise<ISignalRow | null>;
4721
4746
  /**
4722
4747
  * Executes live trading tick for current strategy.
4723
4748
  *
@@ -5165,6 +5190,17 @@ declare class StrategyGlobalService {
5165
5190
  * @returns Promise that resolves when validation is complete
5166
5191
  */
5167
5192
  private validate;
5193
+ /**
5194
+ * Retrieves the currently active pending signal for the symbol.
5195
+ * If no active signal exists, returns null.
5196
+ * Used internally for monitoring TP/SL and time expiration.
5197
+ *
5198
+ * @param symbol - Trading pair symbol
5199
+ * @param when - Timestamp for tick evaluation
5200
+ * @param backtest - Whether running in backtest mode
5201
+ * @returns Promise resolving to pending signal or null
5202
+ */
5203
+ getPendingSignal: (strategyName: StrategyName) => Promise<ISignalRow | null>;
5168
5204
  /**
5169
5205
  * Checks signal status at a specific timestamp.
5170
5206
  *