backtest-kit 1.0.3 → 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 +4132 -407
  3. package/build/index.mjs +4116 -401
  4. package/package.json +2 -9
  5. package/types.d.ts +2432 -69
package/types.d.ts CHANGED
@@ -1,19 +1,6 @@
1
1
  import * as di_scoped from 'di-scoped';
2
2
  import * as functools_kit from 'functools-kit';
3
3
 
4
- interface IExecutionContext {
5
- when: Date;
6
- backtest: boolean;
7
- }
8
- declare const ExecutionContextService: (new () => {
9
- readonly context: IExecutionContext;
10
- }) & Omit<{
11
- new (context: IExecutionContext): {
12
- readonly context: IExecutionContext;
13
- };
14
- }, "prototype"> & di_scoped.IScopedClassRun<[context: IExecutionContext]>;
15
- type TExecutionContextService = InstanceType<typeof ExecutionContextService>;
16
-
17
4
  /**
18
5
  * Interface representing a logging mechanism for the swarm system.
19
6
  * Provides methods to record messages at different severity levels, used across components like agents, sessions, states, storage, swarms, history, embeddings, completions, and policies.
@@ -35,194 +22,2570 @@ interface ILogger {
35
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.
36
23
  */
37
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;
38
30
  }
39
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
+ */
49
+ declare function setLogger(logger: ILogger): Promise<void>;
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
+ */
57
+ interface IExecutionContext {
58
+ /** Trading pair symbol (e.g., "BTCUSDT") */
59
+ symbol: string;
60
+ /** Current timestamp for operation */
61
+ when: Date;
62
+ /** Whether running in backtest mode (true) or live mode (false) */
63
+ backtest: boolean;
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
+ */
84
+ declare const ExecutionContextService: (new () => {
85
+ readonly context: IExecutionContext;
86
+ }) & Omit<{
87
+ new (context: IExecutionContext): {
88
+ readonly context: IExecutionContext;
89
+ };
90
+ }, "prototype"> & di_scoped.IScopedClassRun<[context: IExecutionContext]>;
91
+ /**
92
+ * Type helper for ExecutionContextService instance.
93
+ * Used for dependency injection type annotations.
94
+ */
95
+ type TExecutionContextService = InstanceType<typeof ExecutionContextService>;
96
+
97
+ /**
98
+ * Candle time interval for fetching historical data.
99
+ */
40
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
+ */
41
105
  interface ICandleData {
106
+ /** Unix timestamp in milliseconds when candle opened */
42
107
  timestamp: number;
108
+ /** Opening price at candle start */
43
109
  open: number;
110
+ /** Highest price during candle period */
44
111
  high: number;
112
+ /** Lowest price during candle period */
45
113
  low: number;
114
+ /** Closing price at candle end */
46
115
  close: number;
116
+ /** Trading volume during candle period */
47
117
  volume: number;
48
118
  }
119
+ /**
120
+ * Exchange parameters passed to ClientExchange constructor.
121
+ * Combines schema with runtime dependencies.
122
+ */
49
123
  interface IExchangeParams extends IExchangeSchema {
124
+ /** Logger service for debug output */
50
125
  logger: ILogger;
126
+ /** Execution context service (symbol, when, backtest flag) */
51
127
  execution: TExecutionContextService;
52
128
  }
129
+ /**
130
+ * Optional callbacks for exchange data events.
131
+ */
53
132
  interface IExchangeCallbacks {
133
+ /** Called when candle data is fetched */
54
134
  onCandleData: (symbol: string, interval: CandleInterval, since: Date, limit: number, data: ICandleData[]) => void;
55
135
  }
136
+ /**
137
+ * Exchange schema registered via addExchange().
138
+ * Defines candle data source and formatting logic.
139
+ */
56
140
  interface IExchangeSchema {
141
+ /** Unique exchange identifier for registration */
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
+ */
57
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
+ */
58
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
+ */
59
168
  formatPrice: (symbol: string, price: number) => Promise<string>;
169
+ /** Optional lifecycle event callbacks (onCandleData) */
60
170
  callbacks?: Partial<IExchangeCallbacks>;
61
171
  }
172
+ /**
173
+ * Exchange interface implemented by ClientExchange.
174
+ * Provides candle data access and VWAP calculation.
175
+ */
62
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
+ */
63
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
+ */
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
+ */
64
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
+ */
65
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
+ */
66
220
  getAveragePrice: (symbol: string) => Promise<number>;
67
221
  }
222
+ /**
223
+ * Unique exchange identifier.
224
+ */
225
+ type ExchangeName = string;
68
226
 
69
- interface ISignalData {
70
- id: string;
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
+ */
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
+ */
361
+ interface ISignalDto {
362
+ /** Optional signal ID (auto-generated if not provided) */
363
+ id?: string;
364
+ /** Trade direction: "long" (buy) or "short" (sell) */
71
365
  position: "long" | "short";
72
- note: string;
366
+ /** Human-readable description of signal reason */
367
+ note?: string;
368
+ /** Entry price for the position */
73
369
  priceOpen: number;
370
+ /** Take profit target price (must be > priceOpen for long, < priceOpen for short) */
74
371
  priceTakeProfit: number;
372
+ /** Stop loss exit price (must be < priceOpen for long, > priceOpen for short) */
75
373
  priceStopLoss: number;
374
+ /** Expected duration in minutes before time_expired */
76
375
  minuteEstimatedTime: number;
376
+ }
377
+ /**
378
+ * Complete signal with auto-generated id.
379
+ * Used throughout the system after validation.
380
+ */
381
+ interface ISignalRow extends ISignalDto {
382
+ /** Unique signal identifier (UUID v4 auto-generated) */
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 */
77
389
  timestamp: number;
390
+ /** Trading pair symbol (e.g., "BTCUSDT") */
391
+ symbol: string;
78
392
  }
393
+ /**
394
+ * Optional lifecycle callbacks for signal events.
395
+ * Called when signals are opened, active, idle, or closed.
396
+ */
79
397
  interface IStrategyCallbacks {
80
- onOpen: (backtest: boolean, symbol: string, data: ISignalData) => void;
81
- onClose: (backtest: boolean, symbol: string, priceClose: number, data: ISignalData) => 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;
82
408
  }
409
+ /**
410
+ * Strategy schema registered via addStrategy().
411
+ * Defines signal generation logic and configuration.
412
+ */
83
413
  interface IStrategySchema {
84
- getSignal: (symbol: string) => Promise<ISignalData | null>;
414
+ /** Unique strategy identifier for registration */
415
+ strategyName: StrategyName;
416
+ /** Minimum interval between getSignal calls (throttling) */
417
+ interval: SignalInterval;
418
+ /** Signal generation function (returns null if no signal, validated DTO if signal) */
419
+ getSignal: (symbol: string) => Promise<ISignalDto | null>;
420
+ /** Optional lifecycle event callbacks (onOpen, onClose) */
85
421
  callbacks?: Partial<IStrategyCallbacks>;
86
422
  }
423
+ /**
424
+ * Reason why signal was closed.
425
+ * Used in discriminated union for type-safe handling.
426
+ */
87
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
+ */
88
432
  interface IStrategyPnL {
433
+ /** Profit/loss as percentage (e.g., 1.5 for +1.5%, -2.3 for -2.3%) */
89
434
  pnlPercentage: number;
435
+ /** Entry price adjusted with slippage and fees */
90
436
  priceOpen: number;
437
+ /** Exit price adjusted with slippage and fees */
91
438
  priceClose: number;
92
439
  }
440
+ /**
441
+ * Tick result: no active signal, idle state.
442
+ */
93
443
  interface IStrategyTickResultIdle {
444
+ /** Discriminator for type-safe union */
94
445
  action: "idle";
446
+ /** No signal in idle state */
95
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;
96
454
  }
455
+ /**
456
+ * Tick result: new signal just created.
457
+ * Triggered after getSignal validation and persistence.
458
+ */
97
459
  interface IStrategyTickResultOpened {
460
+ /** Discriminator for type-safe union */
98
461
  action: "opened";
99
- signal: ISignalData;
462
+ /** Newly created and validated signal with generated ID */
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;
100
470
  }
471
+ /**
472
+ * Tick result: signal is being monitored.
473
+ * Waiting for TP/SL or time expiration.
474
+ */
101
475
  interface IStrategyTickResultActive {
476
+ /** Discriminator for type-safe union */
102
477
  action: "active";
103
- signal: ISignalData;
478
+ /** Currently monitored signal */
479
+ signal: ISignalRow;
480
+ /** Current VWAP price for monitoring */
104
481
  currentPrice: number;
482
+ /** Strategy name for tracking */
483
+ strategyName: StrategyName;
484
+ /** Exchange name for tracking */
485
+ exchangeName: ExchangeName;
105
486
  }
487
+ /**
488
+ * Tick result: signal closed with PNL.
489
+ * Final state with close reason and profit/loss calculation.
490
+ */
106
491
  interface IStrategyTickResultClosed {
492
+ /** Discriminator for type-safe union */
107
493
  action: "closed";
108
- signal: ISignalData;
494
+ /** Completed signal with original parameters */
495
+ signal: ISignalRow;
496
+ /** Final VWAP price at close */
109
497
  currentPrice: number;
498
+ /** Why signal closed (time_expired | take_profit | stop_loss) */
110
499
  closeReason: StrategyCloseReason;
500
+ /** Unix timestamp in milliseconds when signal closed */
501
+ closeTimestamp: number;
502
+ /** Profit/loss calculation with fees and slippage */
111
503
  pnl: IStrategyPnL;
504
+ /** Strategy name for tracking */
505
+ strategyName: StrategyName;
506
+ /** Exchange name for tracking */
507
+ exchangeName: ExchangeName;
112
508
  }
509
+ /**
510
+ * Discriminated union of all tick results.
511
+ * Use type guards: `result.action === "closed"` for type safety.
512
+ */
113
513
  type IStrategyTickResult = IStrategyTickResultIdle | IStrategyTickResultOpened | IStrategyTickResultActive | IStrategyTickResultClosed;
514
+ /**
515
+ * Backtest always returns closed result (TP/SL or time_expired).
516
+ */
517
+ type IStrategyBacktestResult = IStrategyTickResultClosed;
518
+ /**
519
+ * Strategy interface implemented by ClientStrategy.
520
+ * Defines core strategy execution methods.
521
+ */
114
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
+ */
115
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
+ */
538
+ backtest: (candles: ICandleData[]) => Promise<IStrategyBacktestResult>;
116
539
  }
540
+ /**
541
+ * Unique strategy identifier.
542
+ */
543
+ type StrategyName = string;
117
544
 
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
+ */
118
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
+ */
119
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
+ */
646
+ declare function addFrame(frameSchema: IFrameSchema): void;
120
647
 
121
- interface IBacktestResult {
122
- symbol: string;
123
- results: IStrategyTickResult[];
124
- }
125
- declare function runBacktest(symbol: string, timeframes: Date[]): Promise<IBacktestResult>;
126
- declare function runBacktestGUI(symbol: string, timeframes: Date[]): Promise<void>;
127
-
128
- interface IReduceResult<T> {
129
- symbol: string;
130
- accumulator: T;
131
- totalTicks: number;
132
- }
133
- type ReduceCallback<T> = (accumulator: T, index: number, when: Date, symbol: string) => T | Promise<T>;
134
- declare function reduce<T>(symbol: string, timeframes: Date[], callback: ReduceCallback<T>, initialValue: T): Promise<IReduceResult<T>>;
135
-
136
- interface IRunConfig {
137
- symbol: string;
138
- interval: number;
139
- }
140
- declare function startRun(config: IRunConfig): void;
141
- declare function stopRun(symbol: string): void;
142
- 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;
143
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
+ */
144
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
+ */
145
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
+ */
146
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
+ */
147
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
+ */
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
+ */
917
+ declare function getMode(): Promise<"backtest" | "live">;
918
+
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
+ */
924
+ interface ISignalData {
925
+ /** Current signal state (null when no active signal) */
926
+ signalRow: ISignalRow | null;
927
+ }
928
+ /**
929
+ * Type helper for PersistBase instance.
930
+ */
931
+ type TPersistBase = InstanceType<typeof PersistBase>;
932
+ /**
933
+ * Constructor type for PersistBase.
934
+ * Used for custom persistence adapters.
935
+ */
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
+ */
940
+ type EntityId = string | number;
941
+ /**
942
+ * Base interface for persisted entities.
943
+ */
944
+ interface IEntity {
945
+ }
946
+ /**
947
+ * Persistence interface for CRUD operations.
948
+ * Implemented by PersistBase.
949
+ */
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
+ */
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
+ */
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
+ */
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
+ */
982
+ writeValue(entityId: EntityId, entity: Entity): Promise<void>;
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
+ */
1001
+ declare const PersistBase: {
1002
+ new <EntityName extends string = string>(entityName: EntityName, baseDir?: string): {
1003
+ /** Computed directory path for entity storage */
1004
+ _directory: string;
1005
+ readonly entityName: EntityName;
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
+ */
1013
+ _getFilePath(entityId: EntityId): string;
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
+ */
1020
+ getCount(): Promise<number>;
1021
+ readValue<T extends IEntity = IEntity>(entityId: EntityId): Promise<T>;
1022
+ hasValue(entityId: EntityId): Promise<boolean>;
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
+ */
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
+ */
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
+ */
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
+ */
1054
+ keys(): AsyncGenerator<EntityId>;
1055
+ /**
1056
+ * Filters entities by predicate function.
1057
+ *
1058
+ * @param predicate - Filter function
1059
+ * @returns AsyncGenerator yielding filtered entities
1060
+ */
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
+ */
1069
+ take<T extends IEntity = IEntity>(total: number, predicate?: (value: T) => boolean): AsyncGenerator<T>;
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
+ */
1077
+ [Symbol.asyncIterator](): AsyncIterableIterator<any>;
1078
+ };
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
+ */
1091
+ declare class PersistSignalUtils {
1092
+ private PersistSignalFactory;
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
+ */
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
+ */
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
+ */
1131
+ writeSignalData: (signalRow: ISignalRow | null, strategyName: StrategyName, symbol: string) => Promise<void>;
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
+ */
1149
+ declare const PersistSignalAdaper: PersistSignalUtils;
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
+ */
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
+ */
1178
+ run: (symbol: string, context: {
1179
+ strategyName: string;
1180
+ exchangeName: string;
1181
+ frameName: string;
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>;
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
+ */
1257
+ declare const Backtest: BacktestUtils;
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
+ */
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
+ */
1299
+ run: (symbol: string, context: {
1300
+ strategyName: string;
1301
+ exchangeName: string;
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>;
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
+ */
1373
+ declare const Live: LiveUtils;
148
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
+ */
149
1386
  declare class LoggerService implements ILogger {
1387
+ private readonly methodContextService;
1388
+ private readonly executionContextService;
150
1389
  private _commonLogger;
1390
+ /**
1391
+ * Gets current method context if available.
1392
+ * Contains strategyName, exchangeName, frameName from MethodContextService.
1393
+ */
1394
+ private get methodContext();
1395
+ /**
1396
+ * Gets current execution context if available.
1397
+ * Contains symbol, when, backtest from ExecutionContextService.
1398
+ */
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
+ */
151
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
+ */
152
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
+ */
153
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
+ */
154
1433
  setLogger: (logger: ILogger) => void;
155
1434
  }
156
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
+ */
157
1462
  declare class ClientExchange implements IExchange {
158
1463
  readonly params: IExchangeParams;
159
1464
  constructor(params: IExchangeParams);
160
- getCandles: (symbol: string, interval: CandleInterval, limit: number) => Promise<ICandleData[]>;
161
- getAveragePrice: (symbol: string) => Promise<number>;
162
- formatQuantity: (symbol: string, quantity: number) => Promise<string>;
163
- formatPrice: (symbol: string, price: number) => Promise<string>;
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
+ */
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
+ */
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
+ */
1498
+ getAveragePrice(symbol: string): Promise<number>;
1499
+ formatQuantity(symbol: string, quantity: number): Promise<string>;
1500
+ formatPrice(symbol: string, price: number): Promise<string>;
164
1501
  }
165
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
+ */
166
1525
  declare class ExchangeConnectionService implements IExchange {
167
1526
  private readonly loggerService;
168
1527
  private readonly executionContextService;
169
1528
  private readonly exchangeSchemaService;
170
- getExchange: ((symbol: string) => ClientExchange) & functools_kit.IClearableMemoize<string> & functools_kit.IControlMemoize<string, ClientExchange>;
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
+ */
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
+ */
171
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
+ */
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
+ */
172
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
+ */
173
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
+ */
174
1592
  formatQuantity: (symbol: string, quantity: number) => Promise<string>;
175
1593
  }
176
1594
 
177
- declare class ExchangeSchemaService {
178
- private readonly loggerService;
179
- private _exchangeSchema;
180
- getSchema: () => IExchangeSchema;
181
- addSchema: (exchangeSchema: IExchangeSchema) => void;
182
- }
183
-
184
- declare class StrategySchemaService {
185
- private readonly loggerService;
186
- private _strategySchema;
187
- getSchema: () => IStrategySchema;
188
- addSchema: (strategySchema: IStrategySchema) => void;
189
- }
190
-
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
+ */
191
1616
  declare class StrategyConnectionService implements IStrategy {
192
1617
  private readonly loggerService;
193
1618
  private readonly executionContextService;
194
1619
  private readonly strategySchemaService;
195
1620
  private readonly exchangeConnectionService;
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
+ */
196
1631
  private getStrategy;
197
- tick: (symbol: string) => Promise<IStrategyTickResult>;
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
+ */
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
+ */
1650
+ backtest: (candles: ICandleData[]) => Promise<IStrategyBacktestResult>;
1651
+ }
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
+ */
1664
+ declare class ClientFrame implements IFrame {
1665
+ readonly params: IFrameParams;
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
+ */
1675
+ getTimeframe: ((symbol: string) => Promise<Date[]>) & functools_kit.ISingleshotClearable;
1676
+ }
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
+ */
1700
+ declare class FrameConnectionService implements IFrame {
1701
+ private readonly loggerService;
1702
+ private readonly frameSchemaService;
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
+ */
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
+ */
1723
+ getTimeframe: (symbol: string) => Promise<Date[]>;
198
1724
  }
199
1725
 
200
- declare class ExchangePublicService {
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
+ */
1734
+ declare class ExchangeGlobalService {
201
1735
  private readonly loggerService;
202
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
+ */
203
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
+ */
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
+ */
204
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
+ */
205
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
+ */
206
1787
  formatQuantity: (symbol: string, quantity: number, when: Date, backtest: boolean) => Promise<string>;
207
1788
  }
208
1789
 
209
- declare class StrategyPublicService {
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
+ */
1798
+ declare class StrategyGlobalService {
210
1799
  private readonly loggerService;
211
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
+ */
212
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
+ */
1825
+ backtest: (symbol: string, candles: ICandleData[], when: Date, backtest: boolean) => Promise<IStrategyBacktestResult>;
1826
+ }
1827
+
1828
+ /**
1829
+ * Global service for frame operations.
1830
+ *
1831
+ * Wraps FrameConnectionService for timeframe generation.
1832
+ * Used internally by BacktestLogicPrivateService.
1833
+ */
1834
+ declare class FrameGlobalService {
1835
+ private readonly loggerService;
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
+ */
1843
+ getTimeframe: (symbol: string) => Promise<Date[]>;
1844
+ }
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
+ */
1852
+ declare class ExchangeSchemaService {
1853
+ readonly loggerService: LoggerService;
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
+ */
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
+ */
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
+ */
1892
+ get: (key: ExchangeName) => IExchangeSchema;
1893
+ }
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
+ */
1901
+ declare class StrategySchemaService {
1902
+ readonly loggerService: LoggerService;
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
+ */
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
+ */
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
+ */
1940
+ get: (key: StrategyName) => IStrategySchema;
1941
+ }
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
+ */
1949
+ declare class FrameSchemaService {
1950
+ readonly loggerService: LoggerService;
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
+ */
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
+ */
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
+ */
1988
+ get(key: FrameName): IFrameSchema;
1989
+ }
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
+ */
2004
+ declare class BacktestLogicPrivateService {
2005
+ private readonly loggerService;
2006
+ private readonly strategyGlobalService;
2007
+ private readonly exchangeGlobalService;
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
+ */
2023
+ run(symbol: string): AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
2024
+ }
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
+ */
2042
+ declare class LiveLogicPrivateService {
2043
+ private readonly loggerService;
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
+ */
2067
+ run(symbol: string): AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
2068
+ }
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
+ */
2094
+ declare class BacktestLogicPublicService {
2095
+ private readonly loggerService;
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
+ */
2107
+ run: (symbol: string, context: {
2108
+ strategyName: string;
2109
+ exchangeName: string;
2110
+ frameName: string;
2111
+ }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
2112
+ }
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
+ */
2145
+ declare class LiveLogicPublicService {
2146
+ private readonly loggerService;
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
+ */
2159
+ run: (symbol: string, context: {
2160
+ strategyName: string;
2161
+ exchangeName: string;
2162
+ }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
2163
+ }
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
+ */
2171
+ declare class LiveGlobalService {
2172
+ private readonly loggerService;
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
+ */
2185
+ run: (symbol: string, context: {
2186
+ strategyName: string;
2187
+ exchangeName: string;
2188
+ }) => AsyncGenerator<IStrategyTickResultOpened | IStrategyTickResultClosed, void, unknown>;
2189
+ }
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
+ */
2197
+ declare class BacktestGlobalService {
2198
+ private readonly loggerService;
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
+ */
2210
+ run: (symbol: string, context: {
2211
+ strategyName: string;
2212
+ exchangeName: string;
2213
+ frameName: string;
2214
+ }) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
2215
+ }
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;
213
2559
  }
214
2560
 
215
2561
  declare const backtest: {
216
- exchangePublicService: ExchangePublicService;
217
- strategyPublicService: StrategyPublicService;
2562
+ exchangeValidationService: ExchangeValidationService;
2563
+ strategyValidationService: StrategyValidationService;
2564
+ frameValidationService: FrameValidationService;
2565
+ backtestMarkdownService: BacktestMarkdownService;
2566
+ liveMarkdownService: LiveMarkdownService;
2567
+ backtestLogicPublicService: BacktestLogicPublicService;
2568
+ liveLogicPublicService: LiveLogicPublicService;
2569
+ backtestLogicPrivateService: BacktestLogicPrivateService;
2570
+ liveLogicPrivateService: LiveLogicPrivateService;
2571
+ exchangeGlobalService: ExchangeGlobalService;
2572
+ strategyGlobalService: StrategyGlobalService;
2573
+ frameGlobalService: FrameGlobalService;
2574
+ liveGlobalService: LiveGlobalService;
2575
+ backtestGlobalService: BacktestGlobalService;
218
2576
  exchangeSchemaService: ExchangeSchemaService;
219
2577
  strategySchemaService: StrategySchemaService;
2578
+ frameSchemaService: FrameSchemaService;
220
2579
  exchangeConnectionService: ExchangeConnectionService;
221
2580
  strategyConnectionService: StrategyConnectionService;
2581
+ frameConnectionService: FrameConnectionService;
222
2582
  executionContextService: {
223
2583
  readonly context: IExecutionContext;
224
2584
  };
2585
+ methodContextService: {
2586
+ readonly context: IMethodContext;
2587
+ };
225
2588
  loggerService: LoggerService;
226
2589
  };
227
2590
 
228
- export { type CandleInterval, ExecutionContextService, type ICandleData, type IExchangeSchema, type ISignalData, type IStrategyPnL, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, addExchange, addStrategy, backtest, formatPrice, formatQuantity, getAveragePrice, getCandles, reduce, runBacktest, runBacktestGUI, 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 };