backtest-kit 1.1.9 → 1.2.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
@@ -2,6 +2,79 @@ import * as di_scoped from 'di-scoped';
2
2
  import * as functools_kit from 'functools-kit';
3
3
  import { Subject } from 'functools-kit';
4
4
 
5
+ declare const GLOBAL_CONFIG: {
6
+ /**
7
+ * Time to wait for scheduled signal to activate (in minutes)
8
+ * If signal does not activate within this time, it will be cancelled.
9
+ */
10
+ CC_SCHEDULE_AWAIT_MINUTES: number;
11
+ /**
12
+ * Number of candles to use for average price calculation (VWAP)
13
+ * Default: 5 candles (last 5 minutes when using 1m interval)
14
+ */
15
+ CC_AVG_PRICE_CANDLES_COUNT: number;
16
+ /**
17
+ * Minimum TakeProfit distance from priceOpen (percentage)
18
+ * Must be greater than trading fees to ensure profitable trades
19
+ * Default: 0.3% (covers 2×0.1% fees + minimum profit margin)
20
+ */
21
+ CC_MIN_TAKEPROFIT_DISTANCE_PERCENT: number;
22
+ /**
23
+ * Maximum StopLoss distance from priceOpen (percentage)
24
+ * Prevents catastrophic losses from extreme StopLoss values
25
+ * Default: 20% (one signal cannot lose more than 20% of position)
26
+ */
27
+ CC_MAX_STOPLOSS_DISTANCE_PERCENT: number;
28
+ /**
29
+ * Maximum signal lifetime in minutes
30
+ * Prevents eternal signals that block risk limits for weeks/months
31
+ * Default: 1440 minutes (1 day)
32
+ */
33
+ CC_MAX_SIGNAL_LIFETIME_MINUTES: number;
34
+ /**
35
+ * Number of retries for getCandles function
36
+ * Default: 3 retries
37
+ */
38
+ CC_GET_CANDLES_RETRY_COUNT: number;
39
+ /**
40
+ * Delay between retries for getCandles function (in milliseconds)
41
+ * Default: 5000 ms (5 seconds)
42
+ */
43
+ CC_GET_CANDLES_RETRY_DELAY_MS: number;
44
+ /**
45
+ * Maximum allowed deviation factor for price anomaly detection.
46
+ * Price should not be more than this factor lower than reference price.
47
+ *
48
+ * Reasoning:
49
+ * - Incomplete candles from Binance API typically have prices near 0 (e.g., $0.01-1)
50
+ * - Normal BTC price ranges: $20,000-100,000
51
+ * - Factor 1000 catches prices below $20-100 when median is $20,000-100,000
52
+ * - Factor 100 would be too permissive (allows $200 when median is $20,000)
53
+ * - Factor 10000 might be too strict for low-cap altcoins
54
+ *
55
+ * Example: BTC at $50,000 median → threshold $50 (catches $0.01-1 anomalies)
56
+ */
57
+ CC_GET_CANDLES_PRICE_ANOMALY_THRESHOLD_FACTOR: number;
58
+ /**
59
+ * Minimum number of candles required for reliable median calculation.
60
+ * Below this threshold, use simple average instead of median.
61
+ *
62
+ * Reasoning:
63
+ * - Each candle provides 4 price points (OHLC)
64
+ * - 5 candles = 20 price points, sufficient for robust median calculation
65
+ * - Below 5 candles, single anomaly can heavily skew median
66
+ * - Statistical rule of thumb: minimum 7-10 data points for median stability
67
+ * - Average is more stable than median for small datasets (n < 20)
68
+ *
69
+ * Example: 3 candles = 12 points (use average), 5 candles = 20 points (use median)
70
+ */
71
+ CC_GET_CANDLES_MIN_CANDLES_FOR_MEDIAN: number;
72
+ };
73
+ /**
74
+ * Type for global configuration object.
75
+ */
76
+ type GlobalConfig = typeof GLOBAL_CONFIG;
77
+
5
78
  /**
6
79
  * Interface representing a logging mechanism for the swarm system.
7
80
  * Provides methods to record messages at different severity levels, used across components like agents, sessions, states, storage, swarms, history, embeddings, completions, and policies.
@@ -48,6 +121,18 @@ interface ILogger {
48
121
  * ```
49
122
  */
50
123
  declare function setLogger(logger: ILogger): Promise<void>;
124
+ /**
125
+ * Sets global configuration parameters for the framework.
126
+ * @param config - Partial configuration object to override default settings
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * setConfig({
131
+ * CC_SCHEDULE_AWAIT_MINUTES: 90,
132
+ * });
133
+ * ```
134
+ */
135
+ declare function setConfig(config: Partial<GlobalConfig>): Promise<void>;
51
136
 
52
137
  /**
53
138
  * Execution context containing runtime parameters for strategy/exchange operations.
@@ -304,7 +389,7 @@ interface IFrame {
304
389
  * @param symbol - Trading pair symbol (unused, for API consistency)
305
390
  * @returns Promise resolving to array of Date objects
306
391
  */
307
- getTimeframe: (symbol: string) => Promise<Date[]>;
392
+ getTimeframe: (symbol: string, frameName: FrameName) => Promise<Date[]>;
308
393
  }
309
394
  /**
310
395
  * Unique identifier for a frame schema.
@@ -523,14 +608,28 @@ interface ISignalRow extends ISignalDto {
523
608
  exchangeName: ExchangeName;
524
609
  /** Unique strategy identifier for execution */
525
610
  strategyName: StrategyName;
526
- /** Signal creation timestamp in milliseconds */
527
- timestamp: number;
611
+ /** Signal creation timestamp in milliseconds (when signal was first created/scheduled) */
612
+ scheduledAt: number;
613
+ /** Pending timestamp in milliseconds (when position became pending/active at priceOpen) */
614
+ pendingAt: number;
528
615
  /** Trading pair symbol (e.g., "BTCUSDT") */
529
616
  symbol: string;
617
+ /** Internal runtime marker for scheduled signals */
618
+ _isScheduled: boolean;
619
+ }
620
+ /**
621
+ * Scheduled signal row for delayed entry at specific price.
622
+ * Inherits from ISignalRow - represents a signal waiting for price to reach priceOpen.
623
+ * Once price reaches priceOpen, will be converted to regular _pendingSignal.
624
+ * Note: pendingAt will be set to scheduledAt until activation, then updated to actual pending time.
625
+ */
626
+ interface IScheduledSignalRow extends ISignalRow {
627
+ /** Entry price for the position */
628
+ priceOpen: number;
530
629
  }
531
630
  /**
532
631
  * Optional lifecycle callbacks for signal events.
533
- * Called when signals are opened, active, idle, or closed.
632
+ * Called when signals are opened, active, idle, closed, scheduled, or cancelled.
534
633
  */
535
634
  interface IStrategyCallbacks {
536
635
  /** Called on every tick with the result */
@@ -543,6 +642,12 @@ interface IStrategyCallbacks {
543
642
  onIdle: (symbol: string, currentPrice: number, backtest: boolean) => void;
544
643
  /** Called when signal is closed with final price */
545
644
  onClose: (symbol: string, data: ISignalRow, priceClose: number, backtest: boolean) => void;
645
+ /** Called when scheduled signal is created (delayed entry) */
646
+ onSchedule: (symbol: string, data: IScheduledSignalRow, currentPrice: number, backtest: boolean) => void;
647
+ /** Called when scheduled signal is cancelled without opening position */
648
+ onCancel: (symbol: string, data: IScheduledSignalRow, currentPrice: number, backtest: boolean) => void;
649
+ /** Called when signal is written to persist storage (for testing) */
650
+ onWrite: (symbol: string, data: ISignalRow | null, backtest: boolean) => void;
546
651
  }
547
652
  /**
548
653
  * Strategy schema registered via addStrategy().
@@ -555,7 +660,11 @@ interface IStrategySchema {
555
660
  note?: string;
556
661
  /** Minimum interval between getSignal calls (throttling) */
557
662
  interval: SignalInterval;
558
- /** Signal generation function (returns null if no signal, validated DTO if signal) */
663
+ /**
664
+ * Signal generation function (returns null if no signal, validated DTO if signal).
665
+ * If priceOpen is provided - becomes scheduled signal waiting for price to reach entry point.
666
+ * If priceOpen is omitted - opens immediately at current price.
667
+ */
559
668
  getSignal: (symbol: string) => Promise<ISignalDto | null>;
560
669
  /** Optional lifecycle event callbacks (onOpen, onClose) */
561
670
  callbacks?: Partial<IStrategyCallbacks>;
@@ -596,6 +705,24 @@ interface IStrategyTickResultIdle {
596
705
  /** Current VWAP price during idle state */
597
706
  currentPrice: number;
598
707
  }
708
+ /**
709
+ * Tick result: scheduled signal created, waiting for price to reach entry point.
710
+ * Triggered when getSignal returns signal with priceOpen specified.
711
+ */
712
+ interface IStrategyTickResultScheduled {
713
+ /** Discriminator for type-safe union */
714
+ action: "scheduled";
715
+ /** Scheduled signal waiting for activation */
716
+ signal: IScheduledSignalRow;
717
+ /** Strategy name for tracking */
718
+ strategyName: StrategyName;
719
+ /** Exchange name for tracking */
720
+ exchangeName: ExchangeName;
721
+ /** Trading pair symbol (e.g., "BTCUSDT") */
722
+ symbol: string;
723
+ /** Current VWAP price when scheduled signal created */
724
+ currentPrice: number;
725
+ }
599
726
  /**
600
727
  * Tick result: new signal just created.
601
728
  * Triggered after getSignal validation and persistence.
@@ -656,15 +783,35 @@ interface IStrategyTickResultClosed {
656
783
  /** Trading pair symbol (e.g., "BTCUSDT") */
657
784
  symbol: string;
658
785
  }
786
+ /**
787
+ * Tick result: scheduled signal cancelled without opening position.
788
+ * Occurs when scheduled signal doesn't activate or hits stop loss before entry.
789
+ */
790
+ interface IStrategyTickResultCancelled {
791
+ /** Discriminator for type-safe union */
792
+ action: "cancelled";
793
+ /** Cancelled scheduled signal */
794
+ signal: IScheduledSignalRow;
795
+ /** Final VWAP price at cancellation */
796
+ currentPrice: number;
797
+ /** Unix timestamp in milliseconds when signal cancelled */
798
+ closeTimestamp: number;
799
+ /** Strategy name for tracking */
800
+ strategyName: StrategyName;
801
+ /** Exchange name for tracking */
802
+ exchangeName: ExchangeName;
803
+ /** Trading pair symbol (e.g., "BTCUSDT") */
804
+ symbol: string;
805
+ }
659
806
  /**
660
807
  * Discriminated union of all tick results.
661
808
  * Use type guards: `result.action === "closed"` for type safety.
662
809
  */
663
- type IStrategyTickResult = IStrategyTickResultIdle | IStrategyTickResultOpened | IStrategyTickResultActive | IStrategyTickResultClosed;
810
+ type IStrategyTickResult = IStrategyTickResultIdle | IStrategyTickResultScheduled | IStrategyTickResultOpened | IStrategyTickResultActive | IStrategyTickResultClosed | IStrategyTickResultCancelled;
664
811
  /**
665
- * Backtest always returns closed result (TP/SL or time_expired).
812
+ * Backtest returns closed result (TP/SL or time_expired) or cancelled result (scheduled signal never activated).
666
813
  */
667
- type IStrategyBacktestResult = IStrategyTickResultClosed;
814
+ type IStrategyBacktestResult = IStrategyTickResultClosed | IStrategyTickResultCancelled;
668
815
  /**
669
816
  * Strategy interface implemented by ClientStrategy.
670
817
  * Defines core strategy execution methods.
@@ -682,6 +829,9 @@ interface IStrategy {
682
829
  * Fast backtest using historical candles.
683
830
  * Iterates through candles, calculates VWAP, checks TP/SL on each candle.
684
831
  *
832
+ * For scheduled signals: first monitors activation/cancellation,
833
+ * then if activated continues with TP/SL monitoring.
834
+ *
685
835
  * @param candles - Array of historical candle data
686
836
  * @returns Promise resolving to closed result (always completes signal)
687
837
  */
@@ -2437,7 +2587,7 @@ interface IHeatmapStatistics {
2437
2587
  * Contains all information about a tick event regardless of action type.
2438
2588
  */
2439
2589
  interface TickEvent {
2440
- /** Event timestamp in milliseconds */
2590
+ /** Event timestamp in milliseconds (pendingAt for opened/closed events) */
2441
2591
  timestamp: number;
2442
2592
  /** Event action type */
2443
2593
  action: "idle" | "opened" | "active" | "closed";
@@ -2658,6 +2808,199 @@ declare class LiveMarkdownService {
2658
2808
  protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
2659
2809
  }
2660
2810
 
2811
+ /**
2812
+ * Unified scheduled signal event data for report generation.
2813
+ * Contains all information about scheduled and cancelled events.
2814
+ */
2815
+ interface ScheduledEvent {
2816
+ /** Event timestamp in milliseconds (scheduledAt for scheduled/cancelled events) */
2817
+ timestamp: number;
2818
+ /** Event action type */
2819
+ action: "scheduled" | "cancelled";
2820
+ /** Trading pair symbol */
2821
+ symbol: string;
2822
+ /** Signal ID */
2823
+ signalId: string;
2824
+ /** Position type */
2825
+ position: string;
2826
+ /** Signal note */
2827
+ note?: string;
2828
+ /** Current market price */
2829
+ currentPrice: number;
2830
+ /** Scheduled entry price */
2831
+ priceOpen: number;
2832
+ /** Take profit price */
2833
+ takeProfit: number;
2834
+ /** Stop loss price */
2835
+ stopLoss: number;
2836
+ /** Close timestamp (only for cancelled) */
2837
+ closeTimestamp?: number;
2838
+ /** Duration in minutes (only for cancelled) */
2839
+ duration?: number;
2840
+ }
2841
+ /**
2842
+ * Statistical data calculated from scheduled signals.
2843
+ *
2844
+ * Provides metrics for scheduled signal tracking and cancellation analysis.
2845
+ *
2846
+ * @example
2847
+ * ```typescript
2848
+ * const stats = await Schedule.getData("my-strategy");
2849
+ *
2850
+ * console.log(`Total events: ${stats.totalEvents}`);
2851
+ * console.log(`Scheduled signals: ${stats.totalScheduled}`);
2852
+ * console.log(`Cancelled signals: ${stats.totalCancelled}`);
2853
+ * console.log(`Cancellation rate: ${stats.cancellationRate}%`);
2854
+ *
2855
+ * // Access raw event data (includes scheduled, cancelled)
2856
+ * stats.eventList.forEach(event => {
2857
+ * if (event.action === "cancelled") {
2858
+ * console.log(`Cancelled signal: ${event.signalId}`);
2859
+ * }
2860
+ * });
2861
+ * ```
2862
+ */
2863
+ interface ScheduleStatistics {
2864
+ /** Array of all scheduled/cancelled events with full details */
2865
+ eventList: ScheduledEvent[];
2866
+ /** Total number of all events (includes scheduled, cancelled) */
2867
+ totalEvents: number;
2868
+ /** Total number of scheduled signals */
2869
+ totalScheduled: number;
2870
+ /** Total number of cancelled signals */
2871
+ totalCancelled: number;
2872
+ /** Cancellation rate as percentage (0-100), null if no scheduled signals. Lower is better. */
2873
+ cancellationRate: number | null;
2874
+ /** Average waiting time for cancelled signals in minutes, null if no cancelled signals */
2875
+ avgWaitTime: number | null;
2876
+ }
2877
+ /**
2878
+ * Service for generating and saving scheduled signals markdown reports.
2879
+ *
2880
+ * Features:
2881
+ * - Listens to scheduled and cancelled signal events via signalLiveEmitter
2882
+ * - Accumulates all events (scheduled, cancelled) per strategy
2883
+ * - Generates markdown tables with detailed event information
2884
+ * - Provides statistics (cancellation rate, average wait time)
2885
+ * - Saves reports to disk in logs/schedule/{strategyName}.md
2886
+ *
2887
+ * @example
2888
+ * ```typescript
2889
+ * const service = new ScheduleMarkdownService();
2890
+ *
2891
+ * // Service automatically subscribes to signalLiveEmitter on init
2892
+ * // No manual callback setup needed
2893
+ *
2894
+ * // Later: generate and save report
2895
+ * await service.dump("my-strategy");
2896
+ * ```
2897
+ */
2898
+ declare class ScheduleMarkdownService {
2899
+ /** Logger service for debug output */
2900
+ private readonly loggerService;
2901
+ /**
2902
+ * Memoized function to get or create ReportStorage for a strategy.
2903
+ * Each strategy gets its own isolated storage instance.
2904
+ */
2905
+ private getStorage;
2906
+ /**
2907
+ * Processes tick events and accumulates scheduled/cancelled events.
2908
+ * Should be called from signalLiveEmitter subscription.
2909
+ *
2910
+ * Processes only scheduled and cancelled event types.
2911
+ *
2912
+ * @param data - Tick result from strategy execution
2913
+ *
2914
+ * @example
2915
+ * ```typescript
2916
+ * const service = new ScheduleMarkdownService();
2917
+ * // Service automatically subscribes in init()
2918
+ * ```
2919
+ */
2920
+ private tick;
2921
+ /**
2922
+ * Gets statistical data from all scheduled signal events for a strategy.
2923
+ * Delegates to ReportStorage.getData().
2924
+ *
2925
+ * @param strategyName - Strategy name to get data for
2926
+ * @returns Statistical data object with all metrics
2927
+ *
2928
+ * @example
2929
+ * ```typescript
2930
+ * const service = new ScheduleMarkdownService();
2931
+ * const stats = await service.getData("my-strategy");
2932
+ * console.log(stats.cancellationRate, stats.avgWaitTime);
2933
+ * ```
2934
+ */
2935
+ getData: (strategyName: StrategyName) => Promise<ScheduleStatistics>;
2936
+ /**
2937
+ * Generates markdown report with all scheduled events for a strategy.
2938
+ * Delegates to ReportStorage.getReport().
2939
+ *
2940
+ * @param strategyName - Strategy name to generate report for
2941
+ * @returns Markdown formatted report string with table of all events
2942
+ *
2943
+ * @example
2944
+ * ```typescript
2945
+ * const service = new ScheduleMarkdownService();
2946
+ * const markdown = await service.getReport("my-strategy");
2947
+ * console.log(markdown);
2948
+ * ```
2949
+ */
2950
+ getReport: (strategyName: StrategyName) => Promise<string>;
2951
+ /**
2952
+ * Saves strategy report to disk.
2953
+ * Creates directory if it doesn't exist.
2954
+ * Delegates to ReportStorage.dump().
2955
+ *
2956
+ * @param strategyName - Strategy name to save report for
2957
+ * @param path - Directory path to save report (default: "./logs/schedule")
2958
+ *
2959
+ * @example
2960
+ * ```typescript
2961
+ * const service = new ScheduleMarkdownService();
2962
+ *
2963
+ * // Save to default path: ./logs/schedule/my-strategy.md
2964
+ * await service.dump("my-strategy");
2965
+ *
2966
+ * // Save to custom path: ./custom/path/my-strategy.md
2967
+ * await service.dump("my-strategy", "./custom/path");
2968
+ * ```
2969
+ */
2970
+ dump: (strategyName: StrategyName, path?: string) => Promise<void>;
2971
+ /**
2972
+ * Clears accumulated event data from storage.
2973
+ * If strategyName is provided, clears only that strategy's data.
2974
+ * If strategyName is omitted, clears all strategies' data.
2975
+ *
2976
+ * @param strategyName - Optional strategy name to clear specific strategy data
2977
+ *
2978
+ * @example
2979
+ * ```typescript
2980
+ * const service = new ScheduleMarkdownService();
2981
+ *
2982
+ * // Clear specific strategy data
2983
+ * await service.clear("my-strategy");
2984
+ *
2985
+ * // Clear all strategies' data
2986
+ * await service.clear();
2987
+ * ```
2988
+ */
2989
+ clear: (strategyName?: StrategyName) => Promise<void>;
2990
+ /**
2991
+ * Initializes the service by subscribing to live signal events.
2992
+ * Uses singleshot to ensure initialization happens only once.
2993
+ * Automatically called on first use.
2994
+ *
2995
+ * @example
2996
+ * ```typescript
2997
+ * const service = new ScheduleMarkdownService();
2998
+ * await service.init(); // Subscribe to live events
2999
+ * ```
3000
+ */
3001
+ protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
3002
+ }
3003
+
2661
3004
  /**
2662
3005
  * Aggregated statistics for a specific metric type.
2663
3006
  */
@@ -3130,7 +3473,7 @@ declare class PersistSignalUtils {
3130
3473
  * async readValue(id) { return JSON.parse(await redis.get(id)); }
3131
3474
  * async writeValue(id, entity) { await redis.set(id, JSON.stringify(entity)); }
3132
3475
  * }
3133
- * PersistSignalAdaper.usePersistSignalAdapter(RedisPersist);
3476
+ * PersistSignalAdapter.usePersistSignalAdapter(RedisPersist);
3134
3477
  * ```
3135
3478
  */
3136
3479
  usePersistSignalAdapter(Ctor: TPersistBaseCtor<StrategyName, SignalData>): void;
@@ -3165,16 +3508,16 @@ declare class PersistSignalUtils {
3165
3508
  * @example
3166
3509
  * ```typescript
3167
3510
  * // Custom adapter
3168
- * PersistSignalAdaper.usePersistSignalAdapter(RedisPersist);
3511
+ * PersistSignalAdapter.usePersistSignalAdapter(RedisPersist);
3169
3512
  *
3170
3513
  * // Read signal
3171
- * const signal = await PersistSignalAdaper.readSignalData("my-strategy", "BTCUSDT");
3514
+ * const signal = await PersistSignalAdapter.readSignalData("my-strategy", "BTCUSDT");
3172
3515
  *
3173
3516
  * // Write signal
3174
- * await PersistSignalAdaper.writeSignalData(signal, "my-strategy", "BTCUSDT");
3517
+ * await PersistSignalAdapter.writeSignalData(signal, "my-strategy", "BTCUSDT");
3175
3518
  * ```
3176
3519
  */
3177
- declare const PersistSignalAdaper: PersistSignalUtils;
3520
+ declare const PersistSignalAdapter: PersistSignalUtils;
3178
3521
  /**
3179
3522
  * Type for persisted risk positions data.
3180
3523
  * Stores Map entries as array of [key, value] tuples for JSON serialization.
@@ -3280,7 +3623,7 @@ declare class BacktestUtils {
3280
3623
  strategyName: string;
3281
3624
  exchangeName: string;
3282
3625
  frameName: string;
3283
- }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
3626
+ }) => AsyncGenerator<IStrategyBacktestResult, void, unknown>;
3284
3627
  /**
3285
3628
  * Runs backtest in background without yielding results.
3286
3629
  *
@@ -3413,7 +3756,7 @@ declare class LiveUtils {
3413
3756
  run: (symbol: string, context: {
3414
3757
  strategyName: string;
3415
3758
  exchangeName: string;
3416
- }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
3759
+ }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, unknown>;
3417
3760
  /**
3418
3761
  * Runs live trading in background without yielding results.
3419
3762
  *
@@ -3499,6 +3842,105 @@ declare class LiveUtils {
3499
3842
  */
3500
3843
  declare const Live: LiveUtils;
3501
3844
 
3845
+ /**
3846
+ * Utility class for scheduled signals reporting operations.
3847
+ *
3848
+ * Provides simplified access to scheduleMarkdownService with logging.
3849
+ * Exported as singleton instance for convenient usage.
3850
+ *
3851
+ * Features:
3852
+ * - Track scheduled signals in queue
3853
+ * - Track cancelled signals
3854
+ * - Calculate cancellation rate and average wait time
3855
+ * - Generate markdown reports
3856
+ *
3857
+ * @example
3858
+ * ```typescript
3859
+ * import { Schedule } from "./classes/Schedule";
3860
+ *
3861
+ * // Get scheduled signals statistics
3862
+ * const stats = await Schedule.getData("my-strategy");
3863
+ * console.log(`Cancellation rate: ${stats.cancellationRate}%`);
3864
+ * console.log(`Average wait time: ${stats.avgWaitTime} minutes`);
3865
+ *
3866
+ * // Generate and save report
3867
+ * await Schedule.dump("my-strategy");
3868
+ * ```
3869
+ */
3870
+ declare class ScheduleUtils {
3871
+ /**
3872
+ * Gets statistical data from all scheduled signal events for a strategy.
3873
+ *
3874
+ * @param strategyName - Strategy name to get data for
3875
+ * @returns Promise resolving to statistical data object
3876
+ *
3877
+ * @example
3878
+ * ```typescript
3879
+ * const stats = await Schedule.getData("my-strategy");
3880
+ * console.log(stats.cancellationRate, stats.avgWaitTime);
3881
+ * ```
3882
+ */
3883
+ getData: (strategyName: StrategyName) => Promise<ScheduleStatistics>;
3884
+ /**
3885
+ * Generates markdown report with all scheduled events for a strategy.
3886
+ *
3887
+ * @param strategyName - Strategy name to generate report for
3888
+ * @returns Promise resolving to markdown formatted report string
3889
+ *
3890
+ * @example
3891
+ * ```typescript
3892
+ * const markdown = await Schedule.getReport("my-strategy");
3893
+ * console.log(markdown);
3894
+ * ```
3895
+ */
3896
+ getReport: (strategyName: StrategyName) => Promise<string>;
3897
+ /**
3898
+ * Saves strategy report to disk.
3899
+ *
3900
+ * @param strategyName - Strategy name to save report for
3901
+ * @param path - Optional directory path to save report (default: "./logs/schedule")
3902
+ *
3903
+ * @example
3904
+ * ```typescript
3905
+ * // Save to default path: ./logs/schedule/my-strategy.md
3906
+ * await Schedule.dump("my-strategy");
3907
+ *
3908
+ * // Save to custom path: ./custom/path/my-strategy.md
3909
+ * await Schedule.dump("my-strategy", "./custom/path");
3910
+ * ```
3911
+ */
3912
+ dump: (strategyName: StrategyName, path?: string) => Promise<void>;
3913
+ /**
3914
+ * Clears accumulated scheduled signal data from storage.
3915
+ * If strategyName is provided, clears only that strategy's data.
3916
+ * If strategyName is omitted, clears all strategies' data.
3917
+ *
3918
+ * @param strategyName - Optional strategy name to clear specific strategy data
3919
+ *
3920
+ * @example
3921
+ * ```typescript
3922
+ * // Clear specific strategy data
3923
+ * await Schedule.clear("my-strategy");
3924
+ *
3925
+ * // Clear all strategies' data
3926
+ * await Schedule.clear();
3927
+ * ```
3928
+ */
3929
+ clear: (strategyName?: StrategyName) => Promise<void>;
3930
+ }
3931
+ /**
3932
+ * Singleton instance of ScheduleUtils for convenient scheduled signals reporting.
3933
+ *
3934
+ * @example
3935
+ * ```typescript
3936
+ * import { Schedule } from "./classes/Schedule";
3937
+ *
3938
+ * const stats = await Schedule.getData("my-strategy");
3939
+ * console.log("Cancellation rate:", stats.cancellationRate);
3940
+ * ```
3941
+ */
3942
+ declare const Schedule: ScheduleUtils;
3943
+
3502
3944
  /**
3503
3945
  * Performance class provides static methods for performance metrics analysis.
3504
3946
  *
@@ -4128,7 +4570,8 @@ declare class ClientExchange implements IExchange {
4128
4570
  */
4129
4571
  getNextCandles(symbol: string, interval: CandleInterval, limit: number): Promise<ICandleData[]>;
4130
4572
  /**
4131
- * Calculates VWAP (Volume Weighted Average Price) from last 5 1m candles.
4573
+ * Calculates VWAP (Volume Weighted Average Price) from last N 1m candles.
4574
+ * The number of candles is configurable via GLOBAL_CONFIG.CC_AVG_PRICE_CANDLES_COUNT.
4132
4575
  *
4133
4576
  * Formula:
4134
4577
  * - Typical Price = (high + low + close) / 3
@@ -4385,7 +4828,7 @@ declare class FrameConnectionService implements IFrame {
4385
4828
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
4386
4829
  * @returns Promise resolving to { startDate: Date, endDate: Date }
4387
4830
  */
4388
- getTimeframe: (symbol: string) => Promise<Date[]>;
4831
+ getTimeframe: (symbol: string, frameName: string) => Promise<Date[]>;
4389
4832
  }
4390
4833
 
4391
4834
  /**
@@ -4616,6 +5059,12 @@ declare class RiskConnectionService {
4616
5059
  strategyName: string;
4617
5060
  riskName: RiskName;
4618
5061
  }) => Promise<void>;
5062
+ /**
5063
+ * Clears the cached ClientRisk instance for the given risk name.
5064
+ *
5065
+ * @param riskName - Name of the risk schema to clear from cache
5066
+ */
5067
+ clear: (riskName?: RiskName) => Promise<void>;
4619
5068
  }
4620
5069
 
4621
5070
  /**
@@ -4629,6 +5078,16 @@ declare class RiskConnectionService {
4629
5078
  declare class ExchangeGlobalService {
4630
5079
  private readonly loggerService;
4631
5080
  private readonly exchangeConnectionService;
5081
+ private readonly methodContextService;
5082
+ private readonly exchangeValidationService;
5083
+ /**
5084
+ * Validates exchange configuration.
5085
+ * Memoized to avoid redundant validations for the same exchange.
5086
+ * Logs validation activity.
5087
+ * @param exchangeName - Name of the exchange to validate
5088
+ * @returns Promise that resolves when validation is complete
5089
+ */
5090
+ private validate;
4632
5091
  /**
4633
5092
  * Fetches historical candles with execution context.
4634
5093
  *
@@ -4693,6 +5152,19 @@ declare class ExchangeGlobalService {
4693
5152
  declare class StrategyGlobalService {
4694
5153
  private readonly loggerService;
4695
5154
  private readonly strategyConnectionService;
5155
+ private readonly strategySchemaService;
5156
+ private readonly riskValidationService;
5157
+ private readonly strategyValidationService;
5158
+ private readonly methodContextService;
5159
+ /**
5160
+ * Validates strategy and associated risk configuration.
5161
+ *
5162
+ * Memoized to avoid redundant validations for the same strategy.
5163
+ * Logs validation activity.
5164
+ * @param strategyName - Name of the strategy to validate
5165
+ * @returns Promise that resolves when validation is complete
5166
+ */
5167
+ private validate;
4696
5168
  /**
4697
5169
  * Checks signal status at a specific timestamp.
4698
5170
  *
@@ -4736,7 +5208,7 @@ declare class StrategyGlobalService {
4736
5208
  *
4737
5209
  * @param strategyName - Name of strategy to clear from cache
4738
5210
  */
4739
- clear: (strategyName: StrategyName) => Promise<void>;
5211
+ clear: (strategyName?: StrategyName) => Promise<void>;
4740
5212
  }
4741
5213
 
4742
5214
  /**
@@ -4748,13 +5220,14 @@ declare class StrategyGlobalService {
4748
5220
  declare class FrameGlobalService {
4749
5221
  private readonly loggerService;
4750
5222
  private readonly frameConnectionService;
5223
+ private readonly frameValidationService;
4751
5224
  /**
4752
5225
  * Generates timeframe array for backtest iteration.
4753
5226
  *
4754
- * @param symbol - Trading pair symbol
5227
+ * @param frameName - Target frame name (e.g., "1m", "1h")
4755
5228
  * @returns Promise resolving to array of Date objects
4756
5229
  */
4757
- getTimeframe: (symbol: string) => Promise<Date[]>;
5230
+ getTimeframe: (symbol: string, frameName: string) => Promise<Date[]>;
4758
5231
  }
4759
5232
 
4760
5233
  /**
@@ -4766,6 +5239,7 @@ declare class FrameGlobalService {
4766
5239
  declare class SizingGlobalService {
4767
5240
  private readonly loggerService;
4768
5241
  private readonly sizingConnectionService;
5242
+ private readonly sizingValidationService;
4769
5243
  /**
4770
5244
  * Calculates position size based on risk parameters.
4771
5245
  *
@@ -4787,6 +5261,15 @@ declare class SizingGlobalService {
4787
5261
  declare class RiskGlobalService {
4788
5262
  private readonly loggerService;
4789
5263
  private readonly riskConnectionService;
5264
+ private readonly riskValidationService;
5265
+ /**
5266
+ * Validates risk configuration.
5267
+ * Memoized to avoid redundant validations for the same risk instance.
5268
+ * Logs validation activity.
5269
+ * @param riskName - Name of the risk instance to validate
5270
+ * @returns Promise that resolves when validation is complete
5271
+ */
5272
+ private validate;
4790
5273
  /**
4791
5274
  * Checks if a signal should be allowed based on risk limits.
4792
5275
  *
@@ -4817,6 +5300,13 @@ declare class RiskGlobalService {
4817
5300
  strategyName: string;
4818
5301
  riskName: RiskName;
4819
5302
  }) => Promise<void>;
5303
+ /**
5304
+ * Clears risk data.
5305
+ * If riskName is provided, clears data for that specific risk instance.
5306
+ * If no riskName is provided, clears all risk data.
5307
+ * @param riskName - Optional name of the risk instance to clear
5308
+ */
5309
+ clear: (riskName?: RiskName) => Promise<void>;
4820
5310
  }
4821
5311
 
4822
5312
  /**
@@ -4828,6 +5318,13 @@ declare class RiskGlobalService {
4828
5318
  declare class WalkerGlobalService {
4829
5319
  private readonly loggerService;
4830
5320
  private readonly walkerLogicPublicService;
5321
+ private readonly walkerSchemaService;
5322
+ private readonly strategyValidationService;
5323
+ private readonly exchangeValidationService;
5324
+ private readonly frameValidationService;
5325
+ private readonly walkerValidationService;
5326
+ private readonly strategySchemaService;
5327
+ private readonly riskValidationService;
4831
5328
  /**
4832
5329
  * Runs walker comparison for a symbol with context propagation.
4833
5330
  *
@@ -5162,7 +5659,7 @@ declare class BacktestLogicPrivateService {
5162
5659
  * }
5163
5660
  * ```
5164
5661
  */
5165
- run(symbol: string): AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
5662
+ run(symbol: string): AsyncGenerator<IStrategyBacktestResult, void, unknown>;
5166
5663
  }
5167
5664
 
5168
5665
  /**
@@ -5207,7 +5704,7 @@ declare class LiveLogicPrivateService {
5207
5704
  * }
5208
5705
  * ```
5209
5706
  */
5210
- run(symbol: string): AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
5707
+ run(symbol: string): AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, unknown>;
5211
5708
  }
5212
5709
 
5213
5710
  /**
@@ -5301,7 +5798,7 @@ declare class BacktestLogicPublicService {
5301
5798
  strategyName: string;
5302
5799
  exchangeName: string;
5303
5800
  frameName: string;
5304
- }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
5801
+ }) => AsyncGenerator<IStrategyBacktestResult, void, unknown>;
5305
5802
  }
5306
5803
 
5307
5804
  /**
@@ -5352,7 +5849,7 @@ declare class LiveLogicPublicService {
5352
5849
  run: (symbol: string, context: {
5353
5850
  strategyName: string;
5354
5851
  exchangeName: string;
5355
- }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
5852
+ }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, unknown>;
5356
5853
  }
5357
5854
 
5358
5855
  /**
@@ -5406,6 +5903,8 @@ declare class LiveGlobalService {
5406
5903
  private readonly liveLogicPublicService;
5407
5904
  private readonly strategyValidationService;
5408
5905
  private readonly exchangeValidationService;
5906
+ private readonly strategySchemaService;
5907
+ private readonly riskValidationService;
5409
5908
  /**
5410
5909
  * Runs live trading for a symbol with context propagation.
5411
5910
  *
@@ -5418,7 +5917,7 @@ declare class LiveGlobalService {
5418
5917
  run: (symbol: string, context: {
5419
5918
  strategyName: string;
5420
5919
  exchangeName: string;
5421
- }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
5920
+ }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed | IStrategyTickResultCancelled, void, unknown>;
5422
5921
  }
5423
5922
 
5424
5923
  /**
@@ -5429,6 +5928,8 @@ declare class LiveGlobalService {
5429
5928
  */
5430
5929
  declare class BacktestGlobalService {
5431
5930
  private readonly loggerService;
5931
+ private readonly strategySchemaService;
5932
+ private readonly riskValidationService;
5432
5933
  private readonly backtestLogicPublicService;
5433
5934
  private readonly strategyValidationService;
5434
5935
  private readonly exchangeValidationService;
@@ -5444,7 +5945,7 @@ declare class BacktestGlobalService {
5444
5945
  strategyName: string;
5445
5946
  exchangeName: string;
5446
5947
  frameName: string;
5447
- }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
5948
+ }) => AsyncGenerator<IStrategyBacktestResult, void, unknown>;
5448
5949
  }
5449
5950
 
5450
5951
  /**
@@ -5827,6 +6328,7 @@ declare const backtest: {
5827
6328
  riskValidationService: RiskValidationService;
5828
6329
  backtestMarkdownService: BacktestMarkdownService;
5829
6330
  liveMarkdownService: LiveMarkdownService;
6331
+ scheduleMarkdownService: ScheduleMarkdownService;
5830
6332
  performanceMarkdownService: PerformanceMarkdownService;
5831
6333
  walkerMarkdownService: WalkerMarkdownService;
5832
6334
  heatMarkdownService: HeatMarkdownService;
@@ -5864,4 +6366,4 @@ declare const backtest: {
5864
6366
  loggerService: LoggerService;
5865
6367
  };
5866
6368
 
5867
- export { Backtest, type BacktestStatistics, type CandleInterval, type DoneContract, type EntityId, ExecutionContextService, type FrameInterval, Heat, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IHeatmapStatistics, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStrategyPnL, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, Live, type LiveStatistics, MethodContextService, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatistics, PersistBase, PersistRiskAdapter, PersistSignalAdaper, PositionSize, type ProgressContract, type RiskData, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, Walker, type WalkerMetric, type WalkerStatistics, addExchange, addFrame, addRisk, addSizing, addStrategy, addWalker, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, backtest as lib, listExchanges, listFrames, listRisks, listSizings, listStrategies, listWalkers, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenPerformance, listenProgress, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, setLogger };
6369
+ export { Backtest, type BacktestStatistics, type CandleInterval, type DoneContract, type EntityId, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IHeatmapStatistics, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, 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 IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, Live, type LiveStatistics, MethodContextService, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatistics, PersistBase, PersistRiskAdapter, PersistSignalAdapter, PositionSize, type ProgressContract, type RiskData, Schedule, type ScheduleStatistics, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, Walker, type WalkerMetric, type WalkerStatistics, addExchange, addFrame, addRisk, addSizing, addStrategy, addWalker, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, backtest as lib, listExchanges, listFrames, listRisks, listSizings, listStrategies, listWalkers, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenPerformance, listenProgress, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, setConfig, setLogger };