backtest-kit 1.9.1 → 1.10.1

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/types.d.ts CHANGED
@@ -227,154 +227,78 @@ declare function partialLoss(symbol: string, percentToClose: number): Promise<vo
227
227
  * ```
228
228
  */
229
229
  declare function trailingStop(symbol: string, percentShift: number): Promise<void>;
230
-
231
- declare const GLOBAL_CONFIG: {
232
- /**
233
- * Time to wait for scheduled signal to activate (in minutes)
234
- * If signal does not activate within this time, it will be cancelled.
235
- */
236
- CC_SCHEDULE_AWAIT_MINUTES: number;
237
- /**
238
- * Number of candles to use for average price calculation (VWAP)
239
- * Default: 5 candles (last 5 minutes when using 1m interval)
240
- */
241
- CC_AVG_PRICE_CANDLES_COUNT: number;
242
- /**
243
- * Slippage percentage applied to entry and exit prices.
244
- * Simulates market impact and order book depth.
245
- * Applied twice (entry and exit) for realistic execution simulation.
246
- * Default: 0.1% per transaction
247
- */
248
- CC_PERCENT_SLIPPAGE: number;
249
- /**
250
- * Fee percentage charged per transaction.
251
- * Applied twice (entry and exit) for total fee calculation.
252
- * Default: 0.1% per transaction (total 0.2%)
253
- */
254
- CC_PERCENT_FEE: number;
255
- /**
256
- * Minimum TakeProfit distance from priceOpen (percentage)
257
- * Must be greater than (slippage + fees) to ensure profitable trades
258
- *
259
- * Calculation:
260
- * - Slippage effect: ~0.2% (0.1% × 2 transactions)
261
- * - Fees: 0.2% (0.1% × 2 transactions)
262
- * - Minimum profit buffer: 0.1%
263
- * - Total: 0.5%
264
- *
265
- * Default: 0.5% (covers all costs + minimum profit margin)
266
- */
267
- CC_MIN_TAKEPROFIT_DISTANCE_PERCENT: number;
268
- /**
269
- * Minimum StopLoss distance from priceOpen (percentage)
270
- * Prevents signals from being immediately stopped out due to price volatility
271
- * Default: 0.5% (buffer to avoid instant stop loss on normal market fluctuations)
272
- */
273
- CC_MIN_STOPLOSS_DISTANCE_PERCENT: number;
274
- /**
275
- * Maximum StopLoss distance from priceOpen (percentage)
276
- * Prevents catastrophic losses from extreme StopLoss values
277
- * Default: 20% (one signal cannot lose more than 20% of position)
278
- */
279
- CC_MAX_STOPLOSS_DISTANCE_PERCENT: number;
280
- /**
281
- * Maximum signal lifetime in minutes
282
- * Prevents eternal signals that block risk limits for weeks/months
283
- * Default: 1440 minutes (1 day)
284
- */
285
- CC_MAX_SIGNAL_LIFETIME_MINUTES: number;
286
- /**
287
- * Maximum time allowed for signal generation (in seconds).
288
- * Prevents long-running or stuck signal generation routines from blocking
289
- * execution or consuming resources indefinitely. If generation exceeds this
290
- * threshold the attempt should be aborted, logged and optionally retried.
291
- *
292
- * Default: 180 seconds (3 minutes)
293
- */
294
- CC_MAX_SIGNAL_GENERATION_SECONDS: number;
295
- /**
296
- * Number of retries for getCandles function
297
- * Default: 3 retries
298
- */
299
- CC_GET_CANDLES_RETRY_COUNT: number;
300
- /**
301
- * Delay between retries for getCandles function (in milliseconds)
302
- * Default: 5000 ms (5 seconds)
303
- */
304
- CC_GET_CANDLES_RETRY_DELAY_MS: number;
305
- /**
306
- * Maximum allowed deviation factor for price anomaly detection.
307
- * Price should not be more than this factor lower than reference price.
308
- *
309
- * Reasoning:
310
- * - Incomplete candles from Binance API typically have prices near 0 (e.g., $0.01-1)
311
- * - Normal BTC price ranges: $20,000-100,000
312
- * - Factor 1000 catches prices below $20-100 when median is $20,000-100,000
313
- * - Factor 100 would be too permissive (allows $200 when median is $20,000)
314
- * - Factor 10000 might be too strict for low-cap altcoins
315
- *
316
- * Example: BTC at $50,000 median → threshold $50 (catches $0.01-1 anomalies)
317
- */
318
- CC_GET_CANDLES_PRICE_ANOMALY_THRESHOLD_FACTOR: number;
319
- /**
320
- * Minimum number of candles required for reliable median calculation.
321
- * Below this threshold, use simple average instead of median.
322
- *
323
- * Reasoning:
324
- * - Each candle provides 4 price points (OHLC)
325
- * - 5 candles = 20 price points, sufficient for robust median calculation
326
- * - Below 5 candles, single anomaly can heavily skew median
327
- * - Statistical rule of thumb: minimum 7-10 data points for median stability
328
- * - Average is more stable than median for small datasets (n < 20)
329
- *
330
- * Example: 3 candles = 12 points (use average), 5 candles = 20 points (use median)
331
- */
332
- CC_GET_CANDLES_MIN_CANDLES_FOR_MEDIAN: number;
333
- /**
334
- * Controls visibility of signal notes in markdown report tables.
335
- * When enabled, the "Note" column will be displayed in all markdown reports
336
- * (backtest, live, schedule, risk, etc.)
337
- *
338
- * Default: false (notes are hidden to reduce table width and improve readability)
339
- */
340
- CC_REPORT_SHOW_SIGNAL_NOTE: boolean;
341
- };
342
230
  /**
343
- * Type for global configuration object.
231
+ * Moves stop-loss to breakeven when price reaches threshold.
232
+ *
233
+ * Moves SL to entry price (zero-risk position) when current price has moved
234
+ * far enough in profit direction to cover transaction costs.
235
+ * Threshold is calculated as: (CC_PERCENT_SLIPPAGE + CC_PERCENT_FEE) * 2
236
+ *
237
+ * Automatically detects backtest/live mode from execution context.
238
+ * Automatically fetches current price via getAveragePrice.
239
+ *
240
+ * @param symbol - Trading pair symbol
241
+ * @returns Promise<boolean> - true if breakeven was set, false if conditions not met
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * import { breakeven } from "backtest-kit";
246
+ *
247
+ * // LONG: entry=100, slippage=0.1%, fee=0.1%, threshold=0.4%
248
+ * // Try to move SL to breakeven (activates when price >= 100.4)
249
+ * const moved = await breakeven("BTCUSDT");
250
+ * if (moved) {
251
+ * console.log("Position moved to breakeven!");
252
+ * }
253
+ * ```
344
254
  */
345
- type GlobalConfig = typeof GLOBAL_CONFIG;
255
+ declare function breakeven(symbol: string): Promise<boolean>;
346
256
 
347
257
  /**
348
- * Mapping of available table/markdown reports to their column definitions.
258
+ * Execution context containing runtime parameters for strategy/exchange operations.
349
259
  *
350
- * Each property references a column definition object imported from
351
- * `src/assets/*.columns`. These are used by markdown/report generators
352
- * (backtest, live, schedule, risk, heat, performance, partial, walker).
260
+ * Propagated through ExecutionContextService to provide implicit context
261
+ * for getCandles(), tick(), backtest() and other operations.
353
262
  */
354
- declare const COLUMN_CONFIG: {
355
- /** Columns used in backtest markdown tables and reports */
356
- backtest_columns: ColumnModel<IStrategyTickResultClosed>[];
357
- /** Columns used by heatmap / heat reports */
358
- heat_columns: ColumnModel<IHeatmapRow>[];
359
- /** Columns for live trading reports and logs */
360
- live_columns: ColumnModel<TickEvent>[];
361
- /** Columns for partial-results / incremental reports */
362
- partial_columns: ColumnModel<PartialEvent>[];
363
- /** Columns for performance summary reports */
364
- performance_columns: ColumnModel<MetricStats>[];
365
- /** Columns for risk-related reports */
366
- risk_columns: ColumnModel<RiskEvent>[];
367
- /** Columns for scheduled report output */
368
- schedule_columns: ColumnModel<ScheduledEvent>[];
369
- /** Walker: PnL summary columns */
370
- walker_pnl_columns: ColumnModel<SignalData$1>[];
371
- /** Walker: strategy-level summary columns */
372
- walker_strategy_columns: ColumnModel<IStrategyResult>[];
373
- };
263
+ interface IExecutionContext {
264
+ /** Trading pair symbol (e.g., "BTCUSDT") */
265
+ symbol: string;
266
+ /** Current timestamp for operation */
267
+ when: Date;
268
+ /** Whether running in backtest mode (true) or live mode (false) */
269
+ backtest: boolean;
270
+ }
374
271
  /**
375
- * Type for the column configuration object.
272
+ * Scoped service for execution context propagation.
273
+ *
274
+ * Uses di-scoped for implicit context passing without explicit parameters.
275
+ * Context includes symbol, when (timestamp), and backtest flag.
276
+ *
277
+ * Used by GlobalServices to inject context into operations.
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * ExecutionContextService.runInContext(
282
+ * async () => {
283
+ * // Inside this callback, context is automatically available
284
+ * return await someOperation();
285
+ * },
286
+ * { symbol: "BTCUSDT", when: new Date(), backtest: true }
287
+ * );
288
+ * ```
376
289
  */
377
- type ColumnConfig = typeof COLUMN_CONFIG;
290
+ declare const ExecutionContextService: (new () => {
291
+ readonly context: IExecutionContext;
292
+ }) & Omit<{
293
+ new (context: IExecutionContext): {
294
+ readonly context: IExecutionContext;
295
+ };
296
+ }, "prototype"> & di_scoped.IScopedClassRun<[context: IExecutionContext]>;
297
+ /**
298
+ * Type helper for ExecutionContextService instance.
299
+ * Used for dependency injection type annotations.
300
+ */
301
+ type TExecutionContextService = InstanceType<typeof ExecutionContextService>;
378
302
 
379
303
  /**
380
304
  * Interface representing a logging mechanism for the swarm system.
@@ -405,244 +329,30 @@ interface ILogger {
405
329
  }
406
330
 
407
331
  /**
408
- * Sets custom logger implementation for the framework.
409
- *
410
- * All log messages from internal services will be forwarded to the provided logger
411
- * with automatic context injection (strategyName, exchangeName, symbol, etc.).
412
- *
413
- * @param logger - Custom logger implementing ILogger interface
414
- *
415
- * @example
416
- * ```typescript
417
- * setLogger({
418
- * log: (topic, ...args) => console.log(topic, args),
419
- * debug: (topic, ...args) => console.debug(topic, args),
420
- * info: (topic, ...args) => console.info(topic, args),
421
- * });
422
- * ```
332
+ * Candle time interval for fetching historical data.
423
333
  */
424
- declare function setLogger(logger: ILogger): void;
334
+ type CandleInterval = "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h";
425
335
  /**
426
- * Sets global configuration parameters for the framework.
427
- * @param config - Partial configuration object to override default settings
428
- * @param _unsafe - Skip config validations - required for testbed
429
- *
430
- * @example
431
- * ```typescript
432
- * setConfig({
433
- * CC_SCHEDULE_AWAIT_MINUTES: 90,
434
- * });
435
- * ```
336
+ * Single OHLCV candle data point.
337
+ * Used for VWAP calculation and backtesting.
436
338
  */
437
- declare function setConfig(config: Partial<GlobalConfig>, _unsafe?: boolean): void;
339
+ interface ICandleData {
340
+ /** Unix timestamp in milliseconds when candle opened */
341
+ timestamp: number;
342
+ /** Opening price at candle start */
343
+ open: number;
344
+ /** Highest price during candle period */
345
+ high: number;
346
+ /** Lowest price during candle period */
347
+ low: number;
348
+ /** Closing price at candle end */
349
+ close: number;
350
+ /** Trading volume during candle period */
351
+ volume: number;
352
+ }
438
353
  /**
439
- * Retrieves a copy of the current global configuration.
440
- *
441
- * Returns a shallow copy of the current GLOBAL_CONFIG to prevent accidental mutations.
442
- * Use this to inspect the current configuration state without modifying it.
443
- *
444
- * @returns {GlobalConfig} A copy of the current global configuration object
445
- *
446
- * @example
447
- * ```typescript
448
- * const currentConfig = getConfig();
449
- * console.log(currentConfig.CC_SCHEDULE_AWAIT_MINUTES);
450
- * ```
451
- */
452
- declare function getConfig(): {
453
- CC_SCHEDULE_AWAIT_MINUTES: number;
454
- CC_AVG_PRICE_CANDLES_COUNT: number;
455
- CC_PERCENT_SLIPPAGE: number;
456
- CC_PERCENT_FEE: number;
457
- CC_MIN_TAKEPROFIT_DISTANCE_PERCENT: number;
458
- CC_MIN_STOPLOSS_DISTANCE_PERCENT: number;
459
- CC_MAX_STOPLOSS_DISTANCE_PERCENT: number;
460
- CC_MAX_SIGNAL_LIFETIME_MINUTES: number;
461
- CC_MAX_SIGNAL_GENERATION_SECONDS: number;
462
- CC_GET_CANDLES_RETRY_COUNT: number;
463
- CC_GET_CANDLES_RETRY_DELAY_MS: number;
464
- CC_GET_CANDLES_PRICE_ANOMALY_THRESHOLD_FACTOR: number;
465
- CC_GET_CANDLES_MIN_CANDLES_FOR_MEDIAN: number;
466
- CC_REPORT_SHOW_SIGNAL_NOTE: boolean;
467
- };
468
- /**
469
- * Retrieves the default configuration object for the framework.
470
- *
471
- * Returns a reference to the default configuration with all preset values.
472
- * Use this to see what configuration options are available and their default values.
473
- *
474
- * @returns {GlobalConfig} The default configuration object
475
- *
476
- * @example
477
- * ```typescript
478
- * const defaultConfig = getDefaultConfig();
479
- * console.log(defaultConfig.CC_SCHEDULE_AWAIT_MINUTES);
480
- * ```
481
- */
482
- declare function getDefaultConfig(): Readonly<{
483
- CC_SCHEDULE_AWAIT_MINUTES: number;
484
- CC_AVG_PRICE_CANDLES_COUNT: number;
485
- CC_PERCENT_SLIPPAGE: number;
486
- CC_PERCENT_FEE: number;
487
- CC_MIN_TAKEPROFIT_DISTANCE_PERCENT: number;
488
- CC_MIN_STOPLOSS_DISTANCE_PERCENT: number;
489
- CC_MAX_STOPLOSS_DISTANCE_PERCENT: number;
490
- CC_MAX_SIGNAL_LIFETIME_MINUTES: number;
491
- CC_MAX_SIGNAL_GENERATION_SECONDS: number;
492
- CC_GET_CANDLES_RETRY_COUNT: number;
493
- CC_GET_CANDLES_RETRY_DELAY_MS: number;
494
- CC_GET_CANDLES_PRICE_ANOMALY_THRESHOLD_FACTOR: number;
495
- CC_GET_CANDLES_MIN_CANDLES_FOR_MEDIAN: number;
496
- CC_REPORT_SHOW_SIGNAL_NOTE: boolean;
497
- }>;
498
- /**
499
- * Sets custom column configurations for markdown report generation.
500
- *
501
- * Allows overriding default column definitions for any report type.
502
- * All columns are validated before assignment to ensure structural correctness.
503
- *
504
- * @param columns - Partial column configuration object to override default column settings
505
- * @param _unsafe - Skip column validations - required for testbed
506
- *
507
- * @example
508
- * ```typescript
509
- * setColumns({
510
- * backtest_columns: [
511
- * {
512
- * key: "customId",
513
- * label: "Custom ID",
514
- * format: (data) => data.signal.id,
515
- * isVisible: () => true
516
- * }
517
- * ],
518
- * });
519
- * ```
520
- *
521
- * @throws {Error} If column configuration is invalid
522
- */
523
- declare function setColumns(columns: Partial<ColumnConfig>, _unsafe?: boolean): void;
524
- /**
525
- * Retrieves a copy of the current column configuration for markdown report generation.
526
- *
527
- * Returns a shallow copy of the current COLUMN_CONFIG to prevent accidental mutations.
528
- * Use this to inspect the current column definitions without modifying them.
529
- *
530
- * @returns {ColumnConfig} A copy of the current column configuration object
531
- *
532
- * @example
533
- * ```typescript
534
- * const currentColumns = getColumns();
535
- * console.log(currentColumns.backtest_columns.length);
536
- * ```
537
- */
538
- declare function getColumns(): {
539
- backtest_columns: ColumnModel<IStrategyTickResultClosed>[];
540
- heat_columns: ColumnModel<IHeatmapRow>[];
541
- live_columns: ColumnModel<TickEvent>[];
542
- partial_columns: ColumnModel<PartialEvent>[];
543
- performance_columns: ColumnModel<MetricStats>[];
544
- risk_columns: ColumnModel<RiskEvent>[];
545
- schedule_columns: ColumnModel<ScheduledEvent>[];
546
- walker_pnl_columns: ColumnModel<SignalData$1>[];
547
- walker_strategy_columns: ColumnModel<IStrategyResult>[];
548
- };
549
- /**
550
- * Retrieves the default column configuration object for markdown report generation.
551
- *
552
- * Returns a reference to the default column definitions with all preset values.
553
- * Use this to see what column options are available and their default definitions.
554
- *
555
- * @returns {ColumnConfig} The default column configuration object
556
- *
557
- * @example
558
- * ```typescript
559
- * const defaultColumns = getDefaultColumns();
560
- * console.log(defaultColumns.backtest_columns);
561
- * ```
562
- */
563
- declare function getDefaultColumns(): Readonly<{
564
- backtest_columns: ColumnModel<IStrategyTickResultClosed>[];
565
- heat_columns: ColumnModel<IHeatmapRow>[];
566
- live_columns: ColumnModel<TickEvent>[];
567
- partial_columns: ColumnModel<PartialEvent>[];
568
- performance_columns: ColumnModel<MetricStats>[];
569
- risk_columns: ColumnModel<RiskEvent>[];
570
- schedule_columns: ColumnModel<ScheduledEvent>[];
571
- walker_pnl_columns: ColumnModel<SignalData$1>[];
572
- walker_strategy_columns: ColumnModel<IStrategyResult>[];
573
- }>;
574
-
575
- /**
576
- * Execution context containing runtime parameters for strategy/exchange operations.
577
- *
578
- * Propagated through ExecutionContextService to provide implicit context
579
- * for getCandles(), tick(), backtest() and other operations.
580
- */
581
- interface IExecutionContext {
582
- /** Trading pair symbol (e.g., "BTCUSDT") */
583
- symbol: string;
584
- /** Current timestamp for operation */
585
- when: Date;
586
- /** Whether running in backtest mode (true) or live mode (false) */
587
- backtest: boolean;
588
- }
589
- /**
590
- * Scoped service for execution context propagation.
591
- *
592
- * Uses di-scoped for implicit context passing without explicit parameters.
593
- * Context includes symbol, when (timestamp), and backtest flag.
594
- *
595
- * Used by GlobalServices to inject context into operations.
596
- *
597
- * @example
598
- * ```typescript
599
- * ExecutionContextService.runInContext(
600
- * async () => {
601
- * // Inside this callback, context is automatically available
602
- * return await someOperation();
603
- * },
604
- * { symbol: "BTCUSDT", when: new Date(), backtest: true }
605
- * );
606
- * ```
607
- */
608
- declare const ExecutionContextService: (new () => {
609
- readonly context: IExecutionContext;
610
- }) & Omit<{
611
- new (context: IExecutionContext): {
612
- readonly context: IExecutionContext;
613
- };
614
- }, "prototype"> & di_scoped.IScopedClassRun<[context: IExecutionContext]>;
615
- /**
616
- * Type helper for ExecutionContextService instance.
617
- * Used for dependency injection type annotations.
618
- */
619
- type TExecutionContextService = InstanceType<typeof ExecutionContextService>;
620
-
621
- /**
622
- * Candle time interval for fetching historical data.
623
- */
624
- type CandleInterval = "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h";
625
- /**
626
- * Single OHLCV candle data point.
627
- * Used for VWAP calculation and backtesting.
628
- */
629
- interface ICandleData {
630
- /** Unix timestamp in milliseconds when candle opened */
631
- timestamp: number;
632
- /** Opening price at candle start */
633
- open: number;
634
- /** Highest price during candle period */
635
- high: number;
636
- /** Lowest price during candle period */
637
- low: number;
638
- /** Closing price at candle end */
639
- close: number;
640
- /** Trading volume during candle period */
641
- volume: number;
642
- }
643
- /**
644
- * Exchange parameters passed to ClientExchange constructor.
645
- * Combines schema with runtime dependencies.
354
+ * Exchange parameters passed to ClientExchange constructor.
355
+ * Combines schema with runtime dependencies.
646
356
  */
647
357
  interface IExchangeParams extends IExchangeSchema {
648
358
  /** Logger service for debug output */
@@ -987,6 +697,8 @@ interface IRiskSchema {
987
697
  * Combines schema with runtime dependencies and emission callbacks.
988
698
  */
989
699
  interface IRiskParams extends IRiskSchema {
700
+ /** Exchange name (e.g., "binance") */
701
+ exchangeName: ExchangeName;
990
702
  /** Logger service for debug output */
991
703
  logger: ILogger;
992
704
  /** True if backtest mode, false if live mode */
@@ -1203,6 +915,112 @@ interface IPartial {
1203
915
  clear(symbol: string, data: IPublicSignalRow, priceClose: number, backtest: boolean): Promise<void>;
1204
916
  }
1205
917
 
918
+ /**
919
+ * Serializable breakeven data for persistence layer.
920
+ * Converts state to simple boolean for JSON serialization.
921
+ *
922
+ * Stored in PersistBreakevenAdapter as Record<signalId, IBreakevenData>.
923
+ * Loaded on initialization and converted back to IBreakevenState.
924
+ */
925
+ interface IBreakevenData {
926
+ /**
927
+ * Whether breakeven has been reached for this signal.
928
+ * Serialized form of IBreakevenState.reached.
929
+ */
930
+ reached: boolean;
931
+ }
932
+ /**
933
+ * Breakeven tracking interface.
934
+ * Implemented by ClientBreakeven and BreakevenConnectionService.
935
+ *
936
+ * Tracks when a signal's stop-loss is moved to breakeven (entry price).
937
+ * Emits events when threshold is reached (price moves far enough to cover transaction costs).
938
+ *
939
+ * @example
940
+ * ```typescript
941
+ * import { ClientBreakeven } from "./client/ClientBreakeven";
942
+ *
943
+ * const breakeven = new ClientBreakeven({
944
+ * logger: loggerService,
945
+ * onBreakeven: (symbol, data, price, backtest, timestamp) => {
946
+ * console.log(`Signal ${data.id} reached breakeven at ${price}`);
947
+ * }
948
+ * });
949
+ *
950
+ * await breakeven.waitForInit("BTCUSDT");
951
+ *
952
+ * // During signal monitoring
953
+ * await breakeven.check("BTCUSDT", signal, 100.5, false, new Date());
954
+ * // Emits event when threshold reached and SL moved to entry
955
+ *
956
+ * // When signal closes
957
+ * await breakeven.clear("BTCUSDT", signal, 101, false);
958
+ * ```
959
+ */
960
+ interface IBreakeven {
961
+ /**
962
+ * Checks if breakeven should be triggered and emits event if conditions met.
963
+ *
964
+ * Called by ClientStrategy during signal monitoring.
965
+ * Checks if:
966
+ * 1. Breakeven not already reached
967
+ * 2. Price has moved far enough to cover transaction costs
968
+ * 3. Stop-loss can be moved to entry price
969
+ *
970
+ * If all conditions met:
971
+ * - Marks breakeven as reached
972
+ * - Calls onBreakeven callback (emits to breakevenSubject)
973
+ * - Persists state to disk
974
+ *
975
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
976
+ * @param data - Signal row data
977
+ * @param currentPrice - Current market price
978
+ * @param backtest - True if backtest mode, false if live mode
979
+ * @param when - Event timestamp (current time for live, candle time for backtest)
980
+ * @returns Promise that resolves when breakeven check is complete
981
+ *
982
+ * @example
983
+ * ```typescript
984
+ * // LONG: entry=100, slippage=0.1%, fee=0.1%, threshold=0.4%
985
+ * // Price at 100.3 - threshold not reached
986
+ * await breakeven.check("BTCUSDT", signal, 100.3, false, new Date());
987
+ * // No event emitted (price < 100.4)
988
+ *
989
+ * // Price at 100.5 - threshold reached!
990
+ * await breakeven.check("BTCUSDT", signal, 100.5, false, new Date());
991
+ * // Emits breakevenSubject event
992
+ *
993
+ * // Price at 101 - already at breakeven
994
+ * await breakeven.check("BTCUSDT", signal, 101, false, new Date());
995
+ * // No event emitted (already reached)
996
+ * ```
997
+ */
998
+ check(symbol: string, data: IPublicSignalRow, currentPrice: number, backtest: boolean, when: Date): Promise<boolean>;
999
+ /**
1000
+ * Clears breakeven state when signal closes.
1001
+ *
1002
+ * Called by ClientStrategy when signal completes (TP/SL/time_expired).
1003
+ * Removes signal state from memory and persists changes to disk.
1004
+ * Cleans up memoized ClientBreakeven instance in BreakevenConnectionService.
1005
+ *
1006
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1007
+ * @param data - Signal row data
1008
+ * @param priceClose - Final closing price
1009
+ * @param backtest - True if backtest mode, false if live mode
1010
+ * @returns Promise that resolves when clear is complete
1011
+ *
1012
+ * @example
1013
+ * ```typescript
1014
+ * // Signal closes at take profit
1015
+ * await breakeven.clear("BTCUSDT", signal, 101);
1016
+ * // State removed from _states Map
1017
+ * // Persisted to disk without this signal's data
1018
+ * // Memoized instance cleared from getBreakeven cache
1019
+ * ```
1020
+ */
1021
+ clear(symbol: string, data: IPublicSignalRow, priceClose: number, backtest: boolean): Promise<void>;
1022
+ }
1023
+
1206
1024
  /**
1207
1025
  * Signal generation interval for throttling.
1208
1026
  * Enforces minimum time between getSignal calls.
@@ -1354,6 +1172,8 @@ interface IStrategyCallbacks {
1354
1172
  onPartialProfit: (symbol: string, data: IPublicSignalRow, currentPrice: number, revenuePercent: number, backtest: boolean) => void | Promise<void>;
1355
1173
  /** Called when signal is in partial loss state (price moved against position but not hit SL yet) */
1356
1174
  onPartialLoss: (symbol: string, data: IPublicSignalRow, currentPrice: number, lossPercent: number, backtest: boolean) => void | Promise<void>;
1175
+ /** Called when signal reaches breakeven (stop-loss moved to entry price to protect capital) */
1176
+ onBreakeven: (symbol: string, data: IPublicSignalRow, currentPrice: number, backtest: boolean) => void | Promise<void>;
1357
1177
  /** Called every minute regardless of strategy interval (for custom monitoring like checking if signal should be cancelled) */
1358
1178
  onPing: (symbol: string, data: IPublicSignalRow, when: Date, backtest: boolean) => void | Promise<void>;
1359
1179
  }
@@ -1771,11 +1591,439 @@ interface IStrategy {
1771
1591
  * ```
1772
1592
  */
1773
1593
  trailingStop: (symbol: string, percentShift: number, backtest: boolean) => Promise<void>;
1774
- }
1594
+ /**
1595
+ * Moves stop-loss to breakeven (entry price) when price reaches threshold.
1596
+ *
1597
+ * Moves SL to entry price (zero-risk position) when current price has moved
1598
+ * far enough in profit direction to cover transaction costs (slippage + fees).
1599
+ * Threshold is calculated as: (CC_PERCENT_SLIPPAGE + CC_PERCENT_FEE) * 2
1600
+ *
1601
+ * Behavior:
1602
+ * - Returns true if SL was moved to breakeven
1603
+ * - Returns false if conditions not met (threshold not reached or already at breakeven)
1604
+ * - Uses _trailingPriceStopLoss to store breakeven SL (preserves original priceStopLoss)
1605
+ * - Only moves SL once per position (idempotent - safe to call multiple times)
1606
+ *
1607
+ * For LONG position (entry=100, slippage=0.1%, fee=0.1%):
1608
+ * - Threshold: (0.1 + 0.1) * 2 = 0.4%
1609
+ * - Breakeven available when price >= 100.4 (entry + 0.4%)
1610
+ * - Moves SL from original (e.g. 95) to 100 (breakeven)
1611
+ * - Returns true on first successful move, false on subsequent calls
1612
+ *
1613
+ * For SHORT position (entry=100, slippage=0.1%, fee=0.1%):
1614
+ * - Threshold: (0.1 + 0.1) * 2 = 0.4%
1615
+ * - Breakeven available when price <= 99.6 (entry - 0.4%)
1616
+ * - Moves SL from original (e.g. 105) to 100 (breakeven)
1617
+ * - Returns true on first successful move, false on subsequent calls
1618
+ *
1619
+ * Validations:
1620
+ * - Throws if no pending signal exists
1621
+ * - Throws if currentPrice is not a positive finite number
1622
+ *
1623
+ * Use case: User-controlled breakeven protection triggered from onPartialProfit callback.
1624
+ *
1625
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1626
+ * @param currentPrice - Current market price to check threshold
1627
+ * @param backtest - Whether running in backtest mode
1628
+ * @returns Promise<boolean> - true if breakeven was set, false if conditions not met
1629
+ *
1630
+ * @example
1631
+ * ```typescript
1632
+ * callbacks: {
1633
+ * onPartialProfit: async (symbol, signal, currentPrice, percentTp, backtest) => {
1634
+ * // Try to move SL to breakeven when threshold reached
1635
+ * const movedToBreakeven = await strategy.breakeven(symbol, currentPrice, backtest);
1636
+ * if (movedToBreakeven) {
1637
+ * console.log(`Position moved to breakeven at ${currentPrice}`);
1638
+ * }
1639
+ * }
1640
+ * }
1641
+ * ```
1642
+ */
1643
+ breakeven: (symbol: string, currentPrice: number, backtest: boolean) => Promise<boolean>;
1644
+ }
1645
+ /**
1646
+ * Unique strategy identifier.
1647
+ */
1648
+ type StrategyName = string;
1649
+
1650
+ /**
1651
+ * Unified breakeven event data for report generation.
1652
+ * Contains all information about when signals reached breakeven.
1653
+ */
1654
+ interface BreakevenEvent {
1655
+ /** Event timestamp in milliseconds */
1656
+ timestamp: number;
1657
+ /** Trading pair symbol */
1658
+ symbol: string;
1659
+ /** Strategy name */
1660
+ strategyName: StrategyName;
1661
+ /** Signal ID */
1662
+ signalId: string;
1663
+ /** Position type */
1664
+ position: string;
1665
+ /** Current market price when breakeven was reached */
1666
+ currentPrice: number;
1667
+ /** Entry price (breakeven level) */
1668
+ priceOpen: number;
1669
+ /** True if backtest mode, false if live mode */
1670
+ backtest: boolean;
1671
+ }
1672
+ /**
1673
+ * Statistical data calculated from breakeven events.
1674
+ *
1675
+ * Provides metrics for breakeven milestone tracking.
1676
+ *
1677
+ * @example
1678
+ * ```typescript
1679
+ * const stats = await Breakeven.getData("BTCUSDT", "my-strategy");
1680
+ *
1681
+ * console.log(`Total breakeven events: ${stats.totalEvents}`);
1682
+ * console.log(`Average threshold: ${stats.averageThreshold}%`);
1683
+ * ```
1684
+ */
1685
+ interface BreakevenStatisticsModel {
1686
+ /** Array of all breakeven events with full details */
1687
+ eventList: BreakevenEvent[];
1688
+ /** Total number of breakeven events */
1689
+ totalEvents: number;
1690
+ }
1691
+
1692
+ declare const GLOBAL_CONFIG: {
1693
+ /**
1694
+ * Time to wait for scheduled signal to activate (in minutes)
1695
+ * If signal does not activate within this time, it will be cancelled.
1696
+ */
1697
+ CC_SCHEDULE_AWAIT_MINUTES: number;
1698
+ /**
1699
+ * Number of candles to use for average price calculation (VWAP)
1700
+ * Default: 5 candles (last 5 minutes when using 1m interval)
1701
+ */
1702
+ CC_AVG_PRICE_CANDLES_COUNT: number;
1703
+ /**
1704
+ * Slippage percentage applied to entry and exit prices.
1705
+ * Simulates market impact and order book depth.
1706
+ * Applied twice (entry and exit) for realistic execution simulation.
1707
+ * Default: 0.1% per transaction
1708
+ */
1709
+ CC_PERCENT_SLIPPAGE: number;
1710
+ /**
1711
+ * Fee percentage charged per transaction.
1712
+ * Applied twice (entry and exit) for total fee calculation.
1713
+ * Default: 0.1% per transaction (total 0.2%)
1714
+ */
1715
+ CC_PERCENT_FEE: number;
1716
+ /**
1717
+ * Minimum TakeProfit distance from priceOpen (percentage)
1718
+ * Must be greater than (slippage + fees) to ensure profitable trades
1719
+ *
1720
+ * Calculation:
1721
+ * - Slippage effect: ~0.2% (0.1% × 2 transactions)
1722
+ * - Fees: 0.2% (0.1% × 2 transactions)
1723
+ * - Minimum profit buffer: 0.1%
1724
+ * - Total: 0.5%
1725
+ *
1726
+ * Default: 0.5% (covers all costs + minimum profit margin)
1727
+ */
1728
+ CC_MIN_TAKEPROFIT_DISTANCE_PERCENT: number;
1729
+ /**
1730
+ * Minimum StopLoss distance from priceOpen (percentage)
1731
+ * Prevents signals from being immediately stopped out due to price volatility
1732
+ * Default: 0.5% (buffer to avoid instant stop loss on normal market fluctuations)
1733
+ */
1734
+ CC_MIN_STOPLOSS_DISTANCE_PERCENT: number;
1735
+ /**
1736
+ * Maximum StopLoss distance from priceOpen (percentage)
1737
+ * Prevents catastrophic losses from extreme StopLoss values
1738
+ * Default: 20% (one signal cannot lose more than 20% of position)
1739
+ */
1740
+ CC_MAX_STOPLOSS_DISTANCE_PERCENT: number;
1741
+ /**
1742
+ * Maximum signal lifetime in minutes
1743
+ * Prevents eternal signals that block risk limits for weeks/months
1744
+ * Default: 1440 minutes (1 day)
1745
+ */
1746
+ CC_MAX_SIGNAL_LIFETIME_MINUTES: number;
1747
+ /**
1748
+ * Maximum time allowed for signal generation (in seconds).
1749
+ * Prevents long-running or stuck signal generation routines from blocking
1750
+ * execution or consuming resources indefinitely. If generation exceeds this
1751
+ * threshold the attempt should be aborted, logged and optionally retried.
1752
+ *
1753
+ * Default: 180 seconds (3 minutes)
1754
+ */
1755
+ CC_MAX_SIGNAL_GENERATION_SECONDS: number;
1756
+ /**
1757
+ * Number of retries for getCandles function
1758
+ * Default: 3 retries
1759
+ */
1760
+ CC_GET_CANDLES_RETRY_COUNT: number;
1761
+ /**
1762
+ * Delay between retries for getCandles function (in milliseconds)
1763
+ * Default: 5000 ms (5 seconds)
1764
+ */
1765
+ CC_GET_CANDLES_RETRY_DELAY_MS: number;
1766
+ /**
1767
+ * Maximum allowed deviation factor for price anomaly detection.
1768
+ * Price should not be more than this factor lower than reference price.
1769
+ *
1770
+ * Reasoning:
1771
+ * - Incomplete candles from Binance API typically have prices near 0 (e.g., $0.01-1)
1772
+ * - Normal BTC price ranges: $20,000-100,000
1773
+ * - Factor 1000 catches prices below $20-100 when median is $20,000-100,000
1774
+ * - Factor 100 would be too permissive (allows $200 when median is $20,000)
1775
+ * - Factor 10000 might be too strict for low-cap altcoins
1776
+ *
1777
+ * Example: BTC at $50,000 median → threshold $50 (catches $0.01-1 anomalies)
1778
+ */
1779
+ CC_GET_CANDLES_PRICE_ANOMALY_THRESHOLD_FACTOR: number;
1780
+ /**
1781
+ * Minimum number of candles required for reliable median calculation.
1782
+ * Below this threshold, use simple average instead of median.
1783
+ *
1784
+ * Reasoning:
1785
+ * - Each candle provides 4 price points (OHLC)
1786
+ * - 5 candles = 20 price points, sufficient for robust median calculation
1787
+ * - Below 5 candles, single anomaly can heavily skew median
1788
+ * - Statistical rule of thumb: minimum 7-10 data points for median stability
1789
+ * - Average is more stable than median for small datasets (n < 20)
1790
+ *
1791
+ * Example: 3 candles = 12 points (use average), 5 candles = 20 points (use median)
1792
+ */
1793
+ CC_GET_CANDLES_MIN_CANDLES_FOR_MEDIAN: number;
1794
+ /**
1795
+ * Controls visibility of signal notes in markdown report tables.
1796
+ * When enabled, the "Note" column will be displayed in all markdown reports
1797
+ * (backtest, live, schedule, risk, etc.)
1798
+ *
1799
+ * Default: false (notes are hidden to reduce table width and improve readability)
1800
+ */
1801
+ CC_REPORT_SHOW_SIGNAL_NOTE: boolean;
1802
+ /**
1803
+ * Breakeven threshold percentage - minimum profit distance from entry to enable breakeven.
1804
+ * When price moves this percentage in profit direction, stop-loss can be moved to entry (breakeven).
1805
+ *
1806
+ * Calculation:
1807
+ * - Slippage effect: ~0.2% (0.1% × 2 transactions)
1808
+ * - Fees: 0.2% (0.1% × 2 transactions)
1809
+ * - Total: 0.4%
1810
+ * - Added buffer: 0.2%
1811
+ * - Overall: 0.6%
1812
+ *
1813
+ * Default: 0.2% (additional buffer above costs to ensure no loss when moving to breakeven)
1814
+ */
1815
+ CC_BREAKEVEN_THRESHOLD: number;
1816
+ };
1817
+ /**
1818
+ * Type for global configuration object.
1819
+ */
1820
+ type GlobalConfig = typeof GLOBAL_CONFIG;
1821
+
1822
+ /**
1823
+ * Mapping of available table/markdown reports to their column definitions.
1824
+ *
1825
+ * Each property references a column definition object imported from
1826
+ * `src/assets/*.columns`. These are used by markdown/report generators
1827
+ * (backtest, live, schedule, risk, heat, performance, partial, walker).
1828
+ */
1829
+ declare const COLUMN_CONFIG: {
1830
+ /** Columns used in backtest markdown tables and reports */
1831
+ backtest_columns: ColumnModel<IStrategyTickResultClosed>[];
1832
+ /** Columns used by heatmap / heat reports */
1833
+ heat_columns: ColumnModel<IHeatmapRow>[];
1834
+ /** Columns for live trading reports and logs */
1835
+ live_columns: ColumnModel<TickEvent>[];
1836
+ /** Columns for partial-results / incremental reports */
1837
+ partial_columns: ColumnModel<PartialEvent>[];
1838
+ /** Columns for breakeven protection events */
1839
+ breakeven_columns: ColumnModel<BreakevenEvent>[];
1840
+ /** Columns for performance summary reports */
1841
+ performance_columns: ColumnModel<MetricStats>[];
1842
+ /** Columns for risk-related reports */
1843
+ risk_columns: ColumnModel<RiskEvent>[];
1844
+ /** Columns for scheduled report output */
1845
+ schedule_columns: ColumnModel<ScheduledEvent>[];
1846
+ /** Walker: PnL summary columns */
1847
+ walker_pnl_columns: ColumnModel<SignalData$1>[];
1848
+ /** Walker: strategy-level summary columns */
1849
+ walker_strategy_columns: ColumnModel<IStrategyResult>[];
1850
+ };
1851
+ /**
1852
+ * Type for the column configuration object.
1853
+ */
1854
+ type ColumnConfig = typeof COLUMN_CONFIG;
1855
+
1856
+ /**
1857
+ * Sets custom logger implementation for the framework.
1858
+ *
1859
+ * All log messages from internal services will be forwarded to the provided logger
1860
+ * with automatic context injection (strategyName, exchangeName, symbol, etc.).
1861
+ *
1862
+ * @param logger - Custom logger implementing ILogger interface
1863
+ *
1864
+ * @example
1865
+ * ```typescript
1866
+ * setLogger({
1867
+ * log: (topic, ...args) => console.log(topic, args),
1868
+ * debug: (topic, ...args) => console.debug(topic, args),
1869
+ * info: (topic, ...args) => console.info(topic, args),
1870
+ * });
1871
+ * ```
1872
+ */
1873
+ declare function setLogger(logger: ILogger): void;
1874
+ /**
1875
+ * Sets global configuration parameters for the framework.
1876
+ * @param config - Partial configuration object to override default settings
1877
+ * @param _unsafe - Skip config validations - required for testbed
1878
+ *
1879
+ * @example
1880
+ * ```typescript
1881
+ * setConfig({
1882
+ * CC_SCHEDULE_AWAIT_MINUTES: 90,
1883
+ * });
1884
+ * ```
1885
+ */
1886
+ declare function setConfig(config: Partial<GlobalConfig>, _unsafe?: boolean): void;
1887
+ /**
1888
+ * Retrieves a copy of the current global configuration.
1889
+ *
1890
+ * Returns a shallow copy of the current GLOBAL_CONFIG to prevent accidental mutations.
1891
+ * Use this to inspect the current configuration state without modifying it.
1892
+ *
1893
+ * @returns {GlobalConfig} A copy of the current global configuration object
1894
+ *
1895
+ * @example
1896
+ * ```typescript
1897
+ * const currentConfig = getConfig();
1898
+ * console.log(currentConfig.CC_SCHEDULE_AWAIT_MINUTES);
1899
+ * ```
1900
+ */
1901
+ declare function getConfig(): {
1902
+ CC_SCHEDULE_AWAIT_MINUTES: number;
1903
+ CC_AVG_PRICE_CANDLES_COUNT: number;
1904
+ CC_PERCENT_SLIPPAGE: number;
1905
+ CC_PERCENT_FEE: number;
1906
+ CC_MIN_TAKEPROFIT_DISTANCE_PERCENT: number;
1907
+ CC_MIN_STOPLOSS_DISTANCE_PERCENT: number;
1908
+ CC_MAX_STOPLOSS_DISTANCE_PERCENT: number;
1909
+ CC_MAX_SIGNAL_LIFETIME_MINUTES: number;
1910
+ CC_MAX_SIGNAL_GENERATION_SECONDS: number;
1911
+ CC_GET_CANDLES_RETRY_COUNT: number;
1912
+ CC_GET_CANDLES_RETRY_DELAY_MS: number;
1913
+ CC_GET_CANDLES_PRICE_ANOMALY_THRESHOLD_FACTOR: number;
1914
+ CC_GET_CANDLES_MIN_CANDLES_FOR_MEDIAN: number;
1915
+ CC_REPORT_SHOW_SIGNAL_NOTE: boolean;
1916
+ CC_BREAKEVEN_THRESHOLD: number;
1917
+ };
1918
+ /**
1919
+ * Retrieves the default configuration object for the framework.
1920
+ *
1921
+ * Returns a reference to the default configuration with all preset values.
1922
+ * Use this to see what configuration options are available and their default values.
1923
+ *
1924
+ * @returns {GlobalConfig} The default configuration object
1925
+ *
1926
+ * @example
1927
+ * ```typescript
1928
+ * const defaultConfig = getDefaultConfig();
1929
+ * console.log(defaultConfig.CC_SCHEDULE_AWAIT_MINUTES);
1930
+ * ```
1931
+ */
1932
+ declare function getDefaultConfig(): Readonly<{
1933
+ CC_SCHEDULE_AWAIT_MINUTES: number;
1934
+ CC_AVG_PRICE_CANDLES_COUNT: number;
1935
+ CC_PERCENT_SLIPPAGE: number;
1936
+ CC_PERCENT_FEE: number;
1937
+ CC_MIN_TAKEPROFIT_DISTANCE_PERCENT: number;
1938
+ CC_MIN_STOPLOSS_DISTANCE_PERCENT: number;
1939
+ CC_MAX_STOPLOSS_DISTANCE_PERCENT: number;
1940
+ CC_MAX_SIGNAL_LIFETIME_MINUTES: number;
1941
+ CC_MAX_SIGNAL_GENERATION_SECONDS: number;
1942
+ CC_GET_CANDLES_RETRY_COUNT: number;
1943
+ CC_GET_CANDLES_RETRY_DELAY_MS: number;
1944
+ CC_GET_CANDLES_PRICE_ANOMALY_THRESHOLD_FACTOR: number;
1945
+ CC_GET_CANDLES_MIN_CANDLES_FOR_MEDIAN: number;
1946
+ CC_REPORT_SHOW_SIGNAL_NOTE: boolean;
1947
+ CC_BREAKEVEN_THRESHOLD: number;
1948
+ }>;
1949
+ /**
1950
+ * Sets custom column configurations for markdown report generation.
1951
+ *
1952
+ * Allows overriding default column definitions for any report type.
1953
+ * All columns are validated before assignment to ensure structural correctness.
1954
+ *
1955
+ * @param columns - Partial column configuration object to override default column settings
1956
+ * @param _unsafe - Skip column validations - required for testbed
1957
+ *
1958
+ * @example
1959
+ * ```typescript
1960
+ * setColumns({
1961
+ * backtest_columns: [
1962
+ * {
1963
+ * key: "customId",
1964
+ * label: "Custom ID",
1965
+ * format: (data) => data.signal.id,
1966
+ * isVisible: () => true
1967
+ * }
1968
+ * ],
1969
+ * });
1970
+ * ```
1971
+ *
1972
+ * @throws {Error} If column configuration is invalid
1973
+ */
1974
+ declare function setColumns(columns: Partial<ColumnConfig>, _unsafe?: boolean): void;
1775
1975
  /**
1776
- * Unique strategy identifier.
1976
+ * Retrieves a copy of the current column configuration for markdown report generation.
1977
+ *
1978
+ * Returns a shallow copy of the current COLUMN_CONFIG to prevent accidental mutations.
1979
+ * Use this to inspect the current column definitions without modifying them.
1980
+ *
1981
+ * @returns {ColumnConfig} A copy of the current column configuration object
1982
+ *
1983
+ * @example
1984
+ * ```typescript
1985
+ * const currentColumns = getColumns();
1986
+ * console.log(currentColumns.backtest_columns.length);
1987
+ * ```
1777
1988
  */
1778
- type StrategyName = string;
1989
+ declare function getColumns(): {
1990
+ backtest_columns: ColumnModel<IStrategyTickResultClosed>[];
1991
+ heat_columns: ColumnModel<IHeatmapRow>[];
1992
+ live_columns: ColumnModel<TickEvent>[];
1993
+ partial_columns: ColumnModel<PartialEvent>[];
1994
+ breakeven_columns: ColumnModel<BreakevenEvent>[];
1995
+ performance_columns: ColumnModel<MetricStats>[];
1996
+ risk_columns: ColumnModel<RiskEvent>[];
1997
+ schedule_columns: ColumnModel<ScheduledEvent>[];
1998
+ walker_pnl_columns: ColumnModel<SignalData$1>[];
1999
+ walker_strategy_columns: ColumnModel<IStrategyResult>[];
2000
+ };
2001
+ /**
2002
+ * Retrieves the default column configuration object for markdown report generation.
2003
+ *
2004
+ * Returns a reference to the default column definitions with all preset values.
2005
+ * Use this to see what column options are available and their default definitions.
2006
+ *
2007
+ * @returns {ColumnConfig} The default column configuration object
2008
+ *
2009
+ * @example
2010
+ * ```typescript
2011
+ * const defaultColumns = getDefaultColumns();
2012
+ * console.log(defaultColumns.backtest_columns);
2013
+ * ```
2014
+ */
2015
+ declare function getDefaultColumns(): Readonly<{
2016
+ backtest_columns: ColumnModel<IStrategyTickResultClosed>[];
2017
+ heat_columns: ColumnModel<IHeatmapRow>[];
2018
+ live_columns: ColumnModel<TickEvent>[];
2019
+ partial_columns: ColumnModel<PartialEvent>[];
2020
+ breakeven_columns: ColumnModel<BreakevenEvent>[];
2021
+ performance_columns: ColumnModel<MetricStats>[];
2022
+ risk_columns: ColumnModel<RiskEvent>[];
2023
+ schedule_columns: ColumnModel<ScheduledEvent>[];
2024
+ walker_pnl_columns: ColumnModel<SignalData$1>[];
2025
+ walker_strategy_columns: ColumnModel<IStrategyResult>[];
2026
+ }>;
1779
2027
 
1780
2028
  /**
1781
2029
  * Statistical data calculated from backtest results.
@@ -3515,6 +3763,91 @@ interface PartialLossContract {
3515
3763
  timestamp: number;
3516
3764
  }
3517
3765
 
3766
+ /**
3767
+ * Contract for breakeven events.
3768
+ *
3769
+ * Emitted by breakevenSubject when a signal's stop-loss is moved to breakeven (entry price).
3770
+ * Used for tracking risk reduction milestones and monitoring strategy safety.
3771
+ *
3772
+ * Events are emitted only once per signal (idempotent - protected by ClientBreakeven state).
3773
+ * Breakeven is triggered when price moves far enough in profit direction to cover transaction costs.
3774
+ *
3775
+ * Consumers:
3776
+ * - BreakevenMarkdownService: Accumulates events for report generation
3777
+ * - User callbacks via listenBreakeven() / listenBreakevenOnce()
3778
+ *
3779
+ * @example
3780
+ * ```typescript
3781
+ * import { listenBreakeven } from "backtest-kit";
3782
+ *
3783
+ * // Listen to all breakeven events
3784
+ * listenBreakeven((event) => {
3785
+ * console.log(`[${event.backtest ? "Backtest" : "Live"}] Signal ${event.data.id} moved to breakeven`);
3786
+ * console.log(`Symbol: ${event.symbol}, Price: ${event.currentPrice}`);
3787
+ * console.log(`Position: ${event.data.position}, Entry: ${event.data.priceOpen}`);
3788
+ * console.log(`Original SL: ${event.data.priceStopLoss}, New SL: ${event.data.priceOpen}`);
3789
+ * });
3790
+ *
3791
+ * // Wait for specific signal to reach breakeven
3792
+ * listenBreakevenOnce(
3793
+ * (event) => event.data.id === "target-signal-id",
3794
+ * (event) => console.log("Signal reached breakeven:", event.data.id)
3795
+ * );
3796
+ * ```
3797
+ */
3798
+ interface BreakevenContract {
3799
+ /**
3800
+ * Trading pair symbol (e.g., "BTCUSDT").
3801
+ * Identifies which market this breakeven event belongs to.
3802
+ */
3803
+ symbol: string;
3804
+ /**
3805
+ * Strategy name that generated this signal.
3806
+ * Identifies which strategy execution this breakeven event belongs to.
3807
+ */
3808
+ strategyName: StrategyName;
3809
+ /**
3810
+ * Exchange name where this signal is being executed.
3811
+ * Identifies which exchange this breakeven event belongs to.
3812
+ */
3813
+ exchangeName: ExchangeName;
3814
+ /**
3815
+ * Frame name where this signal is being executed.
3816
+ * Identifies which frame this breakeven event belongs to (empty string for live mode).
3817
+ */
3818
+ frameName: FrameName;
3819
+ /**
3820
+ * Complete signal row data.
3821
+ * Contains all signal information: id, position, priceOpen, priceTakeProfit, priceStopLoss, etc.
3822
+ */
3823
+ data: ISignalRow;
3824
+ /**
3825
+ * Current market price at which breakeven was triggered.
3826
+ * Used to verify threshold calculation.
3827
+ */
3828
+ currentPrice: number;
3829
+ /**
3830
+ * Execution mode flag.
3831
+ * - true: Event from backtest execution (historical candle data)
3832
+ * - false: Event from live trading (real-time tick)
3833
+ */
3834
+ backtest: boolean;
3835
+ /**
3836
+ * Event timestamp in milliseconds since Unix epoch.
3837
+ *
3838
+ * Timing semantics:
3839
+ * - Live mode: when.getTime() at the moment breakeven was set
3840
+ * - Backtest mode: candle.timestamp of the candle that triggered breakeven
3841
+ *
3842
+ * @example
3843
+ * ```typescript
3844
+ * const eventDate = new Date(event.timestamp);
3845
+ * console.log(`Breakeven set at: ${eventDate.toISOString()}`);
3846
+ * ```
3847
+ */
3848
+ timestamp: number;
3849
+ }
3850
+
3518
3851
  /**
3519
3852
  * Contract for risk rejection events.
3520
3853
  *
@@ -4414,6 +4747,64 @@ declare function listenPartialLoss(fn: (event: PartialLossContract) => void): ()
4414
4747
  * ```
4415
4748
  */
4416
4749
  declare function listenPartialLossOnce(filterFn: (event: PartialLossContract) => boolean, fn: (event: PartialLossContract) => void): () => void;
4750
+ /**
4751
+ * Subscribes to breakeven protection events with queued async processing.
4752
+ *
4753
+ * Emits when a signal's stop-loss is moved to breakeven (entry price).
4754
+ * This happens when price moves far enough in profit direction to cover transaction costs.
4755
+ * Events are processed sequentially in order received, even if callback is async.
4756
+ * Uses queued wrapper to prevent concurrent execution of the callback.
4757
+ *
4758
+ * @param fn - Callback function to handle breakeven events
4759
+ * @returns Unsubscribe function to stop listening to events
4760
+ *
4761
+ * @example
4762
+ * ```typescript
4763
+ * import { listenBreakeven } from "./function/event";
4764
+ *
4765
+ * const unsubscribe = listenBreakeven((event) => {
4766
+ * console.log(`Signal ${event.data.id} reached breakeven`);
4767
+ * console.log(`Symbol: ${event.symbol}, Position: ${event.data.position}`);
4768
+ * console.log(`Entry: ${event.data.priceOpen}, Current: ${event.currentPrice}`);
4769
+ * console.log(`Mode: ${event.backtest ? "Backtest" : "Live"}`);
4770
+ * });
4771
+ *
4772
+ * // Later: stop listening
4773
+ * unsubscribe();
4774
+ * ```
4775
+ */
4776
+ declare function listenBreakeven(fn: (event: BreakevenContract) => void): () => void;
4777
+ /**
4778
+ * Subscribes to filtered breakeven protection events with one-time execution.
4779
+ *
4780
+ * Listens for events matching the filter predicate, then executes callback once
4781
+ * and automatically unsubscribes. Useful for waiting for specific breakeven conditions.
4782
+ *
4783
+ * @param filterFn - Predicate to filter which events trigger the callback
4784
+ * @param fn - Callback function to handle the filtered event (called only once)
4785
+ * @returns Unsubscribe function to cancel the listener before it fires
4786
+ *
4787
+ * @example
4788
+ * ```typescript
4789
+ * import { listenBreakevenOnce } from "./function/event";
4790
+ *
4791
+ * // Wait for first breakeven on any signal
4792
+ * listenBreakevenOnce(
4793
+ * (event) => true,
4794
+ * (event) => console.log("First breakeven reached:", event.data.id)
4795
+ * );
4796
+ *
4797
+ * // Wait for breakeven on BTCUSDT LONG position
4798
+ * const cancel = listenBreakevenOnce(
4799
+ * (event) => event.symbol === "BTCUSDT" && event.data.position === "long",
4800
+ * (event) => console.log("BTCUSDT LONG reached breakeven at", event.currentPrice)
4801
+ * );
4802
+ *
4803
+ * // Cancel if needed before event fires
4804
+ * cancel();
4805
+ * ```
4806
+ */
4807
+ declare function listenBreakevenOnce(filterFn: (event: BreakevenContract) => boolean, fn: (event: BreakevenContract) => void): () => void;
4417
4808
  /**
4418
4809
  * Subscribes to risk rejection events with queued async processing.
4419
4810
  *
@@ -5481,6 +5872,12 @@ interface IPersistBase<Entity extends IEntity | null = IEntity> {
5481
5872
  * @throws Error if write fails
5482
5873
  */
5483
5874
  writeValue(entityId: EntityId, entity: Entity): Promise<void>;
5875
+ /**
5876
+ * Async generator yielding all entity IDs.
5877
+ *
5878
+ * @returns AsyncGenerator yielding entity IDs
5879
+ */
5880
+ keys(): AsyncGenerator<EntityId>;
5484
5881
  }
5485
5882
  /**
5486
5883
  * Base class for file-based persistence with atomic writes.
@@ -5615,9 +6012,10 @@ declare class PersistSignalUtils {
5615
6012
  *
5616
6013
  * @param symbol - Trading pair symbol
5617
6014
  * @param strategyName - Strategy identifier
6015
+ * @param exchangeName - Exchange identifier
5618
6016
  * @returns Promise resolving to signal or null
5619
6017
  */
5620
- readSignalData: (symbol: string, strategyName: StrategyName) => Promise<ISignalRow | null>;
6018
+ readSignalData: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName) => Promise<ISignalRow | null>;
5621
6019
  /**
5622
6020
  * Writes signal data to disk with atomic file writes.
5623
6021
  *
@@ -5627,9 +6025,10 @@ declare class PersistSignalUtils {
5627
6025
  * @param signalRow - Signal data (null to clear)
5628
6026
  * @param symbol - Trading pair symbol
5629
6027
  * @param strategyName - Strategy identifier
6028
+ * @param exchangeName - Exchange identifier
5630
6029
  * @returns Promise that resolves when write is complete
5631
6030
  */
5632
- writeSignalData: (signalRow: ISignalRow | null, symbol: string, strategyName: StrategyName) => Promise<void>;
6031
+ writeSignalData: (signalRow: ISignalRow | null, symbol: string, strategyName: StrategyName, exchangeName: ExchangeName) => Promise<void>;
5633
6032
  }
5634
6033
  /**
5635
6034
  * Global singleton instance of PersistSignalUtils.
@@ -5689,9 +6088,10 @@ declare class PersistRiskUtils {
5689
6088
  * Returns empty Map if no positions exist.
5690
6089
  *
5691
6090
  * @param riskName - Risk profile identifier
6091
+ * @param exchangeName - Exchange identifier
5692
6092
  * @returns Promise resolving to Map of active positions
5693
6093
  */
5694
- readPositionData: (riskName: RiskName) => Promise<RiskData>;
6094
+ readPositionData: (riskName: RiskName, exchangeName: ExchangeName) => Promise<RiskData>;
5695
6095
  /**
5696
6096
  * Writes active positions to disk with atomic file writes.
5697
6097
  *
@@ -5700,9 +6100,10 @@ declare class PersistRiskUtils {
5700
6100
  *
5701
6101
  * @param positions - Map of active positions
5702
6102
  * @param riskName - Risk profile identifier
6103
+ * @param exchangeName - Exchange identifier
5703
6104
  * @returns Promise that resolves when write is complete
5704
6105
  */
5705
- writePositionData: (riskRow: RiskData, riskName: RiskName) => Promise<void>;
6106
+ writePositionData: (riskRow: RiskData, riskName: RiskName, exchangeName: ExchangeName) => Promise<void>;
5706
6107
  }
5707
6108
  /**
5708
6109
  * Global singleton instance of PersistRiskUtils.
@@ -5763,9 +6164,10 @@ declare class PersistScheduleUtils {
5763
6164
  *
5764
6165
  * @param symbol - Trading pair symbol
5765
6166
  * @param strategyName - Strategy identifier
6167
+ * @param exchangeName - Exchange identifier
5766
6168
  * @returns Promise resolving to scheduled signal or null
5767
6169
  */
5768
- readScheduleData: (symbol: string, strategyName: StrategyName) => Promise<IScheduledSignalRow | null>;
6170
+ readScheduleData: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName) => Promise<IScheduledSignalRow | null>;
5769
6171
  /**
5770
6172
  * Writes scheduled signal data to disk with atomic file writes.
5771
6173
  *
@@ -5775,9 +6177,10 @@ declare class PersistScheduleUtils {
5775
6177
  * @param scheduledSignalRow - Scheduled signal data (null to clear)
5776
6178
  * @param symbol - Trading pair symbol
5777
6179
  * @param strategyName - Strategy identifier
6180
+ * @param exchangeName - Exchange identifier
5778
6181
  * @returns Promise that resolves when write is complete
5779
6182
  */
5780
- writeScheduleData: (scheduledSignalRow: IScheduledSignalRow | null, symbol: string, strategyName: StrategyName) => Promise<void>;
6183
+ writeScheduleData: (scheduledSignalRow: IScheduledSignalRow | null, symbol: string, strategyName: StrategyName, exchangeName: ExchangeName) => Promise<void>;
5781
6184
  }
5782
6185
  /**
5783
6186
  * Global singleton instance of PersistScheduleUtils.
@@ -5838,9 +6241,11 @@ declare class PersistPartialUtils {
5838
6241
  *
5839
6242
  * @param symbol - Trading pair symbol
5840
6243
  * @param strategyName - Strategy identifier
6244
+ * @param signalId - Signal identifier
6245
+ * @param exchangeName - Exchange identifier
5841
6246
  * @returns Promise resolving to partial data record
5842
6247
  */
5843
- readPartialData: (symbol: string, strategyName: StrategyName) => Promise<PartialData>;
6248
+ readPartialData: (symbol: string, strategyName: StrategyName, signalId: string, exchangeName: ExchangeName) => Promise<PartialData>;
5844
6249
  /**
5845
6250
  * Writes partial data to disk with atomic file writes.
5846
6251
  *
@@ -5850,9 +6255,11 @@ declare class PersistPartialUtils {
5850
6255
  * @param partialData - Record of signal IDs to partial data
5851
6256
  * @param symbol - Trading pair symbol
5852
6257
  * @param strategyName - Strategy identifier
6258
+ * @param signalId - Signal identifier
6259
+ * @param exchangeName - Exchange identifier
5853
6260
  * @returns Promise that resolves when write is complete
5854
6261
  */
5855
- writePartialData: (partialData: PartialData, symbol: string, strategyName: StrategyName) => Promise<void>;
6262
+ writePartialData: (partialData: PartialData, symbol: string, strategyName: StrategyName, signalId: string, exchangeName: ExchangeName) => Promise<void>;
5856
6263
  }
5857
6264
  /**
5858
6265
  * Global singleton instance of PersistPartialUtils.
@@ -5871,6 +6278,120 @@ declare class PersistPartialUtils {
5871
6278
  * ```
5872
6279
  */
5873
6280
  declare const PersistPartialAdapter: PersistPartialUtils;
6281
+ /**
6282
+ * Type for persisted breakeven data.
6283
+ * Stores breakeven state (reached flag) for each signal ID.
6284
+ */
6285
+ type BreakevenData = Record<string, IBreakevenData>;
6286
+ /**
6287
+ * Persistence utility class for breakeven state management.
6288
+ *
6289
+ * Handles reading and writing breakeven state to disk.
6290
+ * Uses memoized PersistBase instances per symbol-strategy pair.
6291
+ *
6292
+ * Features:
6293
+ * - Atomic file writes via PersistBase.writeValue()
6294
+ * - Lazy initialization on first access
6295
+ * - Singleton pattern for global access
6296
+ * - Custom adapter support via usePersistBreakevenAdapter()
6297
+ *
6298
+ * File structure:
6299
+ * ```
6300
+ * ./dump/data/breakeven/
6301
+ * ├── BTCUSDT_my-strategy/
6302
+ * │ └── state.json // { "signal-id-1": { reached: true }, ... }
6303
+ * └── ETHUSDT_other-strategy/
6304
+ * └── state.json
6305
+ * ```
6306
+ *
6307
+ * @example
6308
+ * ```typescript
6309
+ * // Read breakeven data
6310
+ * const breakevenData = await PersistBreakevenAdapter.readBreakevenData("BTCUSDT", "my-strategy");
6311
+ * // Returns: { "signal-id": { reached: true }, ... }
6312
+ *
6313
+ * // Write breakeven data
6314
+ * await PersistBreakevenAdapter.writeBreakevenData(breakevenData, "BTCUSDT", "my-strategy");
6315
+ * ```
6316
+ */
6317
+ declare class PersistBreakevenUtils {
6318
+ /**
6319
+ * Factory for creating PersistBase instances.
6320
+ * Can be replaced via usePersistBreakevenAdapter().
6321
+ */
6322
+ private PersistBreakevenFactory;
6323
+ /**
6324
+ * Memoized storage factory for breakeven data.
6325
+ * Creates one PersistBase instance per symbol-strategy-exchange combination.
6326
+ * Key format: "symbol:strategyName:exchangeName"
6327
+ *
6328
+ * @param symbol - Trading pair symbol
6329
+ * @param strategyName - Strategy identifier
6330
+ * @param exchangeName - Exchange identifier
6331
+ * @returns PersistBase instance for this symbol-strategy-exchange combination
6332
+ */
6333
+ private getBreakevenStorage;
6334
+ /**
6335
+ * Registers a custom persistence adapter.
6336
+ *
6337
+ * @param Ctor - Custom PersistBase constructor
6338
+ *
6339
+ * @example
6340
+ * ```typescript
6341
+ * class RedisPersist extends PersistBase {
6342
+ * async readValue(id) { return JSON.parse(await redis.get(id)); }
6343
+ * async writeValue(id, entity) { await redis.set(id, JSON.stringify(entity)); }
6344
+ * }
6345
+ * PersistBreakevenAdapter.usePersistBreakevenAdapter(RedisPersist);
6346
+ * ```
6347
+ */
6348
+ usePersistBreakevenAdapter(Ctor: TPersistBaseCtor<string, BreakevenData>): void;
6349
+ /**
6350
+ * Reads persisted breakeven data for a symbol and strategy.
6351
+ *
6352
+ * Called by ClientBreakeven.waitForInit() to restore state.
6353
+ * Returns empty object if no breakeven data exists.
6354
+ *
6355
+ * @param symbol - Trading pair symbol
6356
+ * @param strategyName - Strategy identifier
6357
+ * @param signalId - Signal identifier
6358
+ * @param exchangeName - Exchange identifier
6359
+ * @returns Promise resolving to breakeven data record
6360
+ */
6361
+ readBreakevenData: (symbol: string, strategyName: StrategyName, signalId: string, exchangeName: ExchangeName) => Promise<BreakevenData>;
6362
+ /**
6363
+ * Writes breakeven data to disk.
6364
+ *
6365
+ * Called by ClientBreakeven._persistState() after state changes.
6366
+ * Creates directory and file if they don't exist.
6367
+ * Uses atomic writes to prevent data corruption.
6368
+ *
6369
+ * @param breakevenData - Breakeven data record to persist
6370
+ * @param symbol - Trading pair symbol
6371
+ * @param strategyName - Strategy identifier
6372
+ * @param signalId - Signal identifier
6373
+ * @param exchangeName - Exchange identifier
6374
+ * @returns Promise that resolves when write is complete
6375
+ */
6376
+ writeBreakevenData: (breakevenData: BreakevenData, symbol: string, strategyName: StrategyName, signalId: string, exchangeName: ExchangeName) => Promise<void>;
6377
+ }
6378
+ /**
6379
+ * Global singleton instance of PersistBreakevenUtils.
6380
+ * Used by ClientBreakeven for breakeven state persistence.
6381
+ *
6382
+ * @example
6383
+ * ```typescript
6384
+ * // Custom adapter
6385
+ * PersistBreakevenAdapter.usePersistBreakevenAdapter(RedisPersist);
6386
+ *
6387
+ * // Read breakeven data
6388
+ * const breakevenData = await PersistBreakevenAdapter.readBreakevenData("BTCUSDT", "my-strategy");
6389
+ *
6390
+ * // Write breakeven data
6391
+ * await PersistBreakevenAdapter.writeBreakevenData(breakevenData, "BTCUSDT", "my-strategy");
6392
+ * ```
6393
+ */
6394
+ declare const PersistBreakevenAdapter: PersistBreakevenUtils;
5874
6395
 
5875
6396
  /**
5876
6397
  * Type alias for column configuration used in backtest markdown reports.
@@ -5903,7 +6424,7 @@ declare const PersistPartialAdapter: PersistPartialUtils;
5903
6424
  * @see ColumnModel for the base interface
5904
6425
  * @see IStrategyTickResultClosed for the signal data structure
5905
6426
  */
5906
- type Columns$6 = ColumnModel<IStrategyTickResultClosed>;
6427
+ type Columns$7 = ColumnModel<IStrategyTickResultClosed>;
5907
6428
  /**
5908
6429
  * Service for generating and saving backtest markdown reports.
5909
6430
  *
@@ -5997,7 +6518,7 @@ declare class BacktestMarkdownService {
5997
6518
  * console.log(markdown);
5998
6519
  * ```
5999
6520
  */
6000
- getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$6[]) => Promise<string>;
6521
+ getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$7[]) => Promise<string>;
6001
6522
  /**
6002
6523
  * Saves symbol-strategy report to disk.
6003
6524
  * Creates directory if it doesn't exist.
@@ -6022,7 +6543,7 @@ declare class BacktestMarkdownService {
6022
6543
  * await service.dump("BTCUSDT", "my-strategy", "binance", "1h", true, "./custom/path");
6023
6544
  * ```
6024
6545
  */
6025
- dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$6[]) => Promise<void>;
6546
+ dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$7[]) => Promise<void>;
6026
6547
  /**
6027
6548
  * Clears accumulated signal data from storage.
6028
6549
  * If payload is provided, clears only that specific symbol-strategy-exchange-frame-backtest combination's data.
@@ -6316,6 +6837,32 @@ declare class BacktestUtils {
6316
6837
  exchangeName: ExchangeName;
6317
6838
  frameName: FrameName;
6318
6839
  }) => Promise<void>;
6840
+ /**
6841
+ * Moves stop-loss to breakeven when price reaches threshold.
6842
+ *
6843
+ * Moves SL to entry price (zero-risk position) when current price has moved
6844
+ * far enough in profit direction. Threshold is calculated as: (CC_PERCENT_SLIPPAGE + CC_PERCENT_FEE) * 2
6845
+ *
6846
+ * @param symbol - Trading pair symbol
6847
+ * @param currentPrice - Current market price to check threshold
6848
+ * @param context - Strategy context with strategyName, exchangeName, frameName
6849
+ * @returns Promise<boolean> - true if breakeven was set, false otherwise
6850
+ *
6851
+ * @example
6852
+ * ```typescript
6853
+ * const moved = await Backtest.breakeven(
6854
+ * "BTCUSDT",
6855
+ * 112,
6856
+ * { strategyName: "my-strategy", exchangeName: "binance", frameName: "1h" }
6857
+ * );
6858
+ * console.log(moved); // true (SL moved to entry price)
6859
+ * ```
6860
+ */
6861
+ breakeven: (symbol: string, currentPrice: number, context: {
6862
+ strategyName: StrategyName;
6863
+ exchangeName: ExchangeName;
6864
+ frameName: FrameName;
6865
+ }) => Promise<boolean>;
6319
6866
  /**
6320
6867
  * Gets statistical data from all closed signals for a symbol-strategy pair.
6321
6868
  *
@@ -6362,7 +6909,7 @@ declare class BacktestUtils {
6362
6909
  strategyName: StrategyName;
6363
6910
  exchangeName: ExchangeName;
6364
6911
  frameName: FrameName;
6365
- }, columns?: Columns$6[]) => Promise<string>;
6912
+ }, columns?: Columns$7[]) => Promise<string>;
6366
6913
  /**
6367
6914
  * Saves strategy report to disk.
6368
6915
  *
@@ -6393,7 +6940,7 @@ declare class BacktestUtils {
6393
6940
  strategyName: StrategyName;
6394
6941
  exchangeName: ExchangeName;
6395
6942
  frameName: FrameName;
6396
- }, path?: string, columns?: Columns$6[]) => Promise<void>;
6943
+ }, path?: string, columns?: Columns$7[]) => Promise<void>;
6397
6944
  /**
6398
6945
  * Lists all active backtest instances with their current status.
6399
6946
  *
@@ -6467,7 +7014,7 @@ declare const Backtest: BacktestUtils;
6467
7014
  * @see ColumnModel for the base interface
6468
7015
  * @see TickEvent for the event data structure
6469
7016
  */
6470
- type Columns$5 = ColumnModel<TickEvent>;
7017
+ type Columns$6 = ColumnModel<TickEvent>;
6471
7018
  /**
6472
7019
  * Service for generating and saving live trading markdown reports.
6473
7020
  *
@@ -6566,7 +7113,7 @@ declare class LiveMarkdownService {
6566
7113
  * console.log(markdown);
6567
7114
  * ```
6568
7115
  */
6569
- getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$5[]) => Promise<string>;
7116
+ getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$6[]) => Promise<string>;
6570
7117
  /**
6571
7118
  * Saves symbol-strategy report to disk.
6572
7119
  * Creates directory if it doesn't exist.
@@ -6591,7 +7138,7 @@ declare class LiveMarkdownService {
6591
7138
  * await service.dump("BTCUSDT", "my-strategy", "binance", "1h", false, "./custom/path");
6592
7139
  * ```
6593
7140
  */
6594
- dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$5[]) => Promise<void>;
7141
+ dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$6[]) => Promise<void>;
6595
7142
  /**
6596
7143
  * Clears accumulated event data from storage.
6597
7144
  * If payload is provided, clears only that specific symbol-strategy-exchange-frame-backtest combination's data.
@@ -6881,6 +7428,31 @@ declare class LiveUtils {
6881
7428
  strategyName: StrategyName;
6882
7429
  exchangeName: ExchangeName;
6883
7430
  }) => Promise<void>;
7431
+ /**
7432
+ * Moves stop-loss to breakeven when price reaches threshold.
7433
+ *
7434
+ * Moves SL to entry price (zero-risk position) when current price has moved
7435
+ * far enough in profit direction. Threshold is calculated as: (CC_PERCENT_SLIPPAGE + CC_PERCENT_FEE) * 2
7436
+ *
7437
+ * @param symbol - Trading pair symbol
7438
+ * @param currentPrice - Current market price to check threshold
7439
+ * @param context - Strategy context with strategyName and exchangeName
7440
+ * @returns Promise<boolean> - true if breakeven was set, false otherwise
7441
+ *
7442
+ * @example
7443
+ * ```typescript
7444
+ * const moved = await Live.breakeven(
7445
+ * "BTCUSDT",
7446
+ * 112,
7447
+ * { strategyName: "my-strategy", exchangeName: "binance" }
7448
+ * );
7449
+ * console.log(moved); // true (SL moved to entry price)
7450
+ * ```
7451
+ */
7452
+ breakeven: (symbol: string, currentPrice: number, context: {
7453
+ strategyName: StrategyName;
7454
+ exchangeName: ExchangeName;
7455
+ }) => Promise<boolean>;
6884
7456
  /**
6885
7457
  * Gets statistical data from all live trading events for a symbol-strategy pair.
6886
7458
  *
@@ -6925,7 +7497,7 @@ declare class LiveUtils {
6925
7497
  getReport: (symbol: string, context: {
6926
7498
  strategyName: StrategyName;
6927
7499
  exchangeName: ExchangeName;
6928
- }, columns?: Columns$5[]) => Promise<string>;
7500
+ }, columns?: Columns$6[]) => Promise<string>;
6929
7501
  /**
6930
7502
  * Saves strategy report to disk.
6931
7503
  *
@@ -6955,7 +7527,7 @@ declare class LiveUtils {
6955
7527
  dump: (symbol: string, context: {
6956
7528
  strategyName: StrategyName;
6957
7529
  exchangeName: ExchangeName;
6958
- }, path?: string, columns?: Columns$5[]) => Promise<void>;
7530
+ }, path?: string, columns?: Columns$6[]) => Promise<void>;
6959
7531
  /**
6960
7532
  * Lists all active live trading instances with their current status.
6961
7533
  *
@@ -7025,7 +7597,7 @@ declare const Live: LiveUtils;
7025
7597
  * @see ColumnModel for the base interface
7026
7598
  * @see ScheduledEvent for the event data structure
7027
7599
  */
7028
- type Columns$4 = ColumnModel<ScheduledEvent>;
7600
+ type Columns$5 = ColumnModel<ScheduledEvent>;
7029
7601
  /**
7030
7602
  * Service for generating and saving scheduled signals markdown reports.
7031
7603
  *
@@ -7108,7 +7680,7 @@ declare class ScheduleMarkdownService {
7108
7680
  * console.log(markdown);
7109
7681
  * ```
7110
7682
  */
7111
- getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$4[]) => Promise<string>;
7683
+ getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$5[]) => Promise<string>;
7112
7684
  /**
7113
7685
  * Saves symbol-strategy report to disk.
7114
7686
  * Creates directory if it doesn't exist.
@@ -7133,7 +7705,7 @@ declare class ScheduleMarkdownService {
7133
7705
  * await service.dump("BTCUSDT", "my-strategy", "binance", "1h", false, "./custom/path");
7134
7706
  * ```
7135
7707
  */
7136
- dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$4[]) => Promise<void>;
7708
+ dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$5[]) => Promise<void>;
7137
7709
  /**
7138
7710
  * Clears accumulated event data from storage.
7139
7711
  * If payload is provided, clears only that specific symbol-strategy-exchange-frame-backtest combination's data.
@@ -7240,7 +7812,7 @@ declare class ScheduleUtils {
7240
7812
  strategyName: StrategyName;
7241
7813
  exchangeName: ExchangeName;
7242
7814
  frameName: FrameName;
7243
- }, backtest?: boolean, columns?: Columns$4[]) => Promise<string>;
7815
+ }, backtest?: boolean, columns?: Columns$5[]) => Promise<string>;
7244
7816
  /**
7245
7817
  * Saves strategy report to disk.
7246
7818
  *
@@ -7262,7 +7834,7 @@ declare class ScheduleUtils {
7262
7834
  strategyName: StrategyName;
7263
7835
  exchangeName: ExchangeName;
7264
7836
  frameName: FrameName;
7265
- }, backtest?: boolean, path?: string, columns?: Columns$4[]) => Promise<void>;
7837
+ }, backtest?: boolean, path?: string, columns?: Columns$5[]) => Promise<void>;
7266
7838
  }
7267
7839
  /**
7268
7840
  * Singleton instance of ScheduleUtils for convenient scheduled signals reporting.
@@ -7308,7 +7880,7 @@ declare const Schedule: ScheduleUtils;
7308
7880
  * @see ColumnModel for the base interface
7309
7881
  * @see MetricStats for the metric data structure
7310
7882
  */
7311
- type Columns$3 = ColumnModel<MetricStats>;
7883
+ type Columns$4 = ColumnModel<MetricStats>;
7312
7884
  /**
7313
7885
  * Service for collecting and analyzing performance metrics.
7314
7886
  *
@@ -7387,7 +7959,7 @@ declare class PerformanceMarkdownService {
7387
7959
  * console.log(markdown);
7388
7960
  * ```
7389
7961
  */
7390
- getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$3[]) => Promise<string>;
7962
+ getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$4[]) => Promise<string>;
7391
7963
  /**
7392
7964
  * Saves performance report to disk.
7393
7965
  *
@@ -7408,7 +7980,7 @@ declare class PerformanceMarkdownService {
7408
7980
  * await performanceService.dump("BTCUSDT", "my-strategy", "binance", "1h", false, "./custom/path");
7409
7981
  * ```
7410
7982
  */
7411
- dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$3[]) => Promise<void>;
7983
+ dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$4[]) => Promise<void>;
7412
7984
  /**
7413
7985
  * Clears accumulated performance data from storage.
7414
7986
  *
@@ -7526,7 +8098,7 @@ declare class Performance {
7526
8098
  strategyName: StrategyName;
7527
8099
  exchangeName: ExchangeName;
7528
8100
  frameName: FrameName;
7529
- }, backtest?: boolean, columns?: Columns$3[]): Promise<string>;
8101
+ }, backtest?: boolean, columns?: Columns$4[]): Promise<string>;
7530
8102
  /**
7531
8103
  * Saves performance report to disk.
7532
8104
  *
@@ -7551,7 +8123,7 @@ declare class Performance {
7551
8123
  strategyName: StrategyName;
7552
8124
  exchangeName: ExchangeName;
7553
8125
  frameName: FrameName;
7554
- }, backtest?: boolean, path?: string, columns?: Columns$3[]): Promise<void>;
8126
+ }, backtest?: boolean, path?: string, columns?: Columns$4[]): Promise<void>;
7555
8127
  }
7556
8128
 
7557
8129
  /**
@@ -7971,7 +8543,7 @@ declare const Walker: WalkerUtils;
7971
8543
  * @see ColumnModel for the base interface
7972
8544
  * @see IHeatmapRow for the row data structure
7973
8545
  */
7974
- type Columns$2 = ColumnModel<IHeatmapRow>;
8546
+ type Columns$3 = ColumnModel<IHeatmapRow>;
7975
8547
  /**
7976
8548
  * Portfolio Heatmap Markdown Service.
7977
8549
  *
@@ -8064,7 +8636,7 @@ declare class HeatMarkdownService {
8064
8636
  * // ...
8065
8637
  * ```
8066
8638
  */
8067
- getReport: (strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$2[]) => Promise<string>;
8639
+ getReport: (strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$3[]) => Promise<string>;
8068
8640
  /**
8069
8641
  * Saves heatmap report to disk.
8070
8642
  *
@@ -8089,7 +8661,7 @@ declare class HeatMarkdownService {
8089
8661
  * await service.dump("my-strategy", "binance", "frame1", true, "./reports");
8090
8662
  * ```
8091
8663
  */
8092
- dump: (strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$2[]) => Promise<void>;
8664
+ dump: (strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$3[]) => Promise<void>;
8093
8665
  /**
8094
8666
  * Clears accumulated heatmap data from storage.
8095
8667
  * If payload is provided, clears only that exchangeName+frameName+backtest combination's data.
@@ -8236,7 +8808,7 @@ declare class HeatUtils {
8236
8808
  strategyName: StrategyName;
8237
8809
  exchangeName: ExchangeName;
8238
8810
  frameName: FrameName;
8239
- }, backtest?: boolean, columns?: Columns$2[]) => Promise<string>;
8811
+ }, backtest?: boolean, columns?: Columns$3[]) => Promise<string>;
8240
8812
  /**
8241
8813
  * Saves heatmap report to disk for a strategy.
8242
8814
  *
@@ -8269,7 +8841,7 @@ declare class HeatUtils {
8269
8841
  strategyName: StrategyName;
8270
8842
  exchangeName: ExchangeName;
8271
8843
  frameName: FrameName;
8272
- }, backtest?: boolean, path?: string, columns?: Columns$2[]) => Promise<void>;
8844
+ }, backtest?: boolean, path?: string, columns?: Columns$3[]) => Promise<void>;
8273
8845
  }
8274
8846
  /**
8275
8847
  * Singleton instance of HeatUtils for convenient heatmap operations.
@@ -8500,7 +9072,7 @@ declare const Optimizer: OptimizerUtils;
8500
9072
  * @see ColumnModel for the base interface
8501
9073
  * @see PartialEvent for the event data structure
8502
9074
  */
8503
- type Columns$1 = ColumnModel<PartialEvent>;
9075
+ type Columns$2 = ColumnModel<PartialEvent>;
8504
9076
  /**
8505
9077
  * Service for generating and saving partial profit/loss markdown reports.
8506
9078
  *
@@ -8594,7 +9166,7 @@ declare class PartialMarkdownService {
8594
9166
  * console.log(markdown);
8595
9167
  * ```
8596
9168
  */
8597
- getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$1[]) => Promise<string>;
9169
+ getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$2[]) => Promise<string>;
8598
9170
  /**
8599
9171
  * Saves symbol-strategy report to disk.
8600
9172
  * Creates directory if it doesn't exist.
@@ -8619,7 +9191,7 @@ declare class PartialMarkdownService {
8619
9191
  * await service.dump("BTCUSDT", "my-strategy", "binance", "1h", false, "./custom/path");
8620
9192
  * ```
8621
9193
  */
8622
- dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$1[]) => Promise<void>;
9194
+ dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$2[]) => Promise<void>;
8623
9195
  /**
8624
9196
  * Clears accumulated event data from storage.
8625
9197
  * If payload is provided, clears only that specific symbol-strategy-exchange-frame-backtest combination's data.
@@ -8772,7 +9344,7 @@ declare class PartialUtils {
8772
9344
  strategyName: StrategyName;
8773
9345
  exchangeName: ExchangeName;
8774
9346
  frameName: FrameName;
8775
- }, backtest?: boolean, columns?: Columns$1[]) => Promise<string>;
9347
+ }, backtest?: boolean, columns?: Columns$2[]) => Promise<string>;
8776
9348
  /**
8777
9349
  * Generates and saves markdown report to file.
8778
9350
  *
@@ -8809,7 +9381,7 @@ declare class PartialUtils {
8809
9381
  strategyName: StrategyName;
8810
9382
  exchangeName: ExchangeName;
8811
9383
  frameName: FrameName;
8812
- }, backtest?: boolean, path?: string, columns?: Columns$1[]) => Promise<void>;
9384
+ }, backtest?: boolean, path?: string, columns?: Columns$2[]) => Promise<void>;
8813
9385
  }
8814
9386
  /**
8815
9387
  * Global singleton instance of PartialUtils.
@@ -8937,7 +9509,7 @@ declare const Constant: ConstantUtils;
8937
9509
  * @see ColumnModel for the base interface
8938
9510
  * @see RiskEvent for the event data structure
8939
9511
  */
8940
- type Columns = ColumnModel<RiskEvent>;
9512
+ type Columns$1 = ColumnModel<RiskEvent>;
8941
9513
  /**
8942
9514
  * Service for generating and saving risk rejection markdown reports.
8943
9515
  *
@@ -9018,7 +9590,7 @@ declare class RiskMarkdownService {
9018
9590
  * console.log(markdown);
9019
9591
  * ```
9020
9592
  */
9021
- getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns[]) => Promise<string>;
9593
+ getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns$1[]) => Promise<string>;
9022
9594
  /**
9023
9595
  * Saves symbol-strategy report to disk.
9024
9596
  * Creates directory if it doesn't exist.
@@ -9043,7 +9615,7 @@ declare class RiskMarkdownService {
9043
9615
  * await service.dump("BTCUSDT", "my-strategy", "binance", "1h", false, "./custom/path");
9044
9616
  * ```
9045
9617
  */
9046
- dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns[]) => Promise<void>;
9618
+ dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns$1[]) => Promise<void>;
9047
9619
  /**
9048
9620
  * Clears accumulated event data from storage.
9049
9621
  * If payload is provided, clears only that specific symbol-strategy-exchange-frame-backtest combination's data.
@@ -9198,7 +9770,7 @@ declare class RiskUtils {
9198
9770
  strategyName: StrategyName;
9199
9771
  exchangeName: ExchangeName;
9200
9772
  frameName: FrameName;
9201
- }, backtest?: boolean, columns?: Columns[]) => Promise<string>;
9773
+ }, backtest?: boolean, columns?: Columns$1[]) => Promise<string>;
9202
9774
  /**
9203
9775
  * Generates and saves markdown report to file.
9204
9776
  *
@@ -9235,7 +9807,7 @@ declare class RiskUtils {
9235
9807
  strategyName: StrategyName;
9236
9808
  exchangeName: ExchangeName;
9237
9809
  frameName: FrameName;
9238
- }, backtest?: boolean, path?: string, columns?: Columns[]) => Promise<void>;
9810
+ }, backtest?: boolean, path?: string, columns?: Columns$1[]) => Promise<void>;
9239
9811
  }
9240
9812
  /**
9241
9813
  * Global singleton instance of RiskUtils.
@@ -9524,60 +10096,397 @@ declare class NotificationUtils {
9524
10096
  /** Internal instance containing business logic */
9525
10097
  private _instance;
9526
10098
  /**
9527
- * Returns all notifications in chronological order (newest first).
10099
+ * Returns all notifications in chronological order (newest first).
10100
+ *
10101
+ * @returns Array of strongly-typed notification objects
10102
+ *
10103
+ * @example
10104
+ * ```typescript
10105
+ * const notifications = await Notification.getData();
10106
+ *
10107
+ * notifications.forEach(notification => {
10108
+ * switch (notification.type) {
10109
+ * case "signal.closed":
10110
+ * console.log(`${notification.symbol}: ${notification.pnlPercentage}%`);
10111
+ * break;
10112
+ * case "partial.loss":
10113
+ * if (notification.level >= 30) {
10114
+ * console.warn(`High loss: ${notification.symbol}`);
10115
+ * }
10116
+ * break;
10117
+ * }
10118
+ * });
10119
+ * ```
10120
+ */
10121
+ getData(): Promise<NotificationModel[]>;
10122
+ /**
10123
+ * Clears all notification history.
10124
+ *
10125
+ * @example
10126
+ * ```typescript
10127
+ * await Notification.clear();
10128
+ * ```
10129
+ */
10130
+ clear(): Promise<void>;
10131
+ }
10132
+ /**
10133
+ * Singleton instance of NotificationUtils for convenient notification access.
10134
+ *
10135
+ * @example
10136
+ * ```typescript
10137
+ * import { Notification } from "./classes/Notification";
10138
+ *
10139
+ * // Get all notifications
10140
+ * const all = await Notification.getData();
10141
+ *
10142
+ * // Filter by type using type discrimination
10143
+ * const closedSignals = all.filter(n => n.type === "signal.closed");
10144
+ * const highLosses = all.filter(n =>
10145
+ * n.type === "partial.loss" && n.level >= 30
10146
+ * );
10147
+ *
10148
+ * // Clear history
10149
+ * await Notification.clear();
10150
+ * ```
10151
+ */
10152
+ declare const Notification: NotificationUtils;
10153
+
10154
+ /**
10155
+ * Type alias for column configuration used in breakeven markdown reports.
10156
+ *
10157
+ * Represents a column model specifically designed to format and display
10158
+ * breakeven events in markdown tables.
10159
+ *
10160
+ * @typeParam BreakevenEvent - The breakeven event data type containing
10161
+ * signal information, symbol, and timing details
10162
+ *
10163
+ * @example
10164
+ * ```typescript
10165
+ * // Column to display symbol
10166
+ * const symbolColumn: Columns = {
10167
+ * key: "symbol",
10168
+ * label: "Symbol",
10169
+ * format: (event) => event.symbol,
10170
+ * isVisible: () => true
10171
+ * };
10172
+ *
10173
+ * // Column to display price when breakeven was reached
10174
+ * const priceColumn: Columns = {
10175
+ * key: "currentPrice",
10176
+ * label: "Price",
10177
+ * format: (event) => event.currentPrice.toString(),
10178
+ * isVisible: () => true
10179
+ * };
10180
+ * ```
10181
+ *
10182
+ * @see ColumnModel for the base interface
10183
+ * @see BreakevenEvent for the event data structure
10184
+ */
10185
+ type Columns = ColumnModel<BreakevenEvent>;
10186
+ /**
10187
+ * Service for generating and saving breakeven markdown reports.
10188
+ *
10189
+ * Features:
10190
+ * - Listens to breakeven events via breakevenSubject
10191
+ * - Accumulates all events per symbol-strategy pair
10192
+ * - Generates markdown tables with detailed event information
10193
+ * - Provides statistics (total breakeven events)
10194
+ * - Saves reports to disk in dump/breakeven/{symbol}_{strategyName}.md
10195
+ *
10196
+ * @example
10197
+ * ```typescript
10198
+ * const service = new BreakevenMarkdownService();
10199
+ *
10200
+ * // Service automatically subscribes to subjects on init
10201
+ * // No manual callback setup needed
10202
+ *
10203
+ * // Later: generate and save report
10204
+ * await service.dump("BTCUSDT", "my-strategy");
10205
+ * ```
10206
+ */
10207
+ declare class BreakevenMarkdownService {
10208
+ /** Logger service for debug output */
10209
+ private readonly loggerService;
10210
+ /**
10211
+ * Memoized function to get or create ReportStorage for a symbol-strategy-exchange-frame-backtest combination.
10212
+ * Each combination gets its own isolated storage instance.
10213
+ */
10214
+ private getStorage;
10215
+ /**
10216
+ * Processes breakeven events and accumulates them.
10217
+ * Should be called from breakevenSubject subscription.
10218
+ *
10219
+ * @param data - Breakeven event data with frameName wrapper
10220
+ *
10221
+ * @example
10222
+ * ```typescript
10223
+ * const service = new BreakevenMarkdownService();
10224
+ * // Service automatically subscribes in init()
10225
+ * ```
10226
+ */
10227
+ private tickBreakeven;
10228
+ /**
10229
+ * Gets statistical data from all breakeven events for a symbol-strategy pair.
10230
+ * Delegates to ReportStorage.getData().
10231
+ *
10232
+ * @param symbol - Trading pair symbol to get data for
10233
+ * @param strategyName - Strategy name to get data for
10234
+ * @param exchangeName - Exchange name
10235
+ * @param frameName - Frame name
10236
+ * @param backtest - True if backtest mode, false if live mode
10237
+ * @returns Statistical data object with all metrics
10238
+ *
10239
+ * @example
10240
+ * ```typescript
10241
+ * const service = new BreakevenMarkdownService();
10242
+ * const stats = await service.getData("BTCUSDT", "my-strategy", "binance", "1h", false);
10243
+ * console.log(stats.totalEvents);
10244
+ * ```
10245
+ */
10246
+ getData: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean) => Promise<BreakevenStatisticsModel>;
10247
+ /**
10248
+ * Generates markdown report with all breakeven events for a symbol-strategy pair.
10249
+ * Delegates to ReportStorage.getReport().
10250
+ *
10251
+ * @param symbol - Trading pair symbol to generate report for
10252
+ * @param strategyName - Strategy name to generate report for
10253
+ * @param exchangeName - Exchange name
10254
+ * @param frameName - Frame name
10255
+ * @param backtest - True if backtest mode, false if live mode
10256
+ * @param columns - Column configuration for formatting the table
10257
+ * @returns Markdown formatted report string with table of all events
10258
+ *
10259
+ * @example
10260
+ * ```typescript
10261
+ * const service = new BreakevenMarkdownService();
10262
+ * const markdown = await service.getReport("BTCUSDT", "my-strategy", "binance", "1h", false);
10263
+ * console.log(markdown);
10264
+ * ```
10265
+ */
10266
+ getReport: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, columns?: Columns[]) => Promise<string>;
10267
+ /**
10268
+ * Saves symbol-strategy report to disk.
10269
+ * Creates directory if it doesn't exist.
10270
+ * Delegates to ReportStorage.dump().
10271
+ *
10272
+ * @param symbol - Trading pair symbol to save report for
10273
+ * @param strategyName - Strategy name to save report for
10274
+ * @param exchangeName - Exchange name
10275
+ * @param frameName - Frame name
10276
+ * @param backtest - True if backtest mode, false if live mode
10277
+ * @param path - Directory path to save report (default: "./dump/breakeven")
10278
+ * @param columns - Column configuration for formatting the table
10279
+ *
10280
+ * @example
10281
+ * ```typescript
10282
+ * const service = new BreakevenMarkdownService();
10283
+ *
10284
+ * // Save to default path: ./dump/breakeven/BTCUSDT_my-strategy.md
10285
+ * await service.dump("BTCUSDT", "my-strategy", "binance", "1h", false);
10286
+ *
10287
+ * // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
10288
+ * await service.dump("BTCUSDT", "my-strategy", "binance", "1h", false, "./custom/path");
10289
+ * ```
10290
+ */
10291
+ dump: (symbol: string, strategyName: StrategyName, exchangeName: ExchangeName, frameName: FrameName, backtest: boolean, path?: string, columns?: Columns[]) => Promise<void>;
10292
+ /**
10293
+ * Clears accumulated event data from storage.
10294
+ * If payload is provided, clears only that specific symbol-strategy-exchange-frame-backtest combination's data.
10295
+ * If nothing is provided, clears all data.
10296
+ *
10297
+ * @param payload - Optional payload with symbol, strategyName, exchangeName, frameName, backtest
10298
+ *
10299
+ * @example
10300
+ * ```typescript
10301
+ * const service = new BreakevenMarkdownService();
10302
+ *
10303
+ * // Clear specific combination
10304
+ * await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy", exchangeName: "binance", frameName: "1h", backtest: false });
10305
+ *
10306
+ * // Clear all data
10307
+ * await service.clear();
10308
+ * ```
10309
+ */
10310
+ clear: (payload?: {
10311
+ symbol: string;
10312
+ strategyName: StrategyName;
10313
+ exchangeName: ExchangeName;
10314
+ frameName: FrameName;
10315
+ backtest: boolean;
10316
+ }) => Promise<void>;
10317
+ /**
10318
+ * Initializes the service by subscribing to breakeven events.
10319
+ * Uses singleshot to ensure initialization happens only once.
10320
+ * Automatically called on first use.
10321
+ *
10322
+ * @example
10323
+ * ```typescript
10324
+ * const service = new BreakevenMarkdownService();
10325
+ * await service.init(); // Subscribe to breakeven events
10326
+ * ```
10327
+ */
10328
+ protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
10329
+ /**
10330
+ * Function to unsubscribe from breakeven events.
10331
+ * Assigned during init().
10332
+ */
10333
+ unsubscribe: Function;
10334
+ }
10335
+
10336
+ /**
10337
+ * Utility class for accessing breakeven protection reports and statistics.
10338
+ *
10339
+ * Provides static-like methods (via singleton instance) to retrieve data
10340
+ * accumulated by BreakevenMarkdownService from breakeven events.
10341
+ *
10342
+ * Features:
10343
+ * - Statistical data extraction (total breakeven events count)
10344
+ * - Markdown report generation with event tables
10345
+ * - File export to disk
10346
+ *
10347
+ * Data source:
10348
+ * - BreakevenMarkdownService listens to breakevenSubject
10349
+ * - Accumulates events in ReportStorage (max 250 events per symbol-strategy pair)
10350
+ * - Events include: timestamp, symbol, strategyName, signalId, position, priceOpen, currentPrice, mode
10351
+ *
10352
+ * @example
10353
+ * ```typescript
10354
+ * import { Breakeven } from "./classes/Breakeven";
10355
+ *
10356
+ * // Get statistical data for BTCUSDT:my-strategy
10357
+ * const stats = await Breakeven.getData("BTCUSDT", "my-strategy");
10358
+ * console.log(`Total breakeven events: ${stats.totalEvents}`);
10359
+ *
10360
+ * // Generate markdown report
10361
+ * const markdown = await Breakeven.getReport("BTCUSDT", "my-strategy");
10362
+ * console.log(markdown); // Formatted table with all events
10363
+ *
10364
+ * // Export report to file
10365
+ * await Breakeven.dump("BTCUSDT", "my-strategy"); // Saves to ./dump/breakeven/BTCUSDT_my-strategy.md
10366
+ * await Breakeven.dump("BTCUSDT", "my-strategy", "./custom/path"); // Custom directory
10367
+ * ```
10368
+ */
10369
+ declare class BreakevenUtils {
10370
+ /**
10371
+ * Retrieves statistical data from accumulated breakeven events.
10372
+ *
10373
+ * Delegates to BreakevenMarkdownService.getData() which reads from ReportStorage.
10374
+ * Returns aggregated metrics calculated from all breakeven events.
10375
+ *
10376
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
10377
+ * @param strategyName - Strategy name (e.g., "my-strategy")
10378
+ * @returns Promise resolving to BreakevenStatisticsModel object with counts and event list
10379
+ *
10380
+ * @example
10381
+ * ```typescript
10382
+ * const stats = await Breakeven.getData("BTCUSDT", "my-strategy");
10383
+ *
10384
+ * console.log(`Total breakeven events: ${stats.totalEvents}`);
10385
+ *
10386
+ * // Iterate through all events
10387
+ * for (const event of stats.eventList) {
10388
+ * console.log(`Signal ${event.signalId} reached breakeven at ${event.currentPrice}`);
10389
+ * }
10390
+ * ```
10391
+ */
10392
+ getData: (symbol: string, context: {
10393
+ strategyName: StrategyName;
10394
+ exchangeName: ExchangeName;
10395
+ frameName: FrameName;
10396
+ }, backtest?: boolean) => Promise<BreakevenStatisticsModel>;
10397
+ /**
10398
+ * Generates markdown report with all breakeven events for a symbol-strategy pair.
9528
10399
  *
9529
- * @returns Array of strongly-typed notification objects
10400
+ * Creates formatted table containing:
10401
+ * - Symbol
10402
+ * - Strategy
10403
+ * - Signal ID
10404
+ * - Position (LONG/SHORT)
10405
+ * - Entry Price
10406
+ * - Breakeven Price
10407
+ * - Timestamp (ISO 8601)
10408
+ * - Mode (Backtest/Live)
10409
+ *
10410
+ * Also includes summary statistics at the end.
10411
+ *
10412
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
10413
+ * @param strategyName - Strategy name (e.g., "my-strategy")
10414
+ * @param columns - Optional columns configuration for the report
10415
+ * @returns Promise resolving to markdown formatted report string
9530
10416
  *
9531
10417
  * @example
9532
10418
  * ```typescript
9533
- * const notifications = await Notification.getData();
10419
+ * const markdown = await Breakeven.getReport("BTCUSDT", "my-strategy");
10420
+ * console.log(markdown);
9534
10421
  *
9535
- * notifications.forEach(notification => {
9536
- * switch (notification.type) {
9537
- * case "signal.closed":
9538
- * console.log(`${notification.symbol}: ${notification.pnlPercentage}%`);
9539
- * break;
9540
- * case "partial.loss":
9541
- * if (notification.level >= 30) {
9542
- * console.warn(`High loss: ${notification.symbol}`);
9543
- * }
9544
- * break;
9545
- * }
9546
- * });
10422
+ * // Output:
10423
+ * // # Breakeven Protection Report: BTCUSDT:my-strategy
10424
+ * //
10425
+ * // | Symbol | Strategy | Signal ID | Position | Entry Price | Breakeven Price | Timestamp | Mode |
10426
+ * // | --- | --- | --- | --- | --- | --- | --- | --- |
10427
+ * // | BTCUSDT | my-strategy | abc123 | LONG | 50000.00000000 USD | 50100.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
10428
+ * //
10429
+ * // **Total events:** 1
9547
10430
  * ```
9548
10431
  */
9549
- getData(): Promise<NotificationModel[]>;
10432
+ getReport: (symbol: string, context: {
10433
+ strategyName: StrategyName;
10434
+ exchangeName: ExchangeName;
10435
+ frameName: FrameName;
10436
+ }, backtest?: boolean, columns?: Columns[]) => Promise<string>;
9550
10437
  /**
9551
- * Clears all notification history.
10438
+ * Generates and saves markdown report to file.
10439
+ *
10440
+ * Creates directory if it doesn't exist.
10441
+ * Filename format: {symbol}_{strategyName}.md (e.g., "BTCUSDT_my-strategy.md")
10442
+ *
10443
+ * Delegates to BreakevenMarkdownService.dump() which:
10444
+ * 1. Generates markdown report via getReport()
10445
+ * 2. Creates output directory (recursive mkdir)
10446
+ * 3. Writes file with UTF-8 encoding
10447
+ * 4. Logs success/failure to console
10448
+ *
10449
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
10450
+ * @param strategyName - Strategy name (e.g., "my-strategy")
10451
+ * @param path - Output directory path (default: "./dump/breakeven")
10452
+ * @param columns - Optional columns configuration for the report
10453
+ * @returns Promise that resolves when file is written
9552
10454
  *
9553
10455
  * @example
9554
10456
  * ```typescript
9555
- * await Notification.clear();
10457
+ * // Save to default path: ./dump/breakeven/BTCUSDT_my-strategy.md
10458
+ * await Breakeven.dump("BTCUSDT", "my-strategy");
10459
+ *
10460
+ * // Save to custom path: ./reports/breakeven/BTCUSDT_my-strategy.md
10461
+ * await Breakeven.dump("BTCUSDT", "my-strategy", "./reports/breakeven");
10462
+ *
10463
+ * // After multiple symbols backtested, export all reports
10464
+ * for (const symbol of ["BTCUSDT", "ETHUSDT", "BNBUSDT"]) {
10465
+ * await Breakeven.dump(symbol, "my-strategy", "./backtest-results");
10466
+ * }
9556
10467
  * ```
9557
10468
  */
9558
- clear(): Promise<void>;
10469
+ dump: (symbol: string, context: {
10470
+ strategyName: StrategyName;
10471
+ exchangeName: ExchangeName;
10472
+ frameName: FrameName;
10473
+ }, backtest?: boolean, path?: string, columns?: Columns[]) => Promise<void>;
9559
10474
  }
9560
10475
  /**
9561
- * Singleton instance of NotificationUtils for convenient notification access.
10476
+ * Global singleton instance of BreakevenUtils.
10477
+ * Provides static-like access to breakeven protection reporting methods.
9562
10478
  *
9563
10479
  * @example
9564
10480
  * ```typescript
9565
- * import { Notification } from "./classes/Notification";
9566
- *
9567
- * // Get all notifications
9568
- * const all = await Notification.getData();
9569
- *
9570
- * // Filter by type using type discrimination
9571
- * const closedSignals = all.filter(n => n.type === "signal.closed");
9572
- * const highLosses = all.filter(n =>
9573
- * n.type === "partial.loss" && n.level >= 30
9574
- * );
10481
+ * import { Breakeven } from "backtest-kit";
9575
10482
  *
9576
- * // Clear history
9577
- * await Notification.clear();
10483
+ * // Usage same as BreakevenUtils methods
10484
+ * const stats = await Breakeven.getData("BTCUSDT", "my-strategy");
10485
+ * const report = await Breakeven.getReport("BTCUSDT", "my-strategy");
10486
+ * await Breakeven.dump("BTCUSDT", "my-strategy");
9578
10487
  * ```
9579
10488
  */
9580
- declare const Notification: NotificationUtils;
10489
+ declare const Breakeven: BreakevenUtils;
9581
10490
 
9582
10491
  /**
9583
10492
  * Contract for walker stop signal events.
@@ -9702,6 +10611,11 @@ declare const partialProfitSubject: Subject<PartialProfitContract>;
9702
10611
  * Emits when a signal reaches a loss level (10%, 20%, 30%, etc).
9703
10612
  */
9704
10613
  declare const partialLossSubject: Subject<PartialLossContract>;
10614
+ /**
10615
+ * Breakeven emitter for stop-loss protection milestones.
10616
+ * Emits when a signal's stop-loss is moved to breakeven (entry price).
10617
+ */
10618
+ declare const breakevenSubject: Subject<BreakevenContract>;
9705
10619
  /**
9706
10620
  * Risk rejection emitter for risk management violations.
9707
10621
  * Emits ONLY when a signal is rejected due to risk validation failure.
@@ -9715,6 +10629,7 @@ declare const riskSubject: Subject<RiskContract>;
9715
10629
  */
9716
10630
  declare const pingSubject: Subject<PingContract>;
9717
10631
 
10632
+ declare const emitters_breakevenSubject: typeof breakevenSubject;
9718
10633
  declare const emitters_doneBacktestSubject: typeof doneBacktestSubject;
9719
10634
  declare const emitters_doneLiveSubject: typeof doneLiveSubject;
9720
10635
  declare const emitters_doneWalkerSubject: typeof doneWalkerSubject;
@@ -9736,7 +10651,7 @@ declare const emitters_walkerCompleteSubject: typeof walkerCompleteSubject;
9736
10651
  declare const emitters_walkerEmitter: typeof walkerEmitter;
9737
10652
  declare const emitters_walkerStopSubject: typeof walkerStopSubject;
9738
10653
  declare namespace emitters {
9739
- export { emitters_doneBacktestSubject as doneBacktestSubject, emitters_doneLiveSubject as doneLiveSubject, emitters_doneWalkerSubject as doneWalkerSubject, emitters_errorEmitter as errorEmitter, emitters_exitEmitter as exitEmitter, emitters_partialLossSubject as partialLossSubject, emitters_partialProfitSubject as partialProfitSubject, emitters_performanceEmitter as performanceEmitter, emitters_pingSubject as pingSubject, emitters_progressBacktestEmitter as progressBacktestEmitter, emitters_progressOptimizerEmitter as progressOptimizerEmitter, emitters_progressWalkerEmitter as progressWalkerEmitter, emitters_riskSubject as riskSubject, 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 };
10654
+ export { emitters_breakevenSubject as breakevenSubject, emitters_doneBacktestSubject as doneBacktestSubject, emitters_doneLiveSubject as doneLiveSubject, emitters_doneWalkerSubject as doneWalkerSubject, emitters_errorEmitter as errorEmitter, emitters_exitEmitter as exitEmitter, emitters_partialLossSubject as partialLossSubject, emitters_partialProfitSubject as partialProfitSubject, emitters_performanceEmitter as performanceEmitter, emitters_pingSubject as pingSubject, emitters_progressBacktestEmitter as progressBacktestEmitter, emitters_progressOptimizerEmitter as progressOptimizerEmitter, emitters_progressWalkerEmitter as progressWalkerEmitter, emitters_riskSubject as riskSubject, 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 };
9740
10655
  }
9741
10656
 
9742
10657
  /**
@@ -10305,6 +11220,88 @@ declare class PartialConnectionService implements IPartial {
10305
11220
  clear: (symbol: string, data: ISignalRow, priceClose: number, backtest: boolean) => Promise<void>;
10306
11221
  }
10307
11222
 
11223
+ /**
11224
+ * Connection service for breakeven tracking.
11225
+ *
11226
+ * Provides memoized ClientBreakeven instances per signal ID.
11227
+ * Acts as factory and lifetime manager for ClientBreakeven objects.
11228
+ *
11229
+ * Features:
11230
+ * - Creates one ClientBreakeven instance per signal ID (memoized)
11231
+ * - Configures instances with logger and event emitter callbacks
11232
+ * - Delegates check/clear operations to appropriate ClientBreakeven
11233
+ * - Cleans up memoized instances when signals are cleared
11234
+ *
11235
+ * Architecture:
11236
+ * - Injected into ClientStrategy via BreakevenGlobalService
11237
+ * - Uses memoize from functools-kit for instance caching
11238
+ * - Emits events to breakevenSubject
11239
+ *
11240
+ * @example
11241
+ * ```typescript
11242
+ * // Service injected via DI
11243
+ * const service = inject<BreakevenConnectionService>(TYPES.breakevenConnectionService);
11244
+ *
11245
+ * // Called by ClientStrategy during signal monitoring
11246
+ * await service.check("BTCUSDT", signal, 100.5, false, new Date());
11247
+ * // Creates or reuses ClientBreakeven for signal.id
11248
+ * // Delegates to ClientBreakeven.check()
11249
+ *
11250
+ * // When signal closes
11251
+ * await service.clear("BTCUSDT", signal, 101, false);
11252
+ * // Clears signal state and removes memoized instance
11253
+ * ```
11254
+ */
11255
+ declare class BreakevenConnectionService implements IBreakeven {
11256
+ /**
11257
+ * Logger service injected from DI container.
11258
+ */
11259
+ private readonly loggerService;
11260
+ /**
11261
+ * Memoized factory function for ClientBreakeven instances.
11262
+ *
11263
+ * Creates one ClientBreakeven per signal ID and backtest mode with configured callbacks.
11264
+ * Instances are cached until clear() is called.
11265
+ *
11266
+ * Key format: "signalId:backtest" or "signalId:live"
11267
+ * Value: ClientBreakeven instance with logger and event emitter
11268
+ */
11269
+ private getBreakeven;
11270
+ /**
11271
+ * Checks if breakeven should be triggered and emits event if conditions met.
11272
+ *
11273
+ * Retrieves or creates ClientBreakeven for signal ID, initializes it if needed,
11274
+ * then delegates to ClientBreakeven.check() method.
11275
+ *
11276
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
11277
+ * @param data - Signal row data
11278
+ * @param currentPrice - Current market price
11279
+ * @param backtest - True if backtest mode, false if live mode
11280
+ * @param when - Event timestamp (current time for live, candle time for backtest)
11281
+ * @returns Promise that resolves when breakeven check is complete
11282
+ */
11283
+ check: (symbol: string, data: IPublicSignalRow, currentPrice: number, backtest: boolean, when: Date) => Promise<boolean>;
11284
+ /**
11285
+ * Clears breakeven state when signal closes.
11286
+ *
11287
+ * Retrieves ClientBreakeven for signal ID, initializes if needed,
11288
+ * delegates clear operation, then removes memoized instance.
11289
+ *
11290
+ * Sequence:
11291
+ * 1. Get ClientBreakeven from memoize cache
11292
+ * 2. Ensure initialization (waitForInit)
11293
+ * 3. Call ClientBreakeven.clear() - removes state, persists to disk
11294
+ * 4. Clear memoized instance - prevents memory leaks
11295
+ *
11296
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
11297
+ * @param data - Signal row data
11298
+ * @param priceClose - Final closing price
11299
+ * @param backtest - True if backtest mode, false if live mode
11300
+ * @returns Promise that resolves when clear is complete
11301
+ */
11302
+ clear: (symbol: string, data: ISignalRow, priceClose: number, backtest: boolean) => Promise<void>;
11303
+ }
11304
+
10308
11305
  /**
10309
11306
  * Type definition for strategy methods.
10310
11307
  * Maps all keys of IStrategy to any type.
@@ -10345,6 +11342,7 @@ declare class StrategyConnectionService implements TStrategy$1 {
10345
11342
  readonly riskConnectionService: RiskConnectionService;
10346
11343
  readonly exchangeConnectionService: ExchangeConnectionService;
10347
11344
  readonly partialConnectionService: PartialConnectionService;
11345
+ readonly breakevenConnectionService: BreakevenConnectionService;
10348
11346
  /**
10349
11347
  * Retrieves memoized ClientStrategy instance for given symbol-strategy pair with exchange and frame isolation.
10350
11348
  *
@@ -10584,6 +11582,33 @@ declare class StrategyConnectionService implements TStrategy$1 {
10584
11582
  exchangeName: ExchangeName;
10585
11583
  frameName: FrameName;
10586
11584
  }) => Promise<void>;
11585
+ /**
11586
+ * Delegates to ClientStrategy.breakeven() with current execution context.
11587
+ *
11588
+ * @param backtest - Whether running in backtest mode
11589
+ * @param symbol - Trading pair symbol
11590
+ * @param currentPrice - Current market price to check threshold
11591
+ * @param context - Execution context with strategyName, exchangeName, frameName
11592
+ * @returns Promise<boolean> - true if breakeven was set, false otherwise
11593
+ *
11594
+ * @example
11595
+ * ```typescript
11596
+ * // LONG: entry=100, slippage=0.1%, fee=0.1%, threshold=0.4%
11597
+ * // Try to move SL to breakeven when price >= 100.4
11598
+ * const moved = await strategyConnectionService.breakeven(
11599
+ * false,
11600
+ * "BTCUSDT",
11601
+ * 100.5,
11602
+ * { strategyName: "my-strategy", exchangeName: "binance", frameName: "" }
11603
+ * );
11604
+ * console.log(moved); // true (SL moved to 100)
11605
+ * ```
11606
+ */
11607
+ breakeven: (backtest: boolean, symbol: string, currentPrice: number, context: {
11608
+ strategyName: StrategyName;
11609
+ exchangeName: ExchangeName;
11610
+ frameName: FrameName;
11611
+ }) => Promise<boolean>;
10587
11612
  }
10588
11613
 
10589
11614
  /**
@@ -11087,6 +12112,31 @@ declare class StrategyCoreService implements TStrategy {
11087
12112
  exchangeName: ExchangeName;
11088
12113
  frameName: FrameName;
11089
12114
  }) => Promise<void>;
12115
+ /**
12116
+ * Moves stop-loss to breakeven when price reaches threshold.
12117
+ * Validates context and delegates to StrategyConnectionService.
12118
+ *
12119
+ * @param backtest - Whether running in backtest mode
12120
+ * @param symbol - Trading pair symbol
12121
+ * @param currentPrice - Current market price to check threshold
12122
+ * @param context - Strategy context with strategyName, exchangeName, frameName
12123
+ * @returns Promise<boolean> - true if breakeven was set, false otherwise
12124
+ *
12125
+ * @example
12126
+ * ```typescript
12127
+ * const moved = await strategyCoreService.breakeven(
12128
+ * false,
12129
+ * "BTCUSDT",
12130
+ * 112,
12131
+ * { strategyName: "my-strategy", exchangeName: "binance", frameName: "" }
12132
+ * );
12133
+ * ```
12134
+ */
12135
+ breakeven: (backtest: boolean, symbol: string, currentPrice: number, context: {
12136
+ strategyName: StrategyName;
12137
+ exchangeName: ExchangeName;
12138
+ frameName: FrameName;
12139
+ }) => Promise<boolean>;
11090
12140
  }
11091
12141
 
11092
12142
  /**
@@ -12703,6 +13753,101 @@ declare class PartialGlobalService implements TPartial {
12703
13753
  clear: (symbol: string, data: ISignalRow, priceClose: number, backtest: boolean) => Promise<void>;
12704
13754
  }
12705
13755
 
13756
+ /**
13757
+ * Type definition for breakeven methods.
13758
+ * Maps all keys of IBreakeven to any type.
13759
+ * Used for dynamic method routing in BreakevenGlobalService.
13760
+ */
13761
+ type TBreakeven = {
13762
+ [key in keyof IBreakeven]: any;
13763
+ };
13764
+ /**
13765
+ * Global service for breakeven tracking.
13766
+ *
13767
+ * Thin delegation layer that forwards operations to BreakevenConnectionService.
13768
+ * Provides centralized logging for all breakeven operations at the global level.
13769
+ *
13770
+ * Architecture:
13771
+ * - Injected into ClientStrategy constructor via IStrategyParams
13772
+ * - Delegates all operations to BreakevenConnectionService
13773
+ * - Logs operations at "breakevenGlobalService" level before delegation
13774
+ *
13775
+ * Purpose:
13776
+ * - Single injection point for ClientStrategy (dependency injection pattern)
13777
+ * - Centralized logging for monitoring breakeven operations
13778
+ * - Layer of abstraction between strategy and connection layer
13779
+ *
13780
+ * @example
13781
+ * ```typescript
13782
+ * // Service injected into ClientStrategy via DI
13783
+ * const strategy = new ClientStrategy({
13784
+ * breakeven: breakevenGlobalService,
13785
+ * ...
13786
+ * });
13787
+ *
13788
+ * // Called during signal monitoring
13789
+ * await strategy.params.breakeven.check("BTCUSDT", signal, 100.5, false, new Date());
13790
+ * // Logs at global level → delegates to BreakevenConnectionService
13791
+ * ```
13792
+ */
13793
+ declare class BreakevenGlobalService implements TBreakeven {
13794
+ /**
13795
+ * Logger service injected from DI container.
13796
+ * Used for logging operations at global service level.
13797
+ */
13798
+ private readonly loggerService;
13799
+ /**
13800
+ * Connection service injected from DI container.
13801
+ * Handles actual ClientBreakeven instance creation and management.
13802
+ */
13803
+ private readonly breakevenConnectionService;
13804
+ /**
13805
+ * Strategy validation service for validating strategy existence.
13806
+ */
13807
+ private readonly strategyValidationService;
13808
+ /**
13809
+ * Strategy schema service for retrieving strategy configuration.
13810
+ */
13811
+ private readonly strategySchemaService;
13812
+ /**
13813
+ * Risk validation service for validating risk existence.
13814
+ */
13815
+ private readonly riskValidationService;
13816
+ /**
13817
+ * Validates strategy and associated risk configuration.
13818
+ * Memoized to avoid redundant validations for the same strategy-exchange-frame combination.
13819
+ *
13820
+ * @param context - Context with strategyName, exchangeName and frameName
13821
+ * @param methodName - Name of the calling method for error tracking
13822
+ */
13823
+ private validate;
13824
+ /**
13825
+ * Checks if breakeven should be triggered and emits event if conditions met.
13826
+ *
13827
+ * Logs operation at global service level, then delegates to BreakevenConnectionService.
13828
+ *
13829
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
13830
+ * @param data - Signal row data
13831
+ * @param currentPrice - Current market price
13832
+ * @param backtest - True if backtest mode, false if live mode
13833
+ * @param when - Event timestamp (current time for live, candle time for backtest)
13834
+ * @returns Promise that resolves when breakeven check is complete
13835
+ */
13836
+ check: (symbol: string, data: IPublicSignalRow, currentPrice: number, backtest: boolean, when: Date) => Promise<boolean>;
13837
+ /**
13838
+ * Clears breakeven state when signal closes.
13839
+ *
13840
+ * Logs operation at global service level, then delegates to BreakevenConnectionService.
13841
+ *
13842
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
13843
+ * @param data - Signal row data
13844
+ * @param priceClose - Final closing price
13845
+ * @param backtest - True if backtest mode, false if live mode
13846
+ * @returns Promise that resolves when clear is complete
13847
+ */
13848
+ clear: (symbol: string, data: ISignalRow, priceClose: number, backtest: boolean) => Promise<void>;
13849
+ }
13850
+
12706
13851
  /**
12707
13852
  * Unique identifier for outline result.
12708
13853
  * Can be string or number for flexible ID formats.
@@ -12867,6 +14012,7 @@ declare const backtest: {
12867
14012
  walkerMarkdownService: WalkerMarkdownService;
12868
14013
  heatMarkdownService: HeatMarkdownService;
12869
14014
  partialMarkdownService: PartialMarkdownService;
14015
+ breakevenMarkdownService: BreakevenMarkdownService;
12870
14016
  outlineMarkdownService: OutlineMarkdownService;
12871
14017
  riskMarkdownService: RiskMarkdownService;
12872
14018
  backtestLogicPublicService: BacktestLogicPublicService;
@@ -12882,6 +14028,7 @@ declare const backtest: {
12882
14028
  riskGlobalService: RiskGlobalService;
12883
14029
  optimizerGlobalService: OptimizerGlobalService;
12884
14030
  partialGlobalService: PartialGlobalService;
14031
+ breakevenGlobalService: BreakevenGlobalService;
12885
14032
  exchangeCoreService: ExchangeCoreService;
12886
14033
  strategyCoreService: StrategyCoreService;
12887
14034
  frameCoreService: FrameCoreService;
@@ -12899,6 +14046,7 @@ declare const backtest: {
12899
14046
  riskConnectionService: RiskConnectionService;
12900
14047
  optimizerConnectionService: OptimizerConnectionService;
12901
14048
  partialConnectionService: PartialConnectionService;
14049
+ breakevenConnectionService: BreakevenConnectionService;
12902
14050
  executionContextService: {
12903
14051
  readonly context: IExecutionContext;
12904
14052
  };
@@ -12908,4 +14056,4 @@ declare const backtest: {
12908
14056
  loggerService: LoggerService;
12909
14057
  };
12910
14058
 
12911
- export { Backtest, type BacktestDoneNotification, type BacktestStatisticsModel, type BootstrapNotification, Cache, type CandleInterval, type ColumnConfig, type ColumnModel, Constant, type CriticalErrorNotification, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IOptimizerCallbacks, type IOptimizerData, type IOptimizerFetchArgs, type IOptimizerFilterArgs, type IOptimizerRange, type IOptimizerSchema, type IOptimizerSource, type IOptimizerStrategy, type IOptimizerTemplate, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IPublicSignalRow, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalCancelRow, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStrategyPnL, type IStrategyResult, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, type InfoErrorNotification, Live, type LiveDoneNotification, type LiveStatisticsModel, type MessageModel, type MessageRole, MethodContextService, type MetricStats, Notification, type NotificationModel, Optimizer, Partial$1 as Partial, type PartialData, type PartialEvent, type PartialLossContract, type PartialLossNotification, type PartialProfitContract, type PartialProfitNotification, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, type PingContract, PositionSize, type ProgressBacktestContract, type ProgressBacktestNotification, type ProgressOptimizerContract, type ProgressWalkerContract, Risk, type RiskContract, type RiskData, type RiskEvent, type RiskRejectionNotification, type RiskStatisticsModel, Schedule, type ScheduleData, type ScheduleStatisticsModel, type ScheduledEvent, type SignalCancelledNotification, type SignalClosedNotification, type SignalData, type SignalInterval, type SignalOpenedNotification, type SignalScheduledNotification, type TPersistBase, type TPersistBaseCtor, type TickEvent, type ValidationErrorNotification, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type SignalData$1 as WalkerSignalData, type WalkerStatisticsModel, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, cancel, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenPing, listenPingOnce, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, partialLoss, partialProfit, setColumns, setConfig, setLogger, stop, trailingStop, validate };
14059
+ export { Backtest, type BacktestDoneNotification, type BacktestStatisticsModel, type BootstrapNotification, Breakeven, type BreakevenContract, type BreakevenData, Cache, type CandleInterval, type ColumnConfig, type ColumnModel, Constant, type CriticalErrorNotification, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IOptimizerCallbacks, type IOptimizerData, type IOptimizerFetchArgs, type IOptimizerFilterArgs, type IOptimizerRange, type IOptimizerSchema, type IOptimizerSource, type IOptimizerStrategy, type IOptimizerTemplate, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IPublicSignalRow, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalCancelRow, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStrategyPnL, type IStrategyResult, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, type InfoErrorNotification, Live, type LiveDoneNotification, type LiveStatisticsModel, type MessageModel, type MessageRole, MethodContextService, type MetricStats, Notification, type NotificationModel, Optimizer, Partial$1 as Partial, type PartialData, type PartialEvent, type PartialLossContract, type PartialLossNotification, type PartialProfitContract, type PartialProfitNotification, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistBreakevenAdapter, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, type PingContract, PositionSize, type ProgressBacktestContract, type ProgressBacktestNotification, type ProgressOptimizerContract, type ProgressWalkerContract, Risk, type RiskContract, type RiskData, type RiskEvent, type RiskRejectionNotification, type RiskStatisticsModel, Schedule, type ScheduleData, type ScheduleStatisticsModel, type ScheduledEvent, type SignalCancelledNotification, type SignalClosedNotification, type SignalData, type SignalInterval, type SignalOpenedNotification, type SignalScheduledNotification, type TPersistBase, type TPersistBaseCtor, type TickEvent, type ValidationErrorNotification, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type SignalData$1 as WalkerSignalData, type WalkerStatisticsModel, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, breakeven, cancel, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenBreakeven, listenBreakevenOnce, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenPing, listenPingOnce, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, partialLoss, partialProfit, setColumns, setConfig, setLogger, stop, trailingStop, validate };