backtest-kit 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/README.md +707 -153
  2. package/build/index.cjs +2906 -192
  3. package/build/index.mjs +2901 -188
  4. package/package.json +2 -9
  5. package/types.d.ts +2205 -60
package/types.d.ts CHANGED
@@ -22,15 +22,65 @@ interface ILogger {
22
22
  * Used to record informational updates, such as successful completions, policy validations, or history commits, providing a high-level overview of system activity without excessive detail.
23
23
  */
24
24
  info(topic: string, ...args: any[]): void;
25
+ /**
26
+ * Logs a warning-level message.
27
+ * Used to record potentially problematic situations that don't prevent execution but may require attention, such as missing data, unexpected conditions, or deprecated usage.
28
+ */
29
+ warn(topic: string, ...args: any[]): void;
25
30
  }
26
31
 
32
+ /**
33
+ * Sets custom logger implementation for the framework.
34
+ *
35
+ * All log messages from internal services will be forwarded to the provided logger
36
+ * with automatic context injection (strategyName, exchangeName, symbol, etc.).
37
+ *
38
+ * @param logger - Custom logger implementing ILogger interface
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * setLogger({
43
+ * log: (topic, ...args) => console.log(topic, args),
44
+ * debug: (topic, ...args) => console.debug(topic, args),
45
+ * info: (topic, ...args) => console.info(topic, args),
46
+ * });
47
+ * ```
48
+ */
27
49
  declare function setLogger(logger: ILogger): Promise<void>;
28
50
 
51
+ /**
52
+ * Execution context containing runtime parameters for strategy/exchange operations.
53
+ *
54
+ * Propagated through ExecutionContextService to provide implicit context
55
+ * for getCandles(), tick(), backtest() and other operations.
56
+ */
29
57
  interface IExecutionContext {
58
+ /** Trading pair symbol (e.g., "BTCUSDT") */
30
59
  symbol: string;
60
+ /** Current timestamp for operation */
31
61
  when: Date;
62
+ /** Whether running in backtest mode (true) or live mode (false) */
32
63
  backtest: boolean;
33
64
  }
65
+ /**
66
+ * Scoped service for execution context propagation.
67
+ *
68
+ * Uses di-scoped for implicit context passing without explicit parameters.
69
+ * Context includes symbol, when (timestamp), and backtest flag.
70
+ *
71
+ * Used by GlobalServices to inject context into operations.
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * ExecutionContextService.runInContext(
76
+ * async () => {
77
+ * // Inside this callback, context is automatically available
78
+ * return await someOperation();
79
+ * },
80
+ * { symbol: "BTCUSDT", when: new Date(), backtest: true }
81
+ * );
82
+ * ```
83
+ */
34
84
  declare const ExecutionContextService: (new () => {
35
85
  readonly context: IExecutionContext;
36
86
  }) & Omit<{
@@ -38,351 +88,2022 @@ declare const ExecutionContextService: (new () => {
38
88
  readonly context: IExecutionContext;
39
89
  };
40
90
  }, "prototype"> & di_scoped.IScopedClassRun<[context: IExecutionContext]>;
91
+ /**
92
+ * Type helper for ExecutionContextService instance.
93
+ * Used for dependency injection type annotations.
94
+ */
41
95
  type TExecutionContextService = InstanceType<typeof ExecutionContextService>;
42
96
 
97
+ /**
98
+ * Candle time interval for fetching historical data.
99
+ */
43
100
  type CandleInterval = "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h";
101
+ /**
102
+ * Single OHLCV candle data point.
103
+ * Used for VWAP calculation and backtesting.
104
+ */
44
105
  interface ICandleData {
106
+ /** Unix timestamp in milliseconds when candle opened */
45
107
  timestamp: number;
108
+ /** Opening price at candle start */
46
109
  open: number;
110
+ /** Highest price during candle period */
47
111
  high: number;
112
+ /** Lowest price during candle period */
48
113
  low: number;
114
+ /** Closing price at candle end */
49
115
  close: number;
116
+ /** Trading volume during candle period */
50
117
  volume: number;
51
118
  }
119
+ /**
120
+ * Exchange parameters passed to ClientExchange constructor.
121
+ * Combines schema with runtime dependencies.
122
+ */
52
123
  interface IExchangeParams extends IExchangeSchema {
124
+ /** Logger service for debug output */
53
125
  logger: ILogger;
126
+ /** Execution context service (symbol, when, backtest flag) */
54
127
  execution: TExecutionContextService;
55
128
  }
129
+ /**
130
+ * Optional callbacks for exchange data events.
131
+ */
56
132
  interface IExchangeCallbacks {
133
+ /** Called when candle data is fetched */
57
134
  onCandleData: (symbol: string, interval: CandleInterval, since: Date, limit: number, data: ICandleData[]) => void;
58
135
  }
136
+ /**
137
+ * Exchange schema registered via addExchange().
138
+ * Defines candle data source and formatting logic.
139
+ */
59
140
  interface IExchangeSchema {
141
+ /** Unique exchange identifier for registration */
60
142
  exchangeName: ExchangeName;
143
+ /**
144
+ * Fetch candles from data source (API or database).
145
+ *
146
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
147
+ * @param interval - Candle time interval (e.g., "1m", "1h")
148
+ * @param since - Start date for candle fetching
149
+ * @param limit - Maximum number of candles to fetch
150
+ * @returns Promise resolving to array of OHLCV candle data
151
+ */
61
152
  getCandles: (symbol: string, interval: CandleInterval, since: Date, limit: number) => Promise<ICandleData[]>;
153
+ /**
154
+ * Format quantity according to exchange precision rules.
155
+ *
156
+ * @param symbol - Trading pair symbol
157
+ * @param quantity - Raw quantity value
158
+ * @returns Promise resolving to formatted quantity string
159
+ */
62
160
  formatQuantity: (symbol: string, quantity: number) => Promise<string>;
161
+ /**
162
+ * Format price according to exchange precision rules.
163
+ *
164
+ * @param symbol - Trading pair symbol
165
+ * @param price - Raw price value
166
+ * @returns Promise resolving to formatted price string
167
+ */
63
168
  formatPrice: (symbol: string, price: number) => Promise<string>;
169
+ /** Optional lifecycle event callbacks (onCandleData) */
64
170
  callbacks?: Partial<IExchangeCallbacks>;
65
171
  }
172
+ /**
173
+ * Exchange interface implemented by ClientExchange.
174
+ * Provides candle data access and VWAP calculation.
175
+ */
66
176
  interface IExchange {
177
+ /**
178
+ * Fetch historical candles backwards from execution context time.
179
+ *
180
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
181
+ * @param interval - Candle time interval (e.g., "1m", "1h")
182
+ * @param limit - Maximum number of candles to fetch
183
+ * @returns Promise resolving to array of candle data
184
+ */
67
185
  getCandles: (symbol: string, interval: CandleInterval, limit: number) => Promise<ICandleData[]>;
186
+ /**
187
+ * Fetch future candles forward from execution context time (for backtest).
188
+ *
189
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
190
+ * @param interval - Candle time interval (e.g., "1m", "1h")
191
+ * @param limit - Maximum number of candles to fetch
192
+ * @returns Promise resolving to array of candle data
193
+ */
68
194
  getNextCandles: (symbol: string, interval: CandleInterval, limit: number) => Promise<ICandleData[]>;
195
+ /**
196
+ * Format quantity for exchange precision.
197
+ *
198
+ * @param symbol - Trading pair symbol
199
+ * @param quantity - Raw quantity value
200
+ * @returns Promise resolving to formatted quantity string
201
+ */
69
202
  formatQuantity: (symbol: string, quantity: number) => Promise<string>;
203
+ /**
204
+ * Format price for exchange precision.
205
+ *
206
+ * @param symbol - Trading pair symbol
207
+ * @param price - Raw price value
208
+ * @returns Promise resolving to formatted price string
209
+ */
70
210
  formatPrice: (symbol: string, price: number) => Promise<string>;
211
+ /**
212
+ * Calculate VWAP from last 5 1-minute candles.
213
+ *
214
+ * Formula: VWAP = Σ(Typical Price × Volume) / Σ(Volume)
215
+ * where Typical Price = (High + Low + Close) / 3
216
+ *
217
+ * @param symbol - Trading pair symbol
218
+ * @returns Promise resolving to volume-weighted average price
219
+ */
71
220
  getAveragePrice: (symbol: string) => Promise<number>;
72
221
  }
222
+ /**
223
+ * Unique exchange identifier.
224
+ */
73
225
  type ExchangeName = string;
74
226
 
227
+ /**
228
+ * Timeframe interval for backtest period generation.
229
+ * Determines the granularity of timestamps in the generated timeframe array.
230
+ *
231
+ * Minutes: 1m, 3m, 5m, 15m, 30m
232
+ * Hours: 1h, 2h, 4h, 6h, 8h, 12h
233
+ * Days: 1d, 3d
234
+ */
235
+ type FrameInterval = "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d" | "3d";
236
+ /**
237
+ * Frame parameters passed to ClientFrame constructor.
238
+ * Extends IFrameSchema with logger instance for internal logging.
239
+ */
240
+ interface IFrameParams extends IFrameSchema {
241
+ /** Logger service for debug output */
242
+ logger: ILogger;
243
+ }
244
+ /**
245
+ * Callbacks for frame lifecycle events.
246
+ */
247
+ interface IFrameCallbacks {
248
+ /**
249
+ * Called after timeframe array generation.
250
+ * Useful for logging or validating the generated timeframes.
251
+ *
252
+ * @param timeframe - Array of Date objects representing tick timestamps
253
+ * @param startDate - Start of the backtest period
254
+ * @param endDate - End of the backtest period
255
+ * @param interval - Interval used for generation
256
+ */
257
+ onTimeframe: (timeframe: Date[], startDate: Date, endDate: Date, interval: FrameInterval) => void;
258
+ }
259
+ /**
260
+ * Frame schema registered via addFrame().
261
+ * Defines backtest period and interval for timestamp generation.
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * addFrame({
266
+ * frameName: "1d-backtest",
267
+ * interval: "1m",
268
+ * startDate: new Date("2024-01-01T00:00:00Z"),
269
+ * endDate: new Date("2024-01-02T00:00:00Z"),
270
+ * callbacks: {
271
+ * onTimeframe: (timeframe, startDate, endDate, interval) => {
272
+ * console.log(`Generated ${timeframe.length} timestamps`);
273
+ * },
274
+ * },
275
+ * });
276
+ * ```
277
+ */
278
+ interface IFrameSchema {
279
+ /** Unique identifier for this frame */
280
+ frameName: FrameName;
281
+ /** Interval for timestamp generation */
282
+ interval: FrameInterval;
283
+ /** Start of backtest period (inclusive) */
284
+ startDate: Date;
285
+ /** End of backtest period (inclusive) */
286
+ endDate: Date;
287
+ /** Optional lifecycle callbacks */
288
+ callbacks?: Partial<IFrameCallbacks>;
289
+ }
290
+ /**
291
+ * Frame interface for timeframe generation.
292
+ * Used internally by backtest orchestration.
293
+ */
294
+ interface IFrame {
295
+ /**
296
+ * Generates array of timestamps for backtest iteration.
297
+ * Timestamps are spaced according to the configured interval.
298
+ *
299
+ * @param symbol - Trading pair symbol (unused, for API consistency)
300
+ * @returns Promise resolving to array of Date objects
301
+ */
302
+ getTimeframe: (symbol: string) => Promise<Date[]>;
303
+ }
304
+ /**
305
+ * Unique identifier for a frame schema.
306
+ * Used to retrieve frame instances via dependency injection.
307
+ */
308
+ type FrameName = string;
309
+
310
+ /**
311
+ * Method context containing schema names for operation routing.
312
+ *
313
+ * Propagated through MethodContextService to provide implicit context
314
+ * for retrieving correct strategy/exchange/frame instances.
315
+ */
316
+ interface IMethodContext {
317
+ /** Name of exchange schema to use */
318
+ exchangeName: ExchangeName;
319
+ /** Name of strategy schema to use */
320
+ strategyName: StrategyName;
321
+ /** Name of frame schema to use (empty string for live mode) */
322
+ frameName: FrameName;
323
+ }
324
+ /**
325
+ * Scoped service for method context propagation.
326
+ *
327
+ * Uses di-scoped for implicit context passing without explicit parameters.
328
+ * Context includes strategyName, exchangeName, and frameName.
329
+ *
330
+ * Used by PublicServices to inject schema names into ConnectionServices.
331
+ *
332
+ * @example
333
+ * ```typescript
334
+ * MethodContextService.runAsyncIterator(
335
+ * backtestGenerator,
336
+ * {
337
+ * strategyName: "my-strategy",
338
+ * exchangeName: "my-exchange",
339
+ * frameName: "1d-backtest"
340
+ * }
341
+ * );
342
+ * ```
343
+ */
344
+ declare const MethodContextService: (new () => {
345
+ readonly context: IMethodContext;
346
+ }) & Omit<{
347
+ new (context: IMethodContext): {
348
+ readonly context: IMethodContext;
349
+ };
350
+ }, "prototype"> & di_scoped.IScopedClassRun<[context: IMethodContext]>;
351
+
352
+ /**
353
+ * Signal generation interval for throttling.
354
+ * Enforces minimum time between getSignal calls.
355
+ */
75
356
  type SignalInterval = "1m" | "3m" | "5m" | "15m" | "30m" | "1h";
357
+ /**
358
+ * Signal data transfer object returned by getSignal.
359
+ * Will be validated and augmented with auto-generated id.
360
+ */
76
361
  interface ISignalDto {
362
+ /** Optional signal ID (auto-generated if not provided) */
77
363
  id?: string;
364
+ /** Trade direction: "long" (buy) or "short" (sell) */
78
365
  position: "long" | "short";
79
- note: string;
366
+ /** Human-readable description of signal reason */
367
+ note?: string;
368
+ /** Entry price for the position */
80
369
  priceOpen: number;
370
+ /** Take profit target price (must be > priceOpen for long, < priceOpen for short) */
81
371
  priceTakeProfit: number;
372
+ /** Stop loss exit price (must be < priceOpen for long, > priceOpen for short) */
82
373
  priceStopLoss: number;
374
+ /** Expected duration in minutes before time_expired */
83
375
  minuteEstimatedTime: number;
84
- timestamp: number;
85
376
  }
377
+ /**
378
+ * Complete signal with auto-generated id.
379
+ * Used throughout the system after validation.
380
+ */
86
381
  interface ISignalRow extends ISignalDto {
382
+ /** Unique signal identifier (UUID v4 auto-generated) */
87
383
  id: string;
384
+ /** Unique exchange identifier for execution */
385
+ exchangeName: ExchangeName;
386
+ /** Unique strategy identifier for execution */
387
+ strategyName: StrategyName;
388
+ /** Signal creation timestamp in milliseconds */
389
+ timestamp: number;
390
+ /** Trading pair symbol (e.g., "BTCUSDT") */
391
+ symbol: string;
88
392
  }
393
+ /**
394
+ * Optional lifecycle callbacks for signal events.
395
+ * Called when signals are opened, active, idle, or closed.
396
+ */
89
397
  interface IStrategyCallbacks {
90
- onOpen: (backtest: boolean, symbol: string, data: ISignalRow) => void;
91
- onClose: (backtest: boolean, symbol: string, priceClose: number, data: ISignalRow) => void;
398
+ /** Called on every tick with the result */
399
+ onTick: (symbol: string, result: IStrategyTickResult, backtest: boolean) => void;
400
+ /** Called when new signal is opened (after validation) */
401
+ onOpen: (symbol: string, data: ISignalRow, currentPrice: number, backtest: boolean) => void;
402
+ /** Called when signal is being monitored (active state) */
403
+ onActive: (symbol: string, data: ISignalRow, currentPrice: number, backtest: boolean) => void;
404
+ /** Called when no active signal exists (idle state) */
405
+ onIdle: (symbol: string, currentPrice: number, backtest: boolean) => void;
406
+ /** Called when signal is closed with final price */
407
+ onClose: (symbol: string, data: ISignalRow, priceClose: number, backtest: boolean) => void;
92
408
  }
409
+ /**
410
+ * Strategy schema registered via addStrategy().
411
+ * Defines signal generation logic and configuration.
412
+ */
93
413
  interface IStrategySchema {
414
+ /** Unique strategy identifier for registration */
94
415
  strategyName: StrategyName;
416
+ /** Minimum interval between getSignal calls (throttling) */
95
417
  interval: SignalInterval;
418
+ /** Signal generation function (returns null if no signal, validated DTO if signal) */
96
419
  getSignal: (symbol: string) => Promise<ISignalDto | null>;
420
+ /** Optional lifecycle event callbacks (onOpen, onClose) */
97
421
  callbacks?: Partial<IStrategyCallbacks>;
98
422
  }
423
+ /**
424
+ * Reason why signal was closed.
425
+ * Used in discriminated union for type-safe handling.
426
+ */
99
427
  type StrategyCloseReason = "time_expired" | "take_profit" | "stop_loss";
428
+ /**
429
+ * Profit and loss calculation result.
430
+ * Includes adjusted prices with fees (0.1%) and slippage (0.1%).
431
+ */
100
432
  interface IStrategyPnL {
433
+ /** Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%) */
101
434
  pnlPercentage: number;
435
+ /** Entry price adjusted with slippage and fees */
102
436
  priceOpen: number;
437
+ /** Exit price adjusted with slippage and fees */
103
438
  priceClose: number;
104
439
  }
440
+ /**
441
+ * Tick result: no active signal, idle state.
442
+ */
105
443
  interface IStrategyTickResultIdle {
444
+ /** Discriminator for type-safe union */
106
445
  action: "idle";
446
+ /** No signal in idle state */
107
447
  signal: null;
448
+ /** Strategy name for tracking idle events */
449
+ strategyName: StrategyName;
450
+ /** Exchange name for tracking idle events */
451
+ exchangeName: ExchangeName;
452
+ /** Current VWAP price during idle state */
453
+ currentPrice: number;
108
454
  }
455
+ /**
456
+ * Tick result: new signal just created.
457
+ * Triggered after getSignal validation and persistence.
458
+ */
109
459
  interface IStrategyTickResultOpened {
460
+ /** Discriminator for type-safe union */
110
461
  action: "opened";
462
+ /** Newly created and validated signal with generated ID */
111
463
  signal: ISignalRow;
464
+ /** Strategy name for tracking */
465
+ strategyName: StrategyName;
466
+ /** Exchange name for tracking */
467
+ exchangeName: ExchangeName;
468
+ /** Current VWAP price at signal open */
469
+ currentPrice: number;
112
470
  }
471
+ /**
472
+ * Tick result: signal is being monitored.
473
+ * Waiting for TP/SL or time expiration.
474
+ */
113
475
  interface IStrategyTickResultActive {
476
+ /** Discriminator for type-safe union */
114
477
  action: "active";
478
+ /** Currently monitored signal */
115
479
  signal: ISignalRow;
480
+ /** Current VWAP price for monitoring */
116
481
  currentPrice: number;
482
+ /** Strategy name for tracking */
483
+ strategyName: StrategyName;
484
+ /** Exchange name for tracking */
485
+ exchangeName: ExchangeName;
117
486
  }
487
+ /**
488
+ * Tick result: signal closed with PNL.
489
+ * Final state with close reason and profit/loss calculation.
490
+ */
118
491
  interface IStrategyTickResultClosed {
492
+ /** Discriminator for type-safe union */
119
493
  action: "closed";
494
+ /** Completed signal with original parameters */
120
495
  signal: ISignalRow;
496
+ /** Final VWAP price at close */
121
497
  currentPrice: number;
498
+ /** Why signal closed (time_expired | take_profit | stop_loss) */
122
499
  closeReason: StrategyCloseReason;
500
+ /** Unix timestamp in milliseconds when signal closed */
123
501
  closeTimestamp: number;
502
+ /** Profit/loss calculation with fees and slippage */
124
503
  pnl: IStrategyPnL;
504
+ /** Strategy name for tracking */
505
+ strategyName: StrategyName;
506
+ /** Exchange name for tracking */
507
+ exchangeName: ExchangeName;
125
508
  }
509
+ /**
510
+ * Discriminated union of all tick results.
511
+ * Use type guards: `result.action === "closed"` for type safety.
512
+ */
126
513
  type IStrategyTickResult = IStrategyTickResultIdle | IStrategyTickResultOpened | IStrategyTickResultActive | IStrategyTickResultClosed;
514
+ /**
515
+ * Backtest always returns closed result (TP/SL or time_expired).
516
+ */
127
517
  type IStrategyBacktestResult = IStrategyTickResultClosed;
518
+ /**
519
+ * Strategy interface implemented by ClientStrategy.
520
+ * Defines core strategy execution methods.
521
+ */
128
522
  interface IStrategy {
523
+ /**
524
+ * Single tick of strategy execution with VWAP monitoring.
525
+ * Checks for signal generation (throttled) and TP/SL conditions.
526
+ *
527
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
528
+ * @returns Promise resolving to tick result (idle | opened | active | closed)
529
+ */
129
530
  tick: (symbol: string) => Promise<IStrategyTickResult>;
531
+ /**
532
+ * Fast backtest using historical candles.
533
+ * Iterates through candles, calculates VWAP, checks TP/SL on each candle.
534
+ *
535
+ * @param candles - Array of historical candle data
536
+ * @returns Promise resolving to closed result (always completes signal)
537
+ */
130
538
  backtest: (candles: ICandleData[]) => Promise<IStrategyBacktestResult>;
131
539
  }
540
+ /**
541
+ * Unique strategy identifier.
542
+ */
132
543
  type StrategyName = string;
133
544
 
134
- type FrameInterval = "1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d" | "3d";
135
- interface IFrameParams extends IFrameSchema {
136
- logger: ILogger;
137
- }
138
- interface IFrameCallbacks {
139
- onTimeframe: (timeframe: Date[], startDate: Date, endDate: Date, interval: FrameInterval) => void;
140
- }
141
- interface IFrameSchema {
142
- frameName: FrameName;
143
- interval: FrameInterval;
144
- startDate: Date;
145
- endDate: Date;
146
- callbacks?: Partial<IFrameCallbacks>;
147
- }
148
- interface IFrame {
149
- getTimeframe: (symbol: string) => Promise<Date[]>;
150
- }
151
- type FrameName = string;
152
-
545
+ /**
546
+ * Registers a trading strategy in the framework.
547
+ *
548
+ * The strategy will be validated for:
549
+ * - Signal validation (prices, TP/SL logic, timestamps)
550
+ * - Interval throttling (prevents signal spam)
551
+ * - Crash-safe persistence in live mode
552
+ *
553
+ * @param strategySchema - Strategy configuration object
554
+ * @param strategySchema.strategyName - Unique strategy identifier
555
+ * @param strategySchema.interval - Signal generation interval ("1m" | "3m" | "5m" | "15m" | "30m" | "1h")
556
+ * @param strategySchema.getSignal - Async function that generates trading signals
557
+ * @param strategySchema.callbacks - Optional lifecycle callbacks (onOpen, onClose)
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * addStrategy({
562
+ * strategyName: "my-strategy",
563
+ * interval: "5m",
564
+ * getSignal: async (symbol) => ({
565
+ * position: "long",
566
+ * priceOpen: 50000,
567
+ * priceTakeProfit: 51000,
568
+ * priceStopLoss: 49000,
569
+ * minuteEstimatedTime: 60,
570
+ * timestamp: Date.now(),
571
+ * }),
572
+ * callbacks: {
573
+ * onOpen: (backtest, symbol, signal) => console.log("Signal opened"),
574
+ * onClose: (backtest, symbol, priceClose, signal) => console.log("Signal closed"),
575
+ * },
576
+ * });
577
+ * ```
578
+ */
153
579
  declare function addStrategy(strategySchema: IStrategySchema): void;
580
+ /**
581
+ * Registers an exchange data source in the framework.
582
+ *
583
+ * The exchange provides:
584
+ * - Historical candle data via getCandles
585
+ * - Price/quantity formatting for the exchange
586
+ * - VWAP calculation from last 5 1m candles
587
+ *
588
+ * @param exchangeSchema - Exchange configuration object
589
+ * @param exchangeSchema.exchangeName - Unique exchange identifier
590
+ * @param exchangeSchema.getCandles - Async function to fetch candle data
591
+ * @param exchangeSchema.formatPrice - Async function to format prices
592
+ * @param exchangeSchema.formatQuantity - Async function to format quantities
593
+ * @param exchangeSchema.callbacks - Optional callback for candle data events
594
+ *
595
+ * @example
596
+ * ```typescript
597
+ * addExchange({
598
+ * exchangeName: "binance",
599
+ * getCandles: async (symbol, interval, since, limit) => {
600
+ * // Fetch from Binance API or database
601
+ * return [{
602
+ * timestamp: Date.now(),
603
+ * open: 50000,
604
+ * high: 51000,
605
+ * low: 49000,
606
+ * close: 50500,
607
+ * volume: 1000,
608
+ * }];
609
+ * },
610
+ * formatPrice: async (symbol, price) => price.toFixed(2),
611
+ * formatQuantity: async (symbol, quantity) => quantity.toFixed(8),
612
+ * });
613
+ * ```
614
+ */
154
615
  declare function addExchange(exchangeSchema: IExchangeSchema): void;
616
+ /**
617
+ * Registers a timeframe generator for backtesting.
618
+ *
619
+ * The frame defines:
620
+ * - Start and end dates for backtest period
621
+ * - Interval for timeframe generation
622
+ * - Callback for timeframe generation events
623
+ *
624
+ * @param frameSchema - Frame configuration object
625
+ * @param frameSchema.frameName - Unique frame identifier
626
+ * @param frameSchema.interval - Timeframe interval ("1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h" | "12h" | "1d" | "3d")
627
+ * @param frameSchema.startDate - Start date for timeframe generation
628
+ * @param frameSchema.endDate - End date for timeframe generation
629
+ * @param frameSchema.callbacks - Optional callback for timeframe events
630
+ *
631
+ * @example
632
+ * ```typescript
633
+ * addFrame({
634
+ * frameName: "1d-backtest",
635
+ * interval: "1m",
636
+ * startDate: new Date("2024-01-01T00:00:00Z"),
637
+ * endDate: new Date("2024-01-02T00:00:00Z"),
638
+ * callbacks: {
639
+ * onTimeframe: (timeframe, startDate, endDate, interval) => {
640
+ * console.log(`Generated ${timeframe.length} timeframes`);
641
+ * },
642
+ * },
643
+ * });
644
+ * ```
645
+ */
155
646
  declare function addFrame(frameSchema: IFrameSchema): void;
156
647
 
157
- interface IBacktestResult {
158
- symbol: string;
159
- results: IStrategyTickResult[];
160
- }
161
- declare function runBacktest(symbol: string, timeframes: Date[]): Promise<IBacktestResult>;
162
- declare function runBacktestGUI(symbol: string, timeframes: Date[]): Promise<void>;
163
-
164
- interface IReduceResult<T> {
165
- symbol: string;
166
- accumulator: T;
167
- totalTicks: number;
168
- }
169
- type ReduceCallback<T> = (accumulator: T, index: number, when: Date, symbol: string) => T | Promise<T>;
170
- declare function reduce<T>(symbol: string, timeframes: Date[], callback: ReduceCallback<T>, initialValue: T): Promise<IReduceResult<T>>;
171
-
172
- interface IRunConfig {
173
- symbol: string;
174
- interval: number;
175
- }
176
- declare function startRun(config: IRunConfig): void;
177
- declare function stopRun(symbol: string): void;
178
- declare function stopAll(): void;
648
+ /**
649
+ * Subscribes to all signal events with queued async processing.
650
+ *
651
+ * Events are processed sequentially in order received, even if callback is async.
652
+ * Uses queued wrapper to prevent concurrent execution of the callback.
653
+ *
654
+ * @param fn - Callback function to handle signal events (idle, opened, active, closed)
655
+ * @returns Unsubscribe function to stop listening
656
+ *
657
+ * @example
658
+ * ```typescript
659
+ * import { listenSignal } from "./function/event";
660
+ *
661
+ * const unsubscribe = listenSignal((event) => {
662
+ * if (event.action === "opened") {
663
+ * console.log("New signal opened:", event.signal);
664
+ * } else if (event.action === "closed") {
665
+ * console.log("Signal closed with PNL:", event.pnl.pnlPercentage);
666
+ * }
667
+ * });
668
+ *
669
+ * // Later: stop listening
670
+ * unsubscribe();
671
+ * ```
672
+ */
673
+ declare function listenSignal(fn: (event: IStrategyTickResult) => void): () => void;
674
+ /**
675
+ * Subscribes to filtered signal events with one-time execution.
676
+ *
677
+ * Listens for events matching the filter predicate, then executes callback once
678
+ * and automatically unsubscribes. Useful for waiting for specific signal conditions.
679
+ *
680
+ * @param filterFn - Predicate to filter which events trigger the callback
681
+ * @param fn - Callback function to handle the filtered event (called only once)
682
+ * @returns Unsubscribe function to cancel the listener before it fires
683
+ *
684
+ * @example
685
+ * ```typescript
686
+ * import { listenSignalOnce } from "./function/event";
687
+ *
688
+ * // Wait for first take profit hit
689
+ * listenSignalOnce(
690
+ * (event) => event.action === "closed" && event.closeReason === "take_profit",
691
+ * (event) => {
692
+ * console.log("Take profit hit! PNL:", event.pnl.pnlPercentage);
693
+ * }
694
+ * );
695
+ *
696
+ * // Wait for any signal to close on BTCUSDT
697
+ * const cancel = listenSignalOnce(
698
+ * (event) => event.action === "closed" && event.signal.symbol === "BTCUSDT",
699
+ * (event) => console.log("BTCUSDT signal closed")
700
+ * );
701
+ *
702
+ * // Cancel if needed before event fires
703
+ * cancel();
704
+ * ```
705
+ */
706
+ declare function listenSignalOnce(filterFn: (event: IStrategyTickResult) => boolean, fn: (event: IStrategyTickResult) => void): () => void;
707
+ /**
708
+ * Subscribes to live trading signal events with queued async processing.
709
+ *
710
+ * Only receives events from Live.run() execution.
711
+ * Events are processed sequentially in order received.
712
+ *
713
+ * @param fn - Callback function to handle live signal events
714
+ * @returns Unsubscribe function to stop listening
715
+ *
716
+ * @example
717
+ * ```typescript
718
+ * import { listenSignalLive } from "./function/event";
719
+ *
720
+ * const unsubscribe = listenSignalLive((event) => {
721
+ * if (event.action === "closed") {
722
+ * console.log("Live signal closed:", event.pnl.pnlPercentage);
723
+ * }
724
+ * });
725
+ * ```
726
+ */
727
+ declare function listenSignalLive(fn: (event: IStrategyTickResult) => void): () => void;
728
+ /**
729
+ * Subscribes to filtered live signal events with one-time execution.
730
+ *
731
+ * Only receives events from Live.run() execution.
732
+ * Executes callback once and automatically unsubscribes.
733
+ *
734
+ * @param filterFn - Predicate to filter which events trigger the callback
735
+ * @param fn - Callback function to handle the filtered event (called only once)
736
+ * @returns Unsubscribe function to cancel the listener before it fires
737
+ *
738
+ * @example
739
+ * ```typescript
740
+ * import { listenSignalLiveOnce } from "./function/event";
741
+ *
742
+ * // Wait for first live take profit hit
743
+ * listenSignalLiveOnce(
744
+ * (event) => event.action === "closed" && event.closeReason === "take_profit",
745
+ * (event) => console.log("Live take profit:", event.pnl.pnlPercentage)
746
+ * );
747
+ * ```
748
+ */
749
+ declare function listenSignalLiveOnce(filterFn: (event: IStrategyTickResult) => boolean, fn: (event: IStrategyTickResult) => void): () => void;
750
+ /**
751
+ * Subscribes to backtest signal events with queued async processing.
752
+ *
753
+ * Only receives events from Backtest.run() execution.
754
+ * Events are processed sequentially in order received.
755
+ *
756
+ * @param fn - Callback function to handle backtest signal events
757
+ * @returns Unsubscribe function to stop listening
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * import { listenSignalBacktest } from "./function/event";
762
+ *
763
+ * const unsubscribe = listenSignalBacktest((event) => {
764
+ * if (event.action === "closed") {
765
+ * console.log("Backtest signal closed:", event.pnl.pnlPercentage);
766
+ * }
767
+ * });
768
+ * ```
769
+ */
770
+ declare function listenSignalBacktest(fn: (event: IStrategyTickResult) => void): () => void;
771
+ /**
772
+ * Subscribes to filtered backtest signal events with one-time execution.
773
+ *
774
+ * Only receives events from Backtest.run() execution.
775
+ * Executes callback once and automatically unsubscribes.
776
+ *
777
+ * @param filterFn - Predicate to filter which events trigger the callback
778
+ * @param fn - Callback function to handle the filtered event (called only once)
779
+ * @returns Unsubscribe function to cancel the listener before it fires
780
+ *
781
+ * @example
782
+ * ```typescript
783
+ * import { listenSignalBacktestOnce } from "./function/event";
784
+ *
785
+ * // Wait for first backtest stop loss hit
786
+ * listenSignalBacktestOnce(
787
+ * (event) => event.action === "closed" && event.closeReason === "stop_loss",
788
+ * (event) => console.log("Backtest stop loss:", event.pnl.pnlPercentage)
789
+ * );
790
+ * ```
791
+ */
792
+ declare function listenSignalBacktestOnce(filterFn: (event: IStrategyTickResult) => boolean, fn: (event: IStrategyTickResult) => void): () => void;
793
+ /**
794
+ * Subscribes to background execution errors with queued async processing.
795
+ *
796
+ * Listens to errors caught in Live.background() and Backtest.background() execution.
797
+ * Events are processed sequentially in order received, even if callback is async.
798
+ * Uses queued wrapper to prevent concurrent execution of the callback.
799
+ *
800
+ * @param fn - Callback function to handle error events
801
+ * @returns Unsubscribe function to stop listening
802
+ *
803
+ * @example
804
+ * ```typescript
805
+ * import { listenError } from "./function/event";
806
+ *
807
+ * const unsubscribe = listenError((error) => {
808
+ * console.error("Background execution error:", error.message);
809
+ * // Log to monitoring service, send alerts, etc.
810
+ * });
811
+ *
812
+ * // Later: stop listening
813
+ * unsubscribe();
814
+ * ```
815
+ */
816
+ declare function listenError(fn: (error: Error) => void): () => void;
179
817
 
818
+ /**
819
+ * Fetches historical candle data from the registered exchange.
820
+ *
821
+ * Candles are fetched backwards from the current execution context time.
822
+ * Uses the exchange's getCandles implementation.
823
+ *
824
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
825
+ * @param interval - Candle interval ("1m" | "3m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "6h" | "8h")
826
+ * @param limit - Number of candles to fetch
827
+ * @returns Promise resolving to array of candle data
828
+ *
829
+ * @example
830
+ * ```typescript
831
+ * const candles = await getCandles("BTCUSDT", "1m", 100);
832
+ * console.log(candles[0]); // { timestamp, open, high, low, close, volume }
833
+ * ```
834
+ */
180
835
  declare function getCandles(symbol: string, interval: CandleInterval, limit: number): Promise<ICandleData[]>;
836
+ /**
837
+ * Calculates VWAP (Volume Weighted Average Price) for a symbol.
838
+ *
839
+ * Uses the last 5 1-minute candles to calculate:
840
+ * - Typical Price = (high + low + close) / 3
841
+ * - VWAP = sum(typical_price * volume) / sum(volume)
842
+ *
843
+ * If volume is zero, returns simple average of close prices.
844
+ *
845
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
846
+ * @returns Promise resolving to VWAP price
847
+ *
848
+ * @example
849
+ * ```typescript
850
+ * const vwap = await getAveragePrice("BTCUSDT");
851
+ * console.log(vwap); // 50125.43
852
+ * ```
853
+ */
181
854
  declare function getAveragePrice(symbol: string): Promise<number>;
855
+ /**
856
+ * Formats a price value according to exchange rules.
857
+ *
858
+ * Uses the exchange's formatPrice implementation for proper decimal places.
859
+ *
860
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
861
+ * @param price - Raw price value
862
+ * @returns Promise resolving to formatted price string
863
+ *
864
+ * @example
865
+ * ```typescript
866
+ * const formatted = await formatPrice("BTCUSDT", 50000.123456);
867
+ * console.log(formatted); // "50000.12"
868
+ * ```
869
+ */
182
870
  declare function formatPrice(symbol: string, price: number): Promise<string>;
871
+ /**
872
+ * Formats a quantity value according to exchange rules.
873
+ *
874
+ * Uses the exchange's formatQuantity implementation for proper decimal places.
875
+ *
876
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
877
+ * @param quantity - Raw quantity value
878
+ * @returns Promise resolving to formatted quantity string
879
+ *
880
+ * @example
881
+ * ```typescript
882
+ * const formatted = await formatQuantity("BTCUSDT", 0.123456789);
883
+ * console.log(formatted); // "0.12345678"
884
+ * ```
885
+ */
183
886
  declare function formatQuantity(symbol: string, quantity: number): Promise<string>;
887
+ /**
888
+ * Gets the current date from execution context.
889
+ *
890
+ * In backtest mode: returns the current timeframe date being processed
891
+ * In live mode: returns current real-time date
892
+ *
893
+ * @returns Promise resolving to current execution context date
894
+ *
895
+ * @example
896
+ * ```typescript
897
+ * const date = await getDate();
898
+ * console.log(date); // 2024-01-01T12:00:00.000Z
899
+ * ```
900
+ */
184
901
  declare function getDate(): Promise<Date>;
902
+ /**
903
+ * Gets the current execution mode.
904
+ *
905
+ * @returns Promise resolving to "backtest" or "live"
906
+ *
907
+ * @example
908
+ * ```typescript
909
+ * const mode = await getMode();
910
+ * if (mode === "backtest") {
911
+ * console.log("Running in backtest mode");
912
+ * } else {
913
+ * console.log("Running in live mode");
914
+ * }
915
+ * ```
916
+ */
185
917
  declare function getMode(): Promise<"backtest" | "live">;
186
918
 
187
- interface IMethodContext {
188
- exchangeName: ExchangeName;
189
- strategyName: StrategyName;
190
- frameName: FrameName;
191
- }
192
- declare const MethodContextService: (new () => {
193
- readonly context: IMethodContext;
194
- }) & Omit<{
195
- new (context: IMethodContext): {
196
- readonly context: IMethodContext;
197
- };
198
- }, "prototype"> & di_scoped.IScopedClassRun<[context: IMethodContext]>;
199
-
200
919
  declare const BASE_WAIT_FOR_INIT_SYMBOL: unique symbol;
920
+ /**
921
+ * Signal data stored in persistence layer.
922
+ * Contains nullable signal for atomic updates.
923
+ */
201
924
  interface ISignalData {
925
+ /** Current signal state (null when no active signal) */
202
926
  signalRow: ISignalRow | null;
203
927
  }
928
+ /**
929
+ * Type helper for PersistBase instance.
930
+ */
204
931
  type TPersistBase = InstanceType<typeof PersistBase>;
932
+ /**
933
+ * Constructor type for PersistBase.
934
+ * Used for custom persistence adapters.
935
+ */
205
936
  type TPersistBaseCtor<EntityName extends string = string, Entity extends IEntity = IEntity> = new (entityName: EntityName, baseDir: string) => IPersistBase<Entity>;
937
+ /**
938
+ * Entity identifier - string or number.
939
+ */
206
940
  type EntityId = string | number;
941
+ /**
942
+ * Base interface for persisted entities.
943
+ */
207
944
  interface IEntity {
208
945
  }
946
+ /**
947
+ * Persistence interface for CRUD operations.
948
+ * Implemented by PersistBase.
949
+ */
209
950
  interface IPersistBase<Entity extends IEntity = IEntity> {
951
+ /**
952
+ * Initialize persistence directory and validate existing files.
953
+ * Uses singleshot to ensure one-time execution.
954
+ *
955
+ * @param initial - Whether this is the first initialization
956
+ * @returns Promise that resolves when initialization is complete
957
+ */
210
958
  waitForInit(initial: boolean): Promise<void>;
959
+ /**
960
+ * Read entity from persistence storage.
961
+ *
962
+ * @param entityId - Unique entity identifier
963
+ * @returns Promise resolving to entity data
964
+ * @throws Error if entity not found or read fails
965
+ */
211
966
  readValue(entityId: EntityId): Promise<Entity>;
967
+ /**
968
+ * Check if entity exists in storage.
969
+ *
970
+ * @param entityId - Unique entity identifier
971
+ * @returns Promise resolving to true if exists, false otherwise
972
+ */
212
973
  hasValue(entityId: EntityId): Promise<boolean>;
974
+ /**
975
+ * Write entity to storage with atomic file writes.
976
+ *
977
+ * @param entityId - Unique entity identifier
978
+ * @param entity - Entity data to persist
979
+ * @returns Promise that resolves when write is complete
980
+ * @throws Error if write fails
981
+ */
213
982
  writeValue(entityId: EntityId, entity: Entity): Promise<void>;
214
983
  }
984
+ /**
985
+ * Base class for file-based persistence with atomic writes.
986
+ *
987
+ * Features:
988
+ * - Atomic file writes using writeFileAtomic
989
+ * - Auto-validation and cleanup of corrupted files
990
+ * - Async generator support for iteration
991
+ * - Retry logic for file deletion
992
+ *
993
+ * @example
994
+ * ```typescript
995
+ * const persist = new PersistBase("my-entity", "./data");
996
+ * await persist.waitForInit(true);
997
+ * await persist.writeValue("key1", { data: "value" });
998
+ * const value = await persist.readValue("key1");
999
+ * ```
1000
+ */
215
1001
  declare const PersistBase: {
216
1002
  new <EntityName extends string = string>(entityName: EntityName, baseDir?: string): {
1003
+ /** Computed directory path for entity storage */
217
1004
  _directory: string;
218
1005
  readonly entityName: EntityName;
219
1006
  readonly baseDir: string;
1007
+ /**
1008
+ * Computes file path for entity ID.
1009
+ *
1010
+ * @param entityId - Entity identifier
1011
+ * @returns Full file path to entity JSON file
1012
+ */
220
1013
  _getFilePath(entityId: EntityId): string;
221
1014
  waitForInit(initial: boolean): Promise<void>;
1015
+ /**
1016
+ * Returns count of persisted entities.
1017
+ *
1018
+ * @returns Promise resolving to number of .json files in directory
1019
+ */
222
1020
  getCount(): Promise<number>;
223
1021
  readValue<T extends IEntity = IEntity>(entityId: EntityId): Promise<T>;
224
1022
  hasValue(entityId: EntityId): Promise<boolean>;
225
1023
  writeValue<T extends IEntity = IEntity>(entityId: EntityId, entity: T): Promise<void>;
1024
+ /**
1025
+ * Removes entity from storage.
1026
+ *
1027
+ * @param entityId - Entity identifier to remove
1028
+ * @returns Promise that resolves when entity is deleted
1029
+ * @throws Error if entity not found or deletion fails
1030
+ */
226
1031
  removeValue(entityId: EntityId): Promise<void>;
1032
+ /**
1033
+ * Removes all entities from storage.
1034
+ *
1035
+ * @returns Promise that resolves when all entities are deleted
1036
+ * @throws Error if deletion fails
1037
+ */
227
1038
  removeAll(): Promise<void>;
1039
+ /**
1040
+ * Async generator yielding all entity values.
1041
+ * Sorted alphanumerically by entity ID.
1042
+ *
1043
+ * @returns AsyncGenerator yielding entities
1044
+ * @throws Error if reading fails
1045
+ */
228
1046
  values<T extends IEntity = IEntity>(): AsyncGenerator<T>;
1047
+ /**
1048
+ * Async generator yielding all entity IDs.
1049
+ * Sorted alphanumerically.
1050
+ *
1051
+ * @returns AsyncGenerator yielding entity IDs
1052
+ * @throws Error if reading fails
1053
+ */
229
1054
  keys(): AsyncGenerator<EntityId>;
1055
+ /**
1056
+ * Filters entities by predicate function.
1057
+ *
1058
+ * @param predicate - Filter function
1059
+ * @returns AsyncGenerator yielding filtered entities
1060
+ */
230
1061
  filter<T extends IEntity = IEntity>(predicate: (value: T) => boolean): AsyncGenerator<T>;
1062
+ /**
1063
+ * Takes first N entities, optionally filtered.
1064
+ *
1065
+ * @param total - Maximum number of entities to yield
1066
+ * @param predicate - Optional filter function
1067
+ * @returns AsyncGenerator yielding up to total entities
1068
+ */
231
1069
  take<T extends IEntity = IEntity>(total: number, predicate?: (value: T) => boolean): AsyncGenerator<T>;
232
1070
  [BASE_WAIT_FOR_INIT_SYMBOL]: (() => Promise<void>) & functools_kit.ISingleshotClearable;
1071
+ /**
1072
+ * Async iterator implementation.
1073
+ * Delegates to values() generator.
1074
+ *
1075
+ * @returns AsyncIterableIterator yielding entities
1076
+ */
233
1077
  [Symbol.asyncIterator](): AsyncIterableIterator<any>;
234
1078
  };
235
1079
  };
1080
+ /**
1081
+ * Utility class for managing signal persistence.
1082
+ *
1083
+ * Features:
1084
+ * - Memoized storage instances per strategy
1085
+ * - Custom adapter support
1086
+ * - Atomic read/write operations
1087
+ * - Crash-safe signal state management
1088
+ *
1089
+ * Used by ClientStrategy for live mode persistence.
1090
+ */
236
1091
  declare class PersistSignalUtils {
237
1092
  private PersistSignalFactory;
238
1093
  private getSignalStorage;
1094
+ /**
1095
+ * Registers a custom persistence adapter.
1096
+ *
1097
+ * @param Ctor - Custom PersistBase constructor
1098
+ *
1099
+ * @example
1100
+ * ```typescript
1101
+ * class RedisPersist extends PersistBase {
1102
+ * async readValue(id) { return JSON.parse(await redis.get(id)); }
1103
+ * async writeValue(id, entity) { await redis.set(id, JSON.stringify(entity)); }
1104
+ * }
1105
+ * PersistSignalAdaper.usePersistSignalAdapter(RedisPersist);
1106
+ * ```
1107
+ */
239
1108
  usePersistSignalAdapter(Ctor: TPersistBaseCtor<StrategyName, ISignalData>): void;
1109
+ /**
1110
+ * Reads persisted signal data for a strategy and symbol.
1111
+ *
1112
+ * Called by ClientStrategy.waitForInit() to restore state.
1113
+ * Returns null if no signal exists.
1114
+ *
1115
+ * @param strategyName - Strategy identifier
1116
+ * @param symbol - Trading pair symbol
1117
+ * @returns Promise resolving to signal or null
1118
+ */
240
1119
  readSignalData: (strategyName: StrategyName, symbol: string) => Promise<ISignalRow | null>;
1120
+ /**
1121
+ * Writes signal data to disk with atomic file writes.
1122
+ *
1123
+ * Called by ClientStrategy.setPendingSignal() to persist state.
1124
+ * Uses atomic writes to prevent corruption on crashes.
1125
+ *
1126
+ * @param signalRow - Signal data (null to clear)
1127
+ * @param strategyName - Strategy identifier
1128
+ * @param symbol - Trading pair symbol
1129
+ * @returns Promise that resolves when write is complete
1130
+ */
241
1131
  writeSignalData: (signalRow: ISignalRow | null, strategyName: StrategyName, symbol: string) => Promise<void>;
242
1132
  }
1133
+ /**
1134
+ * Global singleton instance of PersistSignalUtils.
1135
+ * Used by ClientStrategy for signal persistence.
1136
+ *
1137
+ * @example
1138
+ * ```typescript
1139
+ * // Custom adapter
1140
+ * PersistSignalAdaper.usePersistSignalAdapter(RedisPersist);
1141
+ *
1142
+ * // Read signal
1143
+ * const signal = await PersistSignalAdaper.readSignalData("my-strategy", "BTCUSDT");
1144
+ *
1145
+ * // Write signal
1146
+ * await PersistSignalAdaper.writeSignalData(signal, "my-strategy", "BTCUSDT");
1147
+ * ```
1148
+ */
243
1149
  declare const PersistSignalAdaper: PersistSignalUtils;
244
1150
 
1151
+ /**
1152
+ * Utility class for backtest operations.
1153
+ *
1154
+ * Provides simplified access to backtestGlobalService.run() with logging.
1155
+ * Exported as singleton instance for convenient usage.
1156
+ *
1157
+ * @example
1158
+ * ```typescript
1159
+ * import { Backtest } from "./classes/Backtest";
1160
+ *
1161
+ * for await (const result of Backtest.run("BTCUSDT", {
1162
+ * strategyName: "my-strategy",
1163
+ * exchangeName: "my-exchange",
1164
+ * frameName: "1d-backtest"
1165
+ * })) {
1166
+ * console.log("Closed signal PNL:", result.pnl.pnlPercentage);
1167
+ * }
1168
+ * ```
1169
+ */
245
1170
  declare class BacktestUtils {
1171
+ /**
1172
+ * Runs backtest for a symbol with context propagation.
1173
+ *
1174
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1175
+ * @param context - Execution context with strategy, exchange, and frame names
1176
+ * @returns Async generator yielding closed signals with PNL
1177
+ */
246
1178
  run: (symbol: string, context: {
247
1179
  strategyName: string;
248
1180
  exchangeName: string;
249
1181
  frameName: string;
250
1182
  }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
1183
+ /**
1184
+ * Runs backtest in background without yielding results.
1185
+ *
1186
+ * Consumes all backtest results internally without exposing them.
1187
+ * Useful for running backtests for side effects only (callbacks, logging).
1188
+ *
1189
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1190
+ * @param context - Execution context with strategy, exchange, and frame names
1191
+ * @returns Cancellation closure
1192
+ *
1193
+ * @example
1194
+ * ```typescript
1195
+ * // Run backtest silently, only callbacks will fire
1196
+ * await Backtest.background("BTCUSDT", {
1197
+ * strategyName: "my-strategy",
1198
+ * exchangeName: "my-exchange",
1199
+ * frameName: "1d-backtest"
1200
+ * });
1201
+ * console.log("Backtest completed");
1202
+ * ```
1203
+ */
1204
+ background: (symbol: string, context: {
1205
+ strategyName: string;
1206
+ exchangeName: string;
1207
+ frameName: string;
1208
+ }) => Promise<() => void>;
1209
+ /**
1210
+ * Generates markdown report with all closed signals for a strategy.
1211
+ *
1212
+ * @param strategyName - Strategy name to generate report for
1213
+ * @returns Promise resolving to markdown formatted report string
1214
+ *
1215
+ * @example
1216
+ * ```typescript
1217
+ * const markdown = await Backtest.getReport("my-strategy");
1218
+ * console.log(markdown);
1219
+ * ```
1220
+ */
1221
+ getReport: (strategyName: StrategyName) => Promise<string>;
1222
+ /**
1223
+ * Saves strategy report to disk.
1224
+ *
1225
+ * @param strategyName - Strategy name to save report for
1226
+ * @param path - Optional directory path to save report (default: "./logs/backtest")
1227
+ *
1228
+ * @example
1229
+ * ```typescript
1230
+ * // Save to default path: ./logs/backtest/my-strategy.md
1231
+ * await Backtest.dump("my-strategy");
1232
+ *
1233
+ * // Save to custom path: ./custom/path/my-strategy.md
1234
+ * await Backtest.dump("my-strategy", "./custom/path");
1235
+ * ```
1236
+ */
1237
+ dump: (strategyName: StrategyName, path?: string) => Promise<void>;
251
1238
  }
1239
+ /**
1240
+ * Singleton instance of BacktestUtils for convenient backtest operations.
1241
+ *
1242
+ * @example
1243
+ * ```typescript
1244
+ * import { Backtest } from "./classes/Backtest";
1245
+ *
1246
+ * for await (const result of Backtest.run("BTCUSDT", {
1247
+ * strategyName: "my-strategy",
1248
+ * exchangeName: "my-exchange",
1249
+ * frameName: "1d-backtest"
1250
+ * })) {
1251
+ * if (result.action === "closed") {
1252
+ * console.log("PNL:", result.pnl.pnlPercentage);
1253
+ * }
1254
+ * }
1255
+ * ```
1256
+ */
252
1257
  declare const Backtest: BacktestUtils;
253
1258
 
1259
+ /**
1260
+ * Utility class for live trading operations.
1261
+ *
1262
+ * Provides simplified access to liveGlobalService.run() with logging.
1263
+ * Exported as singleton instance for convenient usage.
1264
+ *
1265
+ * Features:
1266
+ * - Infinite async generator (never completes)
1267
+ * - Crash recovery via persisted state
1268
+ * - Real-time progression with Date.now()
1269
+ *
1270
+ * @example
1271
+ * ```typescript
1272
+ * import { Live } from "./classes/Live";
1273
+ *
1274
+ * // Infinite loop - use Ctrl+C to stop
1275
+ * for await (const result of Live.run("BTCUSDT", {
1276
+ * strategyName: "my-strategy",
1277
+ * exchangeName: "my-exchange",
1278
+ * frameName: ""
1279
+ * })) {
1280
+ * if (result.action === "opened") {
1281
+ * console.log("Signal opened:", result.signal);
1282
+ * } else if (result.action === "closed") {
1283
+ * console.log("PNL:", result.pnl.pnlPercentage);
1284
+ * }
1285
+ * }
1286
+ * ```
1287
+ */
254
1288
  declare class LiveUtils {
1289
+ /**
1290
+ * Runs live trading for a symbol with context propagation.
1291
+ *
1292
+ * Infinite async generator with crash recovery support.
1293
+ * Process can crash and restart - state will be recovered from disk.
1294
+ *
1295
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1296
+ * @param context - Execution context with strategy and exchange names
1297
+ * @returns Infinite async generator yielding opened and closed signals
1298
+ */
255
1299
  run: (symbol: string, context: {
256
1300
  strategyName: string;
257
1301
  exchangeName: string;
258
- frameName: string;
259
1302
  }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
1303
+ /**
1304
+ * Runs live trading in background without yielding results.
1305
+ *
1306
+ * Consumes all live trading results internally without exposing them.
1307
+ * Infinite loop - will run until process is stopped or crashes.
1308
+ * Useful for running live trading for side effects only (callbacks, persistence).
1309
+ *
1310
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1311
+ * @param context - Execution context with strategy and exchange names
1312
+ * @returns Cancellation closure
1313
+ *
1314
+ * @example
1315
+ * ```typescript
1316
+ * // Run live trading silently in background, only callbacks will fire
1317
+ * // This will run forever until Ctrl+C
1318
+ * await Live.background("BTCUSDT", {
1319
+ * strategyName: "my-strategy",
1320
+ * exchangeName: "my-exchange"
1321
+ * });
1322
+ * ```
1323
+ */
1324
+ background: (symbol: string, context: {
1325
+ strategyName: string;
1326
+ exchangeName: string;
1327
+ }) => Promise<() => void>;
1328
+ /**
1329
+ * Generates markdown report with all events for a strategy.
1330
+ *
1331
+ * @param strategyName - Strategy name to generate report for
1332
+ * @returns Promise resolving to markdown formatted report string
1333
+ *
1334
+ * @example
1335
+ * ```typescript
1336
+ * const markdown = await Live.getReport("my-strategy");
1337
+ * console.log(markdown);
1338
+ * ```
1339
+ */
1340
+ getReport: (strategyName: StrategyName) => Promise<string>;
1341
+ /**
1342
+ * Saves strategy report to disk.
1343
+ *
1344
+ * @param strategyName - Strategy name to save report for
1345
+ * @param path - Optional directory path to save report (default: "./logs/live")
1346
+ *
1347
+ * @example
1348
+ * ```typescript
1349
+ * // Save to default path: ./logs/live/my-strategy.md
1350
+ * await Live.dump("my-strategy");
1351
+ *
1352
+ * // Save to custom path: ./custom/path/my-strategy.md
1353
+ * await Live.dump("my-strategy", "./custom/path");
1354
+ * ```
1355
+ */
1356
+ dump: (strategyName: StrategyName, path?: string) => Promise<void>;
260
1357
  }
1358
+ /**
1359
+ * Singleton instance of LiveUtils for convenient live trading operations.
1360
+ *
1361
+ * @example
1362
+ * ```typescript
1363
+ * import { Live } from "./classes/Live";
1364
+ *
1365
+ * for await (const result of Live.run("BTCUSDT", {
1366
+ * strategyName: "my-strategy",
1367
+ * exchangeName: "my-exchange",
1368
+ * })) {
1369
+ * console.log("Result:", result.action);
1370
+ * }
1371
+ * ```
1372
+ */
261
1373
  declare const Live: LiveUtils;
262
1374
 
1375
+ /**
1376
+ * Logger service with automatic context injection.
1377
+ *
1378
+ * Features:
1379
+ * - Delegates to user-provided logger via setLogger()
1380
+ * - Automatically appends method context (strategyName, exchangeName, frameName)
1381
+ * - Automatically appends execution context (symbol, when, backtest)
1382
+ * - Defaults to NOOP_LOGGER if no logger configured
1383
+ *
1384
+ * Used throughout the framework for consistent logging with context.
1385
+ */
263
1386
  declare class LoggerService implements ILogger {
264
1387
  private readonly methodContextService;
265
1388
  private readonly executionContextService;
266
1389
  private _commonLogger;
1390
+ /**
1391
+ * Gets current method context if available.
1392
+ * Contains strategyName, exchangeName, frameName from MethodContextService.
1393
+ */
267
1394
  private get methodContext();
1395
+ /**
1396
+ * Gets current execution context if available.
1397
+ * Contains symbol, when, backtest from ExecutionContextService.
1398
+ */
268
1399
  private get executionContext();
1400
+ /**
1401
+ * Logs general-purpose message with automatic context injection.
1402
+ *
1403
+ * @param topic - Log topic/category
1404
+ * @param args - Additional log arguments
1405
+ */
269
1406
  log: (topic: string, ...args: any[]) => Promise<void>;
1407
+ /**
1408
+ * Logs debug-level message with automatic context injection.
1409
+ *
1410
+ * @param topic - Log topic/category
1411
+ * @param args - Additional log arguments
1412
+ */
270
1413
  debug: (topic: string, ...args: any[]) => Promise<void>;
1414
+ /**
1415
+ * Logs info-level message with automatic context injection.
1416
+ *
1417
+ * @param topic - Log topic/category
1418
+ * @param args - Additional log arguments
1419
+ */
271
1420
  info: (topic: string, ...args: any[]) => Promise<void>;
1421
+ /**
1422
+ * Logs warning-level message with automatic context injection.
1423
+ *
1424
+ * @param topic - Log topic/category
1425
+ * @param args - Additional log arguments
1426
+ */
1427
+ warn: (topic: string, ...args: any[]) => Promise<void>;
1428
+ /**
1429
+ * Sets custom logger implementation.
1430
+ *
1431
+ * @param logger - Custom logger implementing ILogger interface
1432
+ */
272
1433
  setLogger: (logger: ILogger) => void;
273
1434
  }
274
1435
 
1436
+ /**
1437
+ * Client implementation for exchange data access.
1438
+ *
1439
+ * Features:
1440
+ * - Historical candle fetching (backwards from execution context)
1441
+ * - Future candle fetching (forwards for backtest)
1442
+ * - VWAP calculation from last 5 1m candles
1443
+ * - Price/quantity formatting for exchange
1444
+ *
1445
+ * All methods use prototype functions for memory efficiency.
1446
+ *
1447
+ * @example
1448
+ * ```typescript
1449
+ * const exchange = new ClientExchange({
1450
+ * exchangeName: "binance",
1451
+ * getCandles: async (symbol, interval, since, limit) => [...],
1452
+ * formatPrice: async (symbol, price) => price.toFixed(2),
1453
+ * formatQuantity: async (symbol, quantity) => quantity.toFixed(8),
1454
+ * execution: executionService,
1455
+ * logger: loggerService,
1456
+ * });
1457
+ *
1458
+ * const candles = await exchange.getCandles("BTCUSDT", "1m", 100);
1459
+ * const vwap = await exchange.getAveragePrice("BTCUSDT");
1460
+ * ```
1461
+ */
275
1462
  declare class ClientExchange implements IExchange {
276
1463
  readonly params: IExchangeParams;
277
1464
  constructor(params: IExchangeParams);
1465
+ /**
1466
+ * Fetches historical candles backwards from execution context time.
1467
+ *
1468
+ * @param symbol - Trading pair symbol
1469
+ * @param interval - Candle interval
1470
+ * @param limit - Number of candles to fetch
1471
+ * @returns Promise resolving to array of candles
1472
+ */
278
1473
  getCandles(symbol: string, interval: CandleInterval, limit: number): Promise<ICandleData[]>;
1474
+ /**
1475
+ * Fetches future candles forwards from execution context time.
1476
+ * Used in backtest mode to get candles for signal duration.
1477
+ *
1478
+ * @param symbol - Trading pair symbol
1479
+ * @param interval - Candle interval
1480
+ * @param limit - Number of candles to fetch
1481
+ * @returns Promise resolving to array of candles
1482
+ * @throws Error if trying to fetch future candles in live mode
1483
+ */
279
1484
  getNextCandles(symbol: string, interval: CandleInterval, limit: number): Promise<ICandleData[]>;
1485
+ /**
1486
+ * Calculates VWAP (Volume Weighted Average Price) from last 5 1m candles.
1487
+ *
1488
+ * Formula:
1489
+ * - Typical Price = (high + low + close) / 3
1490
+ * - VWAP = sum(typical_price * volume) / sum(volume)
1491
+ *
1492
+ * If volume is zero, returns simple average of close prices.
1493
+ *
1494
+ * @param symbol - Trading pair symbol
1495
+ * @returns Promise resolving to VWAP price
1496
+ * @throws Error if no candles available
1497
+ */
280
1498
  getAveragePrice(symbol: string): Promise<number>;
281
1499
  formatQuantity(symbol: string, quantity: number): Promise<string>;
282
1500
  formatPrice(symbol: string, price: number): Promise<string>;
283
1501
  }
284
1502
 
1503
+ /**
1504
+ * Connection service routing exchange operations to correct ClientExchange instance.
1505
+ *
1506
+ * Routes all IExchange method calls to the appropriate exchange implementation
1507
+ * based on methodContextService.context.exchangeName. Uses memoization to cache
1508
+ * ClientExchange instances for performance.
1509
+ *
1510
+ * Key features:
1511
+ * - Automatic exchange routing via method context
1512
+ * - Memoized ClientExchange instances by exchangeName
1513
+ * - Implements full IExchange interface
1514
+ * - Logging for all operations
1515
+ *
1516
+ * @example
1517
+ * ```typescript
1518
+ * // Used internally by framework
1519
+ * const candles = await exchangeConnectionService.getCandles(
1520
+ * "BTCUSDT", "1h", 100
1521
+ * );
1522
+ * // Automatically routes to correct exchange based on methodContext
1523
+ * ```
1524
+ */
285
1525
  declare class ExchangeConnectionService implements IExchange {
286
1526
  private readonly loggerService;
287
1527
  private readonly executionContextService;
288
1528
  private readonly exchangeSchemaService;
289
1529
  private readonly methodContextService;
1530
+ /**
1531
+ * Retrieves memoized ClientExchange instance for given exchange name.
1532
+ *
1533
+ * Creates ClientExchange on first call, returns cached instance on subsequent calls.
1534
+ * Cache key is exchangeName string.
1535
+ *
1536
+ * @param exchangeName - Name of registered exchange schema
1537
+ * @returns Configured ClientExchange instance
1538
+ */
290
1539
  getExchange: ((exchangeName: ExchangeName) => ClientExchange) & functools_kit.IClearableMemoize<string> & functools_kit.IControlMemoize<string, ClientExchange>;
1540
+ /**
1541
+ * Fetches historical candles for symbol using configured exchange.
1542
+ *
1543
+ * Routes to exchange determined by methodContextService.context.exchangeName.
1544
+ *
1545
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1546
+ * @param interval - Candle interval (e.g., "1h", "1d")
1547
+ * @param limit - Maximum number of candles to fetch
1548
+ * @returns Promise resolving to array of candle data
1549
+ */
291
1550
  getCandles: (symbol: string, interval: CandleInterval, limit: number) => Promise<ICandleData[]>;
1551
+ /**
1552
+ * Fetches next batch of candles relative to executionContext.when.
1553
+ *
1554
+ * Returns candles that come after the current execution timestamp.
1555
+ * Used for backtest progression and live trading updates.
1556
+ *
1557
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1558
+ * @param interval - Candle interval (e.g., "1h", "1d")
1559
+ * @param limit - Maximum number of candles to fetch
1560
+ * @returns Promise resolving to array of candle data
1561
+ */
292
1562
  getNextCandles: (symbol: string, interval: CandleInterval, limit: number) => Promise<ICandleData[]>;
1563
+ /**
1564
+ * Retrieves current average price for symbol.
1565
+ *
1566
+ * In live mode: fetches real-time average price from exchange API.
1567
+ * In backtest mode: calculates VWAP from candles in current timeframe.
1568
+ *
1569
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1570
+ * @returns Promise resolving to average price
1571
+ */
293
1572
  getAveragePrice: (symbol: string) => Promise<number>;
1573
+ /**
1574
+ * Formats price according to exchange-specific precision rules.
1575
+ *
1576
+ * Ensures price meets exchange requirements for decimal places and tick size.
1577
+ *
1578
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1579
+ * @param price - Raw price value to format
1580
+ * @returns Promise resolving to formatted price string
1581
+ */
294
1582
  formatPrice: (symbol: string, price: number) => Promise<string>;
1583
+ /**
1584
+ * Formats quantity according to exchange-specific precision rules.
1585
+ *
1586
+ * Ensures quantity meets exchange requirements for decimal places and lot size.
1587
+ *
1588
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1589
+ * @param quantity - Raw quantity value to format
1590
+ * @returns Promise resolving to formatted quantity string
1591
+ */
295
1592
  formatQuantity: (symbol: string, quantity: number) => Promise<string>;
296
1593
  }
297
1594
 
1595
+ /**
1596
+ * Connection service routing strategy operations to correct ClientStrategy instance.
1597
+ *
1598
+ * Routes all IStrategy method calls to the appropriate strategy implementation
1599
+ * based on methodContextService.context.strategyName. Uses memoization to cache
1600
+ * ClientStrategy instances for performance.
1601
+ *
1602
+ * Key features:
1603
+ * - Automatic strategy routing via method context
1604
+ * - Memoized ClientStrategy instances by strategyName
1605
+ * - Implements IStrategy interface
1606
+ * - Ensures initialization with waitForInit() before operations
1607
+ * - Handles both tick() (live) and backtest() operations
1608
+ *
1609
+ * @example
1610
+ * ```typescript
1611
+ * // Used internally by framework
1612
+ * const result = await strategyConnectionService.tick();
1613
+ * // Automatically routes to correct strategy based on methodContext
1614
+ * ```
1615
+ */
298
1616
  declare class StrategyConnectionService implements IStrategy {
299
1617
  private readonly loggerService;
300
1618
  private readonly executionContextService;
301
1619
  private readonly strategySchemaService;
302
1620
  private readonly exchangeConnectionService;
303
1621
  private readonly methodContextService;
1622
+ /**
1623
+ * Retrieves memoized ClientStrategy instance for given strategy name.
1624
+ *
1625
+ * Creates ClientStrategy on first call, returns cached instance on subsequent calls.
1626
+ * Cache key is strategyName string.
1627
+ *
1628
+ * @param strategyName - Name of registered strategy schema
1629
+ * @returns Configured ClientStrategy instance
1630
+ */
304
1631
  private getStrategy;
1632
+ /**
1633
+ * Executes live trading tick for current strategy.
1634
+ *
1635
+ * Waits for strategy initialization before processing tick.
1636
+ * Evaluates current market conditions and returns signal state.
1637
+ *
1638
+ * @returns Promise resolving to tick result (idle, opened, active, closed)
1639
+ */
305
1640
  tick: () => Promise<IStrategyTickResult>;
1641
+ /**
1642
+ * Executes backtest for current strategy with provided candles.
1643
+ *
1644
+ * Waits for strategy initialization before processing candles.
1645
+ * Evaluates strategy signals against historical data.
1646
+ *
1647
+ * @param candles - Array of historical candle data to backtest
1648
+ * @returns Promise resolving to backtest result (signal or idle)
1649
+ */
306
1650
  backtest: (candles: ICandleData[]) => Promise<IStrategyBacktestResult>;
307
1651
  }
308
1652
 
1653
+ /**
1654
+ * Client implementation for backtest timeframe generation.
1655
+ *
1656
+ * Features:
1657
+ * - Generates timestamp arrays for backtest iteration
1658
+ * - Singleshot caching prevents redundant generation
1659
+ * - Configurable interval spacing (1m to 3d)
1660
+ * - Callback support for validation and logging
1661
+ *
1662
+ * Used by BacktestLogicPrivateService to iterate through historical periods.
1663
+ */
309
1664
  declare class ClientFrame implements IFrame {
310
1665
  readonly params: IFrameParams;
311
1666
  constructor(params: IFrameParams);
1667
+ /**
1668
+ * Generates timeframe array for backtest period.
1669
+ * Results are cached via singleshot pattern.
1670
+ *
1671
+ * @param symbol - Trading pair symbol (unused, for API consistency)
1672
+ * @returns Promise resolving to array of Date objects
1673
+ * @throws Error if interval is invalid
1674
+ */
312
1675
  getTimeframe: ((symbol: string) => Promise<Date[]>) & functools_kit.ISingleshotClearable;
313
1676
  }
314
1677
 
1678
+ /**
1679
+ * Connection service routing frame operations to correct ClientFrame instance.
1680
+ *
1681
+ * Routes all IFrame method calls to the appropriate frame implementation
1682
+ * based on methodContextService.context.frameName. Uses memoization to cache
1683
+ * ClientFrame instances for performance.
1684
+ *
1685
+ * Key features:
1686
+ * - Automatic frame routing via method context
1687
+ * - Memoized ClientFrame instances by frameName
1688
+ * - Implements IFrame interface
1689
+ * - Backtest timeframe management (startDate, endDate, interval)
1690
+ *
1691
+ * Note: frameName is empty string for live mode (no frame constraints).
1692
+ *
1693
+ * @example
1694
+ * ```typescript
1695
+ * // Used internally by framework
1696
+ * const timeframe = await frameConnectionService.getTimeframe("BTCUSDT");
1697
+ * // Automatically routes to correct frame based on methodContext
1698
+ * ```
1699
+ */
315
1700
  declare class FrameConnectionService implements IFrame {
316
1701
  private readonly loggerService;
317
1702
  private readonly frameSchemaService;
318
1703
  private readonly methodContextService;
1704
+ /**
1705
+ * Retrieves memoized ClientFrame instance for given frame name.
1706
+ *
1707
+ * Creates ClientFrame on first call, returns cached instance on subsequent calls.
1708
+ * Cache key is frameName string.
1709
+ *
1710
+ * @param frameName - Name of registered frame schema
1711
+ * @returns Configured ClientFrame instance
1712
+ */
319
1713
  getFrame: ((frameName: FrameName) => ClientFrame) & functools_kit.IClearableMemoize<string> & functools_kit.IControlMemoize<string, ClientFrame>;
1714
+ /**
1715
+ * Retrieves backtest timeframe boundaries for symbol.
1716
+ *
1717
+ * Returns startDate and endDate from frame configuration.
1718
+ * Used to limit backtest execution to specific date range.
1719
+ *
1720
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
1721
+ * @returns Promise resolving to { startDate: Date, endDate: Date }
1722
+ */
320
1723
  getTimeframe: (symbol: string) => Promise<Date[]>;
321
1724
  }
322
1725
 
1726
+ /**
1727
+ * Global service for exchange operations with execution context injection.
1728
+ *
1729
+ * Wraps ExchangeConnectionService with ExecutionContextService to inject
1730
+ * symbol, when, and backtest parameters into the execution context.
1731
+ *
1732
+ * Used internally by BacktestLogicPrivateService and LiveLogicPrivateService.
1733
+ */
323
1734
  declare class ExchangeGlobalService {
324
1735
  private readonly loggerService;
325
1736
  private readonly exchangeConnectionService;
1737
+ /**
1738
+ * Fetches historical candles with execution context.
1739
+ *
1740
+ * @param symbol - Trading pair symbol
1741
+ * @param interval - Candle interval (e.g., "1m", "1h")
1742
+ * @param limit - Maximum number of candles to fetch
1743
+ * @param when - Timestamp for context (used in backtest mode)
1744
+ * @param backtest - Whether running in backtest mode
1745
+ * @returns Promise resolving to array of candles
1746
+ */
326
1747
  getCandles: (symbol: string, interval: CandleInterval, limit: number, when: Date, backtest: boolean) => Promise<ICandleData[]>;
1748
+ /**
1749
+ * Fetches future candles (backtest mode only) with execution context.
1750
+ *
1751
+ * @param symbol - Trading pair symbol
1752
+ * @param interval - Candle interval
1753
+ * @param limit - Maximum number of candles to fetch
1754
+ * @param when - Timestamp for context
1755
+ * @param backtest - Whether running in backtest mode (must be true)
1756
+ * @returns Promise resolving to array of future candles
1757
+ */
327
1758
  getNextCandles: (symbol: string, interval: CandleInterval, limit: number, when: Date, backtest: boolean) => Promise<ICandleData[]>;
1759
+ /**
1760
+ * Calculates VWAP with execution context.
1761
+ *
1762
+ * @param symbol - Trading pair symbol
1763
+ * @param when - Timestamp for context
1764
+ * @param backtest - Whether running in backtest mode
1765
+ * @returns Promise resolving to VWAP price
1766
+ */
328
1767
  getAveragePrice: (symbol: string, when: Date, backtest: boolean) => Promise<number>;
1768
+ /**
1769
+ * Formats price with execution context.
1770
+ *
1771
+ * @param symbol - Trading pair symbol
1772
+ * @param price - Price to format
1773
+ * @param when - Timestamp for context
1774
+ * @param backtest - Whether running in backtest mode
1775
+ * @returns Promise resolving to formatted price string
1776
+ */
329
1777
  formatPrice: (symbol: string, price: number, when: Date, backtest: boolean) => Promise<string>;
1778
+ /**
1779
+ * Formats quantity with execution context.
1780
+ *
1781
+ * @param symbol - Trading pair symbol
1782
+ * @param quantity - Quantity to format
1783
+ * @param when - Timestamp for context
1784
+ * @param backtest - Whether running in backtest mode
1785
+ * @returns Promise resolving to formatted quantity string
1786
+ */
330
1787
  formatQuantity: (symbol: string, quantity: number, when: Date, backtest: boolean) => Promise<string>;
331
1788
  }
332
1789
 
1790
+ /**
1791
+ * Global service for strategy operations with execution context injection.
1792
+ *
1793
+ * Wraps StrategyConnectionService with ExecutionContextService to inject
1794
+ * symbol, when, and backtest parameters into the execution context.
1795
+ *
1796
+ * Used internally by BacktestLogicPrivateService and LiveLogicPrivateService.
1797
+ */
333
1798
  declare class StrategyGlobalService {
334
1799
  private readonly loggerService;
335
1800
  private readonly strategyConnectionService;
1801
+ /**
1802
+ * Checks signal status at a specific timestamp.
1803
+ *
1804
+ * Wraps strategy tick() with execution context containing symbol, timestamp,
1805
+ * and backtest mode flag.
1806
+ *
1807
+ * @param symbol - Trading pair symbol
1808
+ * @param when - Timestamp for tick evaluation
1809
+ * @param backtest - Whether running in backtest mode
1810
+ * @returns Discriminated union of tick result (idle, opened, active, closed)
1811
+ */
336
1812
  tick: (symbol: string, when: Date, backtest: boolean) => Promise<IStrategyTickResult>;
1813
+ /**
1814
+ * Runs fast backtest against candle array.
1815
+ *
1816
+ * Wraps strategy backtest() with execution context containing symbol,
1817
+ * timestamp, and backtest mode flag.
1818
+ *
1819
+ * @param symbol - Trading pair symbol
1820
+ * @param candles - Array of historical candles to test against
1821
+ * @param when - Starting timestamp for backtest
1822
+ * @param backtest - Whether running in backtest mode (typically true)
1823
+ * @returns Closed signal result with PNL
1824
+ */
337
1825
  backtest: (symbol: string, candles: ICandleData[], when: Date, backtest: boolean) => Promise<IStrategyBacktestResult>;
338
1826
  }
339
1827
 
1828
+ /**
1829
+ * Global service for frame operations.
1830
+ *
1831
+ * Wraps FrameConnectionService for timeframe generation.
1832
+ * Used internally by BacktestLogicPrivateService.
1833
+ */
340
1834
  declare class FrameGlobalService {
341
1835
  private readonly loggerService;
342
1836
  private readonly frameConnectionService;
1837
+ /**
1838
+ * Generates timeframe array for backtest iteration.
1839
+ *
1840
+ * @param symbol - Trading pair symbol
1841
+ * @returns Promise resolving to array of Date objects
1842
+ */
343
1843
  getTimeframe: (symbol: string) => Promise<Date[]>;
344
1844
  }
345
1845
 
1846
+ /**
1847
+ * Service for managing exchange schema registry.
1848
+ *
1849
+ * Uses ToolRegistry from functools-kit for type-safe schema storage.
1850
+ * Exchanges are registered via addExchange() and retrieved by name.
1851
+ */
346
1852
  declare class ExchangeSchemaService {
347
1853
  readonly loggerService: LoggerService;
348
1854
  private _registry;
1855
+ /**
1856
+ * Registers a new exchange schema.
1857
+ *
1858
+ * @param key - Unique exchange name
1859
+ * @param value - Exchange schema configuration
1860
+ * @throws Error if exchange name already exists
1861
+ */
349
1862
  register: (key: ExchangeName, value: IExchangeSchema) => void;
1863
+ /**
1864
+ * Validates exchange schema structure for required properties.
1865
+ *
1866
+ * Performs shallow validation to ensure all required properties exist
1867
+ * and have correct types before registration in the registry.
1868
+ *
1869
+ * @param exchangeSchema - Exchange schema to validate
1870
+ * @throws Error if exchangeName is missing or not a string
1871
+ * @throws Error if getCandles is missing or not a function
1872
+ * @throws Error if formatPrice is missing or not a function
1873
+ * @throws Error if formatQuantity is missing or not a function
1874
+ */
1875
+ private validateShallow;
1876
+ /**
1877
+ * Overrides an existing exchange schema with partial updates.
1878
+ *
1879
+ * @param key - Exchange name to override
1880
+ * @param value - Partial schema updates
1881
+ * @returns Updated exchange schema
1882
+ * @throws Error if exchange name doesn't exist
1883
+ */
350
1884
  override: (key: ExchangeName, value: Partial<IExchangeSchema>) => IExchangeSchema;
1885
+ /**
1886
+ * Retrieves an exchange schema by name.
1887
+ *
1888
+ * @param key - Exchange name
1889
+ * @returns Exchange schema configuration
1890
+ * @throws Error if exchange name doesn't exist
1891
+ */
351
1892
  get: (key: ExchangeName) => IExchangeSchema;
352
1893
  }
353
1894
 
1895
+ /**
1896
+ * Service for managing strategy schema registry.
1897
+ *
1898
+ * Uses ToolRegistry from functools-kit for type-safe schema storage.
1899
+ * Strategies are registered via addStrategy() and retrieved by name.
1900
+ */
354
1901
  declare class StrategySchemaService {
355
1902
  readonly loggerService: LoggerService;
356
1903
  private _registry;
1904
+ /**
1905
+ * Registers a new strategy schema.
1906
+ *
1907
+ * @param key - Unique strategy name
1908
+ * @param value - Strategy schema configuration
1909
+ * @throws Error if strategy name already exists
1910
+ */
357
1911
  register: (key: StrategyName, value: IStrategySchema) => void;
1912
+ /**
1913
+ * Validates strategy schema structure for required properties.
1914
+ *
1915
+ * Performs shallow validation to ensure all required properties exist
1916
+ * and have correct types before registration in the registry.
1917
+ *
1918
+ * @param strategySchema - Strategy schema to validate
1919
+ * @throws Error if strategyName is missing or not a string
1920
+ * @throws Error if interval is missing or not a valid SignalInterval
1921
+ * @throws Error if getSignal is missing or not a function
1922
+ */
1923
+ private validateShallow;
1924
+ /**
1925
+ * Overrides an existing strategy schema with partial updates.
1926
+ *
1927
+ * @param key - Strategy name to override
1928
+ * @param value - Partial schema updates
1929
+ * @returns Updated strategy schema
1930
+ * @throws Error if strategy name doesn't exist
1931
+ */
358
1932
  override: (key: StrategyName, value: Partial<IStrategySchema>) => IStrategySchema;
1933
+ /**
1934
+ * Retrieves a strategy schema by name.
1935
+ *
1936
+ * @param key - Strategy name
1937
+ * @returns Strategy schema configuration
1938
+ * @throws Error if strategy name doesn't exist
1939
+ */
359
1940
  get: (key: StrategyName) => IStrategySchema;
360
1941
  }
361
1942
 
1943
+ /**
1944
+ * Service for managing frame schema registry.
1945
+ *
1946
+ * Uses ToolRegistry from functools-kit for type-safe schema storage.
1947
+ * Frames are registered via addFrame() and retrieved by name.
1948
+ */
362
1949
  declare class FrameSchemaService {
1950
+ readonly loggerService: LoggerService;
363
1951
  private _registry;
1952
+ /**
1953
+ * Registers a new frame schema.
1954
+ *
1955
+ * @param key - Unique frame name
1956
+ * @param value - Frame schema configuration
1957
+ * @throws Error if frame name already exists
1958
+ */
364
1959
  register(key: FrameName, value: IFrameSchema): void;
1960
+ /**
1961
+ * Validates frame schema structure for required properties.
1962
+ *
1963
+ * Performs shallow validation to ensure all required properties exist
1964
+ * and have correct types before registration in the registry.
1965
+ *
1966
+ * @param frameSchema - Frame schema to validate
1967
+ * @throws Error if frameName is missing or not a string
1968
+ * @throws Error if interval is missing or not a valid FrameInterval
1969
+ * @throws Error if startDate is missing or not a Date
1970
+ * @throws Error if endDate is missing or not a Date
1971
+ */
1972
+ private validateShallow;
1973
+ /**
1974
+ * Overrides an existing frame schema with partial updates.
1975
+ *
1976
+ * @param key - Frame name to override
1977
+ * @param value - Partial schema updates
1978
+ * @throws Error if frame name doesn't exist
1979
+ */
365
1980
  override(key: FrameName, value: Partial<IFrameSchema>): void;
1981
+ /**
1982
+ * Retrieves a frame schema by name.
1983
+ *
1984
+ * @param key - Frame name
1985
+ * @returns Frame schema configuration
1986
+ * @throws Error if frame name doesn't exist
1987
+ */
366
1988
  get(key: FrameName): IFrameSchema;
367
1989
  }
368
1990
 
1991
+ /**
1992
+ * Private service for backtest orchestration using async generators.
1993
+ *
1994
+ * Flow:
1995
+ * 1. Get timeframes from frame service
1996
+ * 2. Iterate through timeframes calling tick()
1997
+ * 3. When signal opens: fetch candles and call backtest()
1998
+ * 4. Skip timeframes until signal closes
1999
+ * 5. Yield closed result and continue
2000
+ *
2001
+ * Memory efficient: streams results without array accumulation.
2002
+ * Supports early termination via break in consumer.
2003
+ */
369
2004
  declare class BacktestLogicPrivateService {
370
2005
  private readonly loggerService;
371
2006
  private readonly strategyGlobalService;
372
2007
  private readonly exchangeGlobalService;
373
2008
  private readonly frameGlobalService;
2009
+ /**
2010
+ * Runs backtest for a symbol, streaming closed signals as async generator.
2011
+ *
2012
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2013
+ * @yields Closed signal results with PNL
2014
+ *
2015
+ * @example
2016
+ * ```typescript
2017
+ * for await (const result of backtestLogic.run("BTCUSDT")) {
2018
+ * console.log(result.closeReason, result.pnl.pnlPercentage);
2019
+ * if (result.pnl.pnlPercentage < -10) break; // Early termination
2020
+ * }
2021
+ * ```
2022
+ */
374
2023
  run(symbol: string): AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
375
2024
  }
376
2025
 
2026
+ /**
2027
+ * Private service for live trading orchestration using async generators.
2028
+ *
2029
+ * Flow:
2030
+ * 1. Infinite while(true) loop for continuous monitoring
2031
+ * 2. Create real-time date with new Date()
2032
+ * 3. Call tick() to check signal status
2033
+ * 4. Yield opened/closed results (skip idle/active)
2034
+ * 5. Sleep for TICK_TTL between iterations
2035
+ *
2036
+ * Features:
2037
+ * - Crash recovery via ClientStrategy.waitForInit()
2038
+ * - Real-time progression with new Date()
2039
+ * - Memory efficient streaming
2040
+ * - Never completes (infinite generator)
2041
+ */
377
2042
  declare class LiveLogicPrivateService {
378
2043
  private readonly loggerService;
379
2044
  private readonly strategyGlobalService;
2045
+ /**
2046
+ * Runs live trading for a symbol, streaming results as async generator.
2047
+ *
2048
+ * Infinite generator that yields opened and closed signals.
2049
+ * Process can crash and restart - state will be recovered from disk.
2050
+ *
2051
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2052
+ * @yields Opened and closed signal results
2053
+ *
2054
+ * @example
2055
+ * ```typescript
2056
+ * for await (const result of liveLogic.run("BTCUSDT")) {
2057
+ * if (result.action === "opened") {
2058
+ * console.log("New signal:", result.signal.id);
2059
+ * }
2060
+ * if (result.action === "closed") {
2061
+ * console.log("PNL:", result.pnl.pnlPercentage);
2062
+ * }
2063
+ * // Infinite loop - will never complete
2064
+ * }
2065
+ * ```
2066
+ */
380
2067
  run(symbol: string): AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
381
2068
  }
382
2069
 
2070
+ /**
2071
+ * Public service for backtest orchestration with context management.
2072
+ *
2073
+ * Wraps BacktestLogicPrivateService with MethodContextService to provide
2074
+ * implicit context propagation for strategyName, exchangeName, and frameName.
2075
+ *
2076
+ * This allows getCandles(), getSignal(), and other functions to work without
2077
+ * explicit context parameters.
2078
+ *
2079
+ * @example
2080
+ * ```typescript
2081
+ * const backtestLogicPublicService = inject(TYPES.backtestLogicPublicService);
2082
+ *
2083
+ * for await (const result of backtestLogicPublicService.run("BTCUSDT", {
2084
+ * strategyName: "my-strategy",
2085
+ * exchangeName: "my-exchange",
2086
+ * frameName: "1d-backtest",
2087
+ * })) {
2088
+ * if (result.action === "closed") {
2089
+ * console.log("PNL:", result.pnl.profit);
2090
+ * }
2091
+ * }
2092
+ * ```
2093
+ */
383
2094
  declare class BacktestLogicPublicService {
384
2095
  private readonly loggerService;
385
2096
  private readonly backtestLogicPrivateService;
2097
+ /**
2098
+ * Runs backtest for a symbol with context propagation.
2099
+ *
2100
+ * Streams closed signals as async generator. Context is automatically
2101
+ * injected into all framework functions called during iteration.
2102
+ *
2103
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2104
+ * @param context - Execution context with strategy, exchange, and frame names
2105
+ * @returns Async generator yielding closed signals with PNL
2106
+ */
386
2107
  run: (symbol: string, context: {
387
2108
  strategyName: string;
388
2109
  exchangeName: string;
@@ -390,27 +2111,102 @@ declare class BacktestLogicPublicService {
390
2111
  }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
391
2112
  }
392
2113
 
2114
+ /**
2115
+ * Public service for live trading orchestration with context management.
2116
+ *
2117
+ * Wraps LiveLogicPrivateService with MethodContextService to provide
2118
+ * implicit context propagation for strategyName and exchangeName.
2119
+ *
2120
+ * This allows getCandles(), getSignal(), and other functions to work without
2121
+ * explicit context parameters.
2122
+ *
2123
+ * Features:
2124
+ * - Infinite async generator (never completes)
2125
+ * - Crash recovery via persisted state
2126
+ * - Real-time progression with Date.now()
2127
+ *
2128
+ * @example
2129
+ * ```typescript
2130
+ * const liveLogicPublicService = inject(TYPES.liveLogicPublicService);
2131
+ *
2132
+ * // Infinite loop - use Ctrl+C to stop
2133
+ * for await (const result of liveLogicPublicService.run("BTCUSDT", {
2134
+ * strategyName: "my-strategy",
2135
+ * exchangeName: "my-exchange",
2136
+ * })) {
2137
+ * if (result.action === "opened") {
2138
+ * console.log("Signal opened:", result.signal);
2139
+ * } else if (result.action === "closed") {
2140
+ * console.log("PNL:", result.pnl.profit);
2141
+ * }
2142
+ * }
2143
+ * ```
2144
+ */
393
2145
  declare class LiveLogicPublicService {
394
2146
  private readonly loggerService;
395
2147
  private readonly liveLogicPrivateService;
2148
+ /**
2149
+ * Runs live trading for a symbol with context propagation.
2150
+ *
2151
+ * Streams opened and closed signals as infinite async generator.
2152
+ * Context is automatically injected into all framework functions.
2153
+ * Process can crash and restart - state will be recovered from disk.
2154
+ *
2155
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2156
+ * @param context - Execution context with strategy and exchange names
2157
+ * @returns Infinite async generator yielding opened and closed signals
2158
+ */
396
2159
  run: (symbol: string, context: {
397
2160
  strategyName: string;
398
2161
  exchangeName: string;
399
2162
  }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
400
2163
  }
401
2164
 
2165
+ /**
2166
+ * Global service providing access to live trading functionality.
2167
+ *
2168
+ * Simple wrapper around LiveLogicPublicService for dependency injection.
2169
+ * Used by public API exports.
2170
+ */
402
2171
  declare class LiveGlobalService {
403
2172
  private readonly loggerService;
404
2173
  private readonly liveLogicPublicService;
2174
+ private readonly strategyValidationService;
2175
+ private readonly exchangeValidationService;
2176
+ /**
2177
+ * Runs live trading for a symbol with context propagation.
2178
+ *
2179
+ * Infinite async generator with crash recovery support.
2180
+ *
2181
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2182
+ * @param context - Execution context with strategy and exchange names
2183
+ * @returns Infinite async generator yielding opened and closed signals
2184
+ */
405
2185
  run: (symbol: string, context: {
406
2186
  strategyName: string;
407
2187
  exchangeName: string;
408
2188
  }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
409
2189
  }
410
2190
 
2191
+ /**
2192
+ * Global service providing access to backtest functionality.
2193
+ *
2194
+ * Simple wrapper around BacktestLogicPublicService for dependency injection.
2195
+ * Used by public API exports.
2196
+ */
411
2197
  declare class BacktestGlobalService {
412
2198
  private readonly loggerService;
413
2199
  private readonly backtestLogicPublicService;
2200
+ private readonly strategyValidationService;
2201
+ private readonly exchangeValidationService;
2202
+ private readonly frameValidationService;
2203
+ /**
2204
+ * Runs backtest for a symbol with context propagation.
2205
+ *
2206
+ * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
2207
+ * @param context - Execution context with strategy, exchange, and frame names
2208
+ * @returns Async generator yielding closed signals with PNL
2209
+ */
414
2210
  run: (symbol: string, context: {
415
2211
  strategyName: string;
416
2212
  exchangeName: string;
@@ -418,7 +2214,356 @@ declare class BacktestGlobalService {
418
2214
  }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
419
2215
  }
420
2216
 
2217
+ /**
2218
+ * Service for generating and saving backtest markdown reports.
2219
+ *
2220
+ * Features:
2221
+ * - Listens to signal events via onTick callback
2222
+ * - Accumulates closed signals per strategy using memoized storage
2223
+ * - Generates markdown tables with detailed signal information
2224
+ * - Saves reports to disk in logs/backtest/{strategyName}.md
2225
+ *
2226
+ * @example
2227
+ * ```typescript
2228
+ * const service = new BacktestMarkdownService();
2229
+ *
2230
+ * // Add to strategy callbacks
2231
+ * addStrategy({
2232
+ * strategyName: "my-strategy",
2233
+ * callbacks: {
2234
+ * onTick: (symbol, result, backtest) => {
2235
+ * service.tick(result);
2236
+ * }
2237
+ * }
2238
+ * });
2239
+ *
2240
+ * // After backtest, generate and save report
2241
+ * await service.saveReport("my-strategy");
2242
+ * ```
2243
+ */
2244
+ declare class BacktestMarkdownService {
2245
+ /** Logger service for debug output */
2246
+ private readonly loggerService;
2247
+ /**
2248
+ * Memoized function to get or create ReportStorage for a strategy.
2249
+ * Each strategy gets its own isolated storage instance.
2250
+ */
2251
+ private getStorage;
2252
+ /**
2253
+ * Processes tick events and accumulates closed signals.
2254
+ * Should be called from IStrategyCallbacks.onTick.
2255
+ *
2256
+ * Only processes closed signals - opened signals are ignored.
2257
+ *
2258
+ * @param data - Tick result from strategy execution (opened or closed)
2259
+ *
2260
+ * @example
2261
+ * ```typescript
2262
+ * const service = new BacktestMarkdownService();
2263
+ *
2264
+ * callbacks: {
2265
+ * onTick: (symbol, result, backtest) => {
2266
+ * service.tick(result);
2267
+ * }
2268
+ * }
2269
+ * ```
2270
+ */
2271
+ private tick;
2272
+ /**
2273
+ * Generates markdown report with all closed signals for a strategy.
2274
+ * Delegates to ReportStorage.generateReport().
2275
+ *
2276
+ * @param strategyName - Strategy name to generate report for
2277
+ * @returns Markdown formatted report string with table of all closed signals
2278
+ *
2279
+ * @example
2280
+ * ```typescript
2281
+ * const service = new BacktestMarkdownService();
2282
+ * const markdown = service.generateReport("my-strategy");
2283
+ * console.log(markdown);
2284
+ * ```
2285
+ */
2286
+ getReport: (strategyName: StrategyName) => Promise<string>;
2287
+ /**
2288
+ * Saves strategy report to disk.
2289
+ * Creates directory if it doesn't exist.
2290
+ * Delegates to ReportStorage.dump().
2291
+ *
2292
+ * @param strategyName - Strategy name to save report for
2293
+ * @param path - Directory path to save report (default: "./logs/backtest")
2294
+ *
2295
+ * @example
2296
+ * ```typescript
2297
+ * const service = new BacktestMarkdownService();
2298
+ *
2299
+ * // Save to default path: ./logs/backtest/my-strategy.md
2300
+ * await service.dump("my-strategy");
2301
+ *
2302
+ * // Save to custom path: ./custom/path/my-strategy.md
2303
+ * await service.dump("my-strategy", "./custom/path");
2304
+ * ```
2305
+ */
2306
+ dump: (strategyName: StrategyName, path?: string) => Promise<void>;
2307
+ /**
2308
+ * Clears accumulated signal data from storage.
2309
+ * If strategyName is provided, clears only that strategy's data.
2310
+ * If strategyName is omitted, clears all strategies' data.
2311
+ *
2312
+ * @param strategyName - Optional strategy name to clear specific strategy data
2313
+ *
2314
+ * @example
2315
+ * ```typescript
2316
+ * const service = new BacktestMarkdownService();
2317
+ *
2318
+ * // Clear specific strategy data
2319
+ * await service.clear("my-strategy");
2320
+ *
2321
+ * // Clear all strategies' data
2322
+ * await service.clear();
2323
+ * ```
2324
+ */
2325
+ clear: (strategyName?: StrategyName) => Promise<void>;
2326
+ /**
2327
+ * Initializes the service by subscribing to backtest signal events.
2328
+ * Uses singleshot to ensure initialization happens only once.
2329
+ * Automatically called on first use.
2330
+ *
2331
+ * @example
2332
+ * ```typescript
2333
+ * const service = new BacktestMarkdownService();
2334
+ * await service.init(); // Subscribe to backtest events
2335
+ * ```
2336
+ */
2337
+ protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
2338
+ }
2339
+
2340
+ /**
2341
+ * Service for generating and saving live trading markdown reports.
2342
+ *
2343
+ * Features:
2344
+ * - Listens to all signal events via onTick callback
2345
+ * - Accumulates all events (idle, opened, active, closed) per strategy
2346
+ * - Generates markdown tables with detailed event information
2347
+ * - Provides trading statistics (win rate, average PNL)
2348
+ * - Saves reports to disk in logs/live/{strategyName}.md
2349
+ *
2350
+ * @example
2351
+ * ```typescript
2352
+ * const service = new LiveMarkdownService();
2353
+ *
2354
+ * // Add to strategy callbacks
2355
+ * addStrategy({
2356
+ * strategyName: "my-strategy",
2357
+ * callbacks: {
2358
+ * onTick: (symbol, result, backtest) => {
2359
+ * if (!backtest) {
2360
+ * service.tick(result);
2361
+ * }
2362
+ * }
2363
+ * }
2364
+ * });
2365
+ *
2366
+ * // Later: generate and save report
2367
+ * await service.dump("my-strategy");
2368
+ * ```
2369
+ */
2370
+ declare class LiveMarkdownService {
2371
+ /** Logger service for debug output */
2372
+ private readonly loggerService;
2373
+ /**
2374
+ * Memoized function to get or create ReportStorage for a strategy.
2375
+ * Each strategy gets its own isolated storage instance.
2376
+ */
2377
+ private getStorage;
2378
+ /**
2379
+ * Processes tick events and accumulates all event types.
2380
+ * Should be called from IStrategyCallbacks.onTick.
2381
+ *
2382
+ * Processes all event types: idle, opened, active, closed.
2383
+ *
2384
+ * @param data - Tick result from strategy execution
2385
+ *
2386
+ * @example
2387
+ * ```typescript
2388
+ * const service = new LiveMarkdownService();
2389
+ *
2390
+ * callbacks: {
2391
+ * onTick: (symbol, result, backtest) => {
2392
+ * if (!backtest) {
2393
+ * service.tick(result);
2394
+ * }
2395
+ * }
2396
+ * }
2397
+ * ```
2398
+ */
2399
+ private tick;
2400
+ /**
2401
+ * Generates markdown report with all events for a strategy.
2402
+ * Delegates to ReportStorage.getReport().
2403
+ *
2404
+ * @param strategyName - Strategy name to generate report for
2405
+ * @returns Markdown formatted report string with table of all events
2406
+ *
2407
+ * @example
2408
+ * ```typescript
2409
+ * const service = new LiveMarkdownService();
2410
+ * const markdown = await service.getReport("my-strategy");
2411
+ * console.log(markdown);
2412
+ * ```
2413
+ */
2414
+ getReport: (strategyName: StrategyName) => Promise<string>;
2415
+ /**
2416
+ * Saves strategy report to disk.
2417
+ * Creates directory if it doesn't exist.
2418
+ * Delegates to ReportStorage.dump().
2419
+ *
2420
+ * @param strategyName - Strategy name to save report for
2421
+ * @param path - Directory path to save report (default: "./logs/live")
2422
+ *
2423
+ * @example
2424
+ * ```typescript
2425
+ * const service = new LiveMarkdownService();
2426
+ *
2427
+ * // Save to default path: ./logs/live/my-strategy.md
2428
+ * await service.dump("my-strategy");
2429
+ *
2430
+ * // Save to custom path: ./custom/path/my-strategy.md
2431
+ * await service.dump("my-strategy", "./custom/path");
2432
+ * ```
2433
+ */
2434
+ dump: (strategyName: StrategyName, path?: string) => Promise<void>;
2435
+ /**
2436
+ * Clears accumulated event data from storage.
2437
+ * If strategyName is provided, clears only that strategy's data.
2438
+ * If strategyName is omitted, clears all strategies' data.
2439
+ *
2440
+ * @param strategyName - Optional strategy name to clear specific strategy data
2441
+ *
2442
+ * @example
2443
+ * ```typescript
2444
+ * const service = new LiveMarkdownService();
2445
+ *
2446
+ * // Clear specific strategy data
2447
+ * await service.clear("my-strategy");
2448
+ *
2449
+ * // Clear all strategies' data
2450
+ * await service.clear();
2451
+ * ```
2452
+ */
2453
+ clear: (strategyName?: StrategyName) => Promise<void>;
2454
+ /**
2455
+ * Initializes the service by subscribing to live signal events.
2456
+ * Uses singleshot to ensure initialization happens only once.
2457
+ * Automatically called on first use.
2458
+ *
2459
+ * @example
2460
+ * ```typescript
2461
+ * const service = new LiveMarkdownService();
2462
+ * await service.init(); // Subscribe to live events
2463
+ * ```
2464
+ */
2465
+ protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
2466
+ }
2467
+
2468
+ /**
2469
+ * @class ExchangeValidationService
2470
+ * Service for managing and validating exchange configurations
2471
+ */
2472
+ declare class ExchangeValidationService {
2473
+ /**
2474
+ * @private
2475
+ * @readonly
2476
+ * Injected logger service instance
2477
+ */
2478
+ private readonly loggerService;
2479
+ /**
2480
+ * @private
2481
+ * Map storing exchange schemas by exchange name
2482
+ */
2483
+ private _exchangeMap;
2484
+ /**
2485
+ * Adds an exchange schema to the validation service
2486
+ * @public
2487
+ * @throws {Error} If exchangeName already exists
2488
+ */
2489
+ addExchange: (exchangeName: ExchangeName, exchangeSchema: IExchangeSchema) => void;
2490
+ /**
2491
+ * Validates the existence of an exchange
2492
+ * @public
2493
+ * @throws {Error} If exchangeName is not found
2494
+ * Memoized function to cache validation results
2495
+ */
2496
+ validate: (exchangeName: ExchangeName, source: string) => void;
2497
+ }
2498
+
2499
+ /**
2500
+ * @class StrategyValidationService
2501
+ * Service for managing and validating strategy configurations
2502
+ */
2503
+ declare class StrategyValidationService {
2504
+ /**
2505
+ * @private
2506
+ * @readonly
2507
+ * Injected logger service instance
2508
+ */
2509
+ private readonly loggerService;
2510
+ /**
2511
+ * @private
2512
+ * Map storing strategy schemas by strategy name
2513
+ */
2514
+ private _strategyMap;
2515
+ /**
2516
+ * Adds a strategy schema to the validation service
2517
+ * @public
2518
+ * @throws {Error} If strategyName already exists
2519
+ */
2520
+ addStrategy: (strategyName: StrategyName, strategySchema: IStrategySchema) => void;
2521
+ /**
2522
+ * Validates the existence of a strategy
2523
+ * @public
2524
+ * @throws {Error} If strategyName is not found
2525
+ * Memoized function to cache validation results
2526
+ */
2527
+ validate: (strategyName: StrategyName, source: string) => void;
2528
+ }
2529
+
2530
+ /**
2531
+ * @class FrameValidationService
2532
+ * Service for managing and validating frame configurations
2533
+ */
2534
+ declare class FrameValidationService {
2535
+ /**
2536
+ * @private
2537
+ * @readonly
2538
+ * Injected logger service instance
2539
+ */
2540
+ private readonly loggerService;
2541
+ /**
2542
+ * @private
2543
+ * Map storing frame schemas by frame name
2544
+ */
2545
+ private _frameMap;
2546
+ /**
2547
+ * Adds a frame schema to the validation service
2548
+ * @public
2549
+ * @throws {Error} If frameName already exists
2550
+ */
2551
+ addFrame: (frameName: FrameName, frameSchema: IFrameSchema) => void;
2552
+ /**
2553
+ * Validates the existence of a frame
2554
+ * @public
2555
+ * @throws {Error} If frameName is not found
2556
+ * Memoized function to cache validation results
2557
+ */
2558
+ validate: (frameName: FrameName, source: string) => void;
2559
+ }
2560
+
421
2561
  declare const backtest: {
2562
+ exchangeValidationService: ExchangeValidationService;
2563
+ strategyValidationService: StrategyValidationService;
2564
+ frameValidationService: FrameValidationService;
2565
+ backtestMarkdownService: BacktestMarkdownService;
2566
+ liveMarkdownService: LiveMarkdownService;
422
2567
  backtestLogicPublicService: BacktestLogicPublicService;
423
2568
  liveLogicPublicService: LiveLogicPublicService;
424
2569
  backtestLogicPrivateService: BacktestLogicPrivateService;
@@ -443,4 +2588,4 @@ declare const backtest: {
443
2588
  loggerService: LoggerService;
444
2589
  };
445
2590
 
446
- export { Backtest, type CandleInterval, ExecutionContextService, type FrameInterval, type ICandleData, type IExchangeSchema, type IFrameSchema, type IPersistBase, type ISignalDto, type ISignalRow, type IStrategyPnL, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, Live, MethodContextService, PersistBase, PersistSignalAdaper, type SignalInterval, type TPersistBase, type TPersistBaseCtor, addExchange, addFrame, addStrategy, backtest, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, reduce, runBacktest, runBacktestGUI, setLogger, startRun, stopAll, stopRun };
2591
+ export { Backtest, type CandleInterval, ExecutionContextService, type FrameInterval, type ICandleData, type IExchangeSchema, type IFrameSchema, type IPersistBase, type ISignalDto, type ISignalRow, type IStrategyPnL, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, Live, MethodContextService, PersistBase, PersistSignalAdaper, type SignalInterval, type TPersistBase, type TPersistBaseCtor, addExchange, addFrame, addStrategy, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, backtest as lib, listenError, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, setLogger };