backtest-kit 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +133 -1
- package/build/index.cjs +519 -5
- package/build/index.mjs +518 -6
- package/package.json +2 -2
- package/types.d.ts +339 -1
package/types.d.ts
CHANGED
|
@@ -819,6 +819,51 @@ interface ProgressContract {
|
|
|
819
819
|
progress: number;
|
|
820
820
|
}
|
|
821
821
|
|
|
822
|
+
/**
|
|
823
|
+
* Performance metric types tracked by the system.
|
|
824
|
+
*
|
|
825
|
+
* Backtest metrics:
|
|
826
|
+
* - backtest_total: Total backtest duration from start to finish
|
|
827
|
+
* - backtest_timeframe: Duration to process a single timeframe iteration
|
|
828
|
+
* - backtest_signal: Duration to process a signal (tick + getNextCandles + backtest)
|
|
829
|
+
*
|
|
830
|
+
* Live metrics:
|
|
831
|
+
* - live_tick: Duration of a single live tick iteration
|
|
832
|
+
*/
|
|
833
|
+
type PerformanceMetricType = "backtest_total" | "backtest_timeframe" | "backtest_signal" | "live_tick";
|
|
834
|
+
/**
|
|
835
|
+
* Contract for performance tracking events.
|
|
836
|
+
*
|
|
837
|
+
* Emitted during execution to track performance metrics for various operations.
|
|
838
|
+
* Useful for profiling and identifying bottlenecks.
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```typescript
|
|
842
|
+
* import { listenPerformance } from "backtest-kit";
|
|
843
|
+
*
|
|
844
|
+
* listenPerformance((event) => {
|
|
845
|
+
* console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
|
|
846
|
+
* console.log(`${event.strategyName} @ ${event.exchangeName}`);
|
|
847
|
+
* });
|
|
848
|
+
* ```
|
|
849
|
+
*/
|
|
850
|
+
interface PerformanceContract {
|
|
851
|
+
/** Timestamp when the metric was recorded (milliseconds since epoch) */
|
|
852
|
+
timestamp: number;
|
|
853
|
+
/** Type of operation being measured */
|
|
854
|
+
metricType: PerformanceMetricType;
|
|
855
|
+
/** Duration of the operation in milliseconds */
|
|
856
|
+
duration: number;
|
|
857
|
+
/** Strategy name associated with this metric */
|
|
858
|
+
strategyName: string;
|
|
859
|
+
/** Exchange name associated with this metric */
|
|
860
|
+
exchangeName: string;
|
|
861
|
+
/** Trading symbol associated with this metric */
|
|
862
|
+
symbol: string;
|
|
863
|
+
/** Whether this metric is from backtest mode (true) or live mode (false) */
|
|
864
|
+
backtest: boolean;
|
|
865
|
+
}
|
|
866
|
+
|
|
822
867
|
/**
|
|
823
868
|
* Subscribes to all signal events with queued async processing.
|
|
824
869
|
*
|
|
@@ -1078,6 +1123,39 @@ declare function listenDoneOnce(filterFn: (event: DoneContract) => boolean, fn:
|
|
|
1078
1123
|
* ```
|
|
1079
1124
|
*/
|
|
1080
1125
|
declare function listenProgress(fn: (event: ProgressContract) => void): () => void;
|
|
1126
|
+
/**
|
|
1127
|
+
* Subscribes to performance metric events with queued async processing.
|
|
1128
|
+
*
|
|
1129
|
+
* Emits during strategy execution to track timing metrics for operations.
|
|
1130
|
+
* Useful for profiling and identifying performance bottlenecks.
|
|
1131
|
+
* Events are processed sequentially in order received, even if callback is async.
|
|
1132
|
+
* Uses queued wrapper to prevent concurrent execution of the callback.
|
|
1133
|
+
*
|
|
1134
|
+
* @param fn - Callback function to handle performance events
|
|
1135
|
+
* @returns Unsubscribe function to stop listening to events
|
|
1136
|
+
*
|
|
1137
|
+
* @example
|
|
1138
|
+
* ```typescript
|
|
1139
|
+
* import { listenPerformance, Backtest } from "backtest-kit";
|
|
1140
|
+
*
|
|
1141
|
+
* const unsubscribe = listenPerformance((event) => {
|
|
1142
|
+
* console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
|
|
1143
|
+
* if (event.duration > 100) {
|
|
1144
|
+
* console.warn("Slow operation detected:", event.metricType);
|
|
1145
|
+
* }
|
|
1146
|
+
* });
|
|
1147
|
+
*
|
|
1148
|
+
* Backtest.background("BTCUSDT", {
|
|
1149
|
+
* strategyName: "my-strategy",
|
|
1150
|
+
* exchangeName: "binance",
|
|
1151
|
+
* frameName: "1d-backtest"
|
|
1152
|
+
* });
|
|
1153
|
+
*
|
|
1154
|
+
* // Later: stop listening
|
|
1155
|
+
* unsubscribe();
|
|
1156
|
+
* ```
|
|
1157
|
+
*/
|
|
1158
|
+
declare function listenPerformance(fn: (event: PerformanceContract) => void): () => void;
|
|
1081
1159
|
|
|
1082
1160
|
/**
|
|
1083
1161
|
* Fetches historical candle data from the registered exchange.
|
|
@@ -1590,6 +1668,145 @@ declare class LiveMarkdownService {
|
|
|
1590
1668
|
protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
1591
1669
|
}
|
|
1592
1670
|
|
|
1671
|
+
/**
|
|
1672
|
+
* Aggregated statistics for a specific metric type.
|
|
1673
|
+
*/
|
|
1674
|
+
interface MetricStats {
|
|
1675
|
+
/** Type of metric */
|
|
1676
|
+
metricType: PerformanceMetricType;
|
|
1677
|
+
/** Number of recorded samples */
|
|
1678
|
+
count: number;
|
|
1679
|
+
/** Total duration across all samples (ms) */
|
|
1680
|
+
totalDuration: number;
|
|
1681
|
+
/** Average duration (ms) */
|
|
1682
|
+
avgDuration: number;
|
|
1683
|
+
/** Minimum duration (ms) */
|
|
1684
|
+
minDuration: number;
|
|
1685
|
+
/** Maximum duration (ms) */
|
|
1686
|
+
maxDuration: number;
|
|
1687
|
+
/** Standard deviation of duration (ms) */
|
|
1688
|
+
stdDev: number;
|
|
1689
|
+
/** Median duration (ms) */
|
|
1690
|
+
median: number;
|
|
1691
|
+
/** 95th percentile duration (ms) */
|
|
1692
|
+
p95: number;
|
|
1693
|
+
/** 99th percentile duration (ms) */
|
|
1694
|
+
p99: number;
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Performance statistics aggregated by strategy.
|
|
1698
|
+
*/
|
|
1699
|
+
interface PerformanceStatistics {
|
|
1700
|
+
/** Strategy name */
|
|
1701
|
+
strategyName: string;
|
|
1702
|
+
/** Total number of performance events recorded */
|
|
1703
|
+
totalEvents: number;
|
|
1704
|
+
/** Total execution time across all metrics (ms) */
|
|
1705
|
+
totalDuration: number;
|
|
1706
|
+
/** Statistics grouped by metric type */
|
|
1707
|
+
metricStats: Record<string, MetricStats>;
|
|
1708
|
+
/** All raw performance events */
|
|
1709
|
+
events: PerformanceContract[];
|
|
1710
|
+
}
|
|
1711
|
+
/**
|
|
1712
|
+
* Service for collecting and analyzing performance metrics.
|
|
1713
|
+
*
|
|
1714
|
+
* Features:
|
|
1715
|
+
* - Listens to performance events via performanceEmitter
|
|
1716
|
+
* - Accumulates metrics per strategy
|
|
1717
|
+
* - Calculates aggregated statistics (avg, min, max, percentiles)
|
|
1718
|
+
* - Generates markdown reports with bottleneck analysis
|
|
1719
|
+
* - Saves reports to disk in logs/performance/{strategyName}.md
|
|
1720
|
+
*
|
|
1721
|
+
* @example
|
|
1722
|
+
* ```typescript
|
|
1723
|
+
* import { listenPerformance } from "backtest-kit";
|
|
1724
|
+
*
|
|
1725
|
+
* // Subscribe to performance events
|
|
1726
|
+
* listenPerformance((event) => {
|
|
1727
|
+
* console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
|
|
1728
|
+
* });
|
|
1729
|
+
*
|
|
1730
|
+
* // After execution, generate report
|
|
1731
|
+
* const stats = await Performance.getData("my-strategy");
|
|
1732
|
+
* console.log("Bottlenecks:", stats.metricStats);
|
|
1733
|
+
*
|
|
1734
|
+
* // Save report to disk
|
|
1735
|
+
* await Performance.dump("my-strategy");
|
|
1736
|
+
* ```
|
|
1737
|
+
*/
|
|
1738
|
+
declare class PerformanceMarkdownService {
|
|
1739
|
+
/** Logger service for debug output */
|
|
1740
|
+
private readonly loggerService;
|
|
1741
|
+
/**
|
|
1742
|
+
* Memoized function to get or create PerformanceStorage for a strategy.
|
|
1743
|
+
* Each strategy gets its own isolated storage instance.
|
|
1744
|
+
*/
|
|
1745
|
+
private getStorage;
|
|
1746
|
+
/**
|
|
1747
|
+
* Processes performance events and accumulates metrics.
|
|
1748
|
+
* Should be called from performance tracking code.
|
|
1749
|
+
*
|
|
1750
|
+
* @param event - Performance event with timing data
|
|
1751
|
+
*/
|
|
1752
|
+
private track;
|
|
1753
|
+
/**
|
|
1754
|
+
* Gets aggregated performance statistics for a strategy.
|
|
1755
|
+
*
|
|
1756
|
+
* @param strategyName - Strategy name to get data for
|
|
1757
|
+
* @returns Performance statistics with aggregated metrics
|
|
1758
|
+
*
|
|
1759
|
+
* @example
|
|
1760
|
+
* ```typescript
|
|
1761
|
+
* const stats = await performanceService.getData("my-strategy");
|
|
1762
|
+
* console.log("Total time:", stats.totalDuration);
|
|
1763
|
+
* console.log("Slowest operation:", Object.values(stats.metricStats)
|
|
1764
|
+
* .sort((a, b) => b.avgDuration - a.avgDuration)[0]);
|
|
1765
|
+
* ```
|
|
1766
|
+
*/
|
|
1767
|
+
getData: (strategyName: string) => Promise<PerformanceStatistics>;
|
|
1768
|
+
/**
|
|
1769
|
+
* Generates markdown report with performance analysis.
|
|
1770
|
+
*
|
|
1771
|
+
* @param strategyName - Strategy name to generate report for
|
|
1772
|
+
* @returns Markdown formatted report string
|
|
1773
|
+
*
|
|
1774
|
+
* @example
|
|
1775
|
+
* ```typescript
|
|
1776
|
+
* const markdown = await performanceService.getReport("my-strategy");
|
|
1777
|
+
* console.log(markdown);
|
|
1778
|
+
* ```
|
|
1779
|
+
*/
|
|
1780
|
+
getReport: (strategyName: string) => Promise<string>;
|
|
1781
|
+
/**
|
|
1782
|
+
* Saves performance report to disk.
|
|
1783
|
+
*
|
|
1784
|
+
* @param strategyName - Strategy name to save report for
|
|
1785
|
+
* @param path - Directory path to save report
|
|
1786
|
+
*
|
|
1787
|
+
* @example
|
|
1788
|
+
* ```typescript
|
|
1789
|
+
* // Save to default path: ./logs/performance/my-strategy.md
|
|
1790
|
+
* await performanceService.dump("my-strategy");
|
|
1791
|
+
*
|
|
1792
|
+
* // Save to custom path
|
|
1793
|
+
* await performanceService.dump("my-strategy", "./custom/path");
|
|
1794
|
+
* ```
|
|
1795
|
+
*/
|
|
1796
|
+
dump: (strategyName: string, path?: string) => Promise<void>;
|
|
1797
|
+
/**
|
|
1798
|
+
* Clears accumulated performance data from storage.
|
|
1799
|
+
*
|
|
1800
|
+
* @param strategyName - Optional strategy name to clear specific strategy data
|
|
1801
|
+
*/
|
|
1802
|
+
clear: (strategyName?: string) => Promise<void>;
|
|
1803
|
+
/**
|
|
1804
|
+
* Initializes the service by subscribing to performance events.
|
|
1805
|
+
* Uses singleshot to ensure initialization happens only once.
|
|
1806
|
+
*/
|
|
1807
|
+
protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1593
1810
|
declare const BASE_WAIT_FOR_INIT_SYMBOL: unique symbol;
|
|
1594
1811
|
/**
|
|
1595
1812
|
* Signal data stored in persistence layer.
|
|
@@ -2069,6 +2286,125 @@ declare class LiveUtils {
|
|
|
2069
2286
|
*/
|
|
2070
2287
|
declare const Live: LiveUtils;
|
|
2071
2288
|
|
|
2289
|
+
/**
|
|
2290
|
+
* Performance class provides static methods for performance metrics analysis.
|
|
2291
|
+
*
|
|
2292
|
+
* Features:
|
|
2293
|
+
* - Get aggregated performance statistics by strategy
|
|
2294
|
+
* - Generate markdown reports with bottleneck analysis
|
|
2295
|
+
* - Save reports to disk
|
|
2296
|
+
* - Clear accumulated metrics
|
|
2297
|
+
*
|
|
2298
|
+
* @example
|
|
2299
|
+
* ```typescript
|
|
2300
|
+
* import { Performance, listenPerformance } from "backtest-kit";
|
|
2301
|
+
*
|
|
2302
|
+
* // Subscribe to performance events
|
|
2303
|
+
* listenPerformance((event) => {
|
|
2304
|
+
* console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
|
|
2305
|
+
* });
|
|
2306
|
+
*
|
|
2307
|
+
* // Run backtest...
|
|
2308
|
+
*
|
|
2309
|
+
* // Get aggregated statistics
|
|
2310
|
+
* const stats = await Performance.getData("my-strategy");
|
|
2311
|
+
* console.log("Total time:", stats.totalDuration);
|
|
2312
|
+
* console.log("Slowest operations:", Object.values(stats.metricStats)
|
|
2313
|
+
* .sort((a, b) => b.avgDuration - a.avgDuration)
|
|
2314
|
+
* .slice(0, 5));
|
|
2315
|
+
*
|
|
2316
|
+
* // Generate and save report
|
|
2317
|
+
* await Performance.dump("my-strategy");
|
|
2318
|
+
* ```
|
|
2319
|
+
*/
|
|
2320
|
+
declare class Performance {
|
|
2321
|
+
/**
|
|
2322
|
+
* Gets aggregated performance statistics for a strategy.
|
|
2323
|
+
*
|
|
2324
|
+
* Returns detailed metrics grouped by operation type:
|
|
2325
|
+
* - Count, total duration, average, min, max
|
|
2326
|
+
* - Standard deviation for volatility
|
|
2327
|
+
* - Percentiles (median, P95, P99) for outlier detection
|
|
2328
|
+
*
|
|
2329
|
+
* @param strategyName - Strategy name to analyze
|
|
2330
|
+
* @returns Performance statistics with aggregated metrics
|
|
2331
|
+
*
|
|
2332
|
+
* @example
|
|
2333
|
+
* ```typescript
|
|
2334
|
+
* const stats = await Performance.getData("my-strategy");
|
|
2335
|
+
*
|
|
2336
|
+
* // Find slowest operation type
|
|
2337
|
+
* const slowest = Object.values(stats.metricStats)
|
|
2338
|
+
* .sort((a, b) => b.avgDuration - a.avgDuration)[0];
|
|
2339
|
+
* console.log(`Slowest: ${slowest.metricType} (${slowest.avgDuration.toFixed(2)}ms avg)`);
|
|
2340
|
+
*
|
|
2341
|
+
* // Check for outliers
|
|
2342
|
+
* for (const metric of Object.values(stats.metricStats)) {
|
|
2343
|
+
* if (metric.p99 > metric.avgDuration * 5) {
|
|
2344
|
+
* console.warn(`High variance in ${metric.metricType}: P99=${metric.p99}ms, Avg=${metric.avgDuration}ms`);
|
|
2345
|
+
* }
|
|
2346
|
+
* }
|
|
2347
|
+
* ```
|
|
2348
|
+
*/
|
|
2349
|
+
static getData(strategyName: string): Promise<PerformanceStatistics>;
|
|
2350
|
+
/**
|
|
2351
|
+
* Generates markdown report with performance analysis.
|
|
2352
|
+
*
|
|
2353
|
+
* Report includes:
|
|
2354
|
+
* - Time distribution across operation types
|
|
2355
|
+
* - Detailed metrics table with statistics
|
|
2356
|
+
* - Percentile analysis for bottleneck detection
|
|
2357
|
+
*
|
|
2358
|
+
* @param strategyName - Strategy name to generate report for
|
|
2359
|
+
* @returns Markdown formatted report string
|
|
2360
|
+
*
|
|
2361
|
+
* @example
|
|
2362
|
+
* ```typescript
|
|
2363
|
+
* const markdown = await Performance.getReport("my-strategy");
|
|
2364
|
+
* console.log(markdown);
|
|
2365
|
+
*
|
|
2366
|
+
* // Or save to file
|
|
2367
|
+
* import fs from "fs/promises";
|
|
2368
|
+
* await fs.writeFile("performance-report.md", markdown);
|
|
2369
|
+
* ```
|
|
2370
|
+
*/
|
|
2371
|
+
static getReport(strategyName: string): Promise<string>;
|
|
2372
|
+
/**
|
|
2373
|
+
* Saves performance report to disk.
|
|
2374
|
+
*
|
|
2375
|
+
* Creates directory if it doesn't exist.
|
|
2376
|
+
* Default path: ./logs/performance/{strategyName}.md
|
|
2377
|
+
*
|
|
2378
|
+
* @param strategyName - Strategy name to save report for
|
|
2379
|
+
* @param path - Optional custom directory path
|
|
2380
|
+
*
|
|
2381
|
+
* @example
|
|
2382
|
+
* ```typescript
|
|
2383
|
+
* // Save to default path: ./logs/performance/my-strategy.md
|
|
2384
|
+
* await Performance.dump("my-strategy");
|
|
2385
|
+
*
|
|
2386
|
+
* // Save to custom path: ./reports/perf/my-strategy.md
|
|
2387
|
+
* await Performance.dump("my-strategy", "./reports/perf");
|
|
2388
|
+
* ```
|
|
2389
|
+
*/
|
|
2390
|
+
static dump(strategyName: string, path?: string): Promise<void>;
|
|
2391
|
+
/**
|
|
2392
|
+
* Clears accumulated performance metrics from memory.
|
|
2393
|
+
*
|
|
2394
|
+
* @param strategyName - Optional strategy name to clear specific strategy's metrics
|
|
2395
|
+
*
|
|
2396
|
+
* @example
|
|
2397
|
+
* ```typescript
|
|
2398
|
+
* // Clear specific strategy metrics
|
|
2399
|
+
* await Performance.clear("my-strategy");
|
|
2400
|
+
*
|
|
2401
|
+
* // Clear all metrics for all strategies
|
|
2402
|
+
* await Performance.clear();
|
|
2403
|
+
* ```
|
|
2404
|
+
*/
|
|
2405
|
+
static clear(strategyName?: string): Promise<void>;
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2072
2408
|
/**
|
|
2073
2409
|
* Logger service with automatic context injection.
|
|
2074
2410
|
*
|
|
@@ -2778,6 +3114,7 @@ declare class BacktestLogicPrivateService {
|
|
|
2778
3114
|
declare class LiveLogicPrivateService {
|
|
2779
3115
|
private readonly loggerService;
|
|
2780
3116
|
private readonly strategyGlobalService;
|
|
3117
|
+
private readonly methodContextService;
|
|
2781
3118
|
/**
|
|
2782
3119
|
* Runs live trading for a symbol, streaming results as async generator.
|
|
2783
3120
|
*
|
|
@@ -3067,6 +3404,7 @@ declare const backtest: {
|
|
|
3067
3404
|
frameValidationService: FrameValidationService;
|
|
3068
3405
|
backtestMarkdownService: BacktestMarkdownService;
|
|
3069
3406
|
liveMarkdownService: LiveMarkdownService;
|
|
3407
|
+
performanceMarkdownService: PerformanceMarkdownService;
|
|
3070
3408
|
backtestLogicPublicService: BacktestLogicPublicService;
|
|
3071
3409
|
liveLogicPublicService: LiveLogicPublicService;
|
|
3072
3410
|
backtestLogicPrivateService: BacktestLogicPrivateService;
|
|
@@ -3091,4 +3429,4 @@ declare const backtest: {
|
|
|
3091
3429
|
loggerService: LoggerService;
|
|
3092
3430
|
};
|
|
3093
3431
|
|
|
3094
|
-
export { Backtest, type BacktestStatistics, type CandleInterval, type DoneContract, type EntityId, 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, type LiveStatistics, MethodContextService, PersistBase, PersistSignalAdaper, type ProgressContract, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, addExchange, addFrame, addStrategy, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, backtest as lib, listExchanges, listFrames, listStrategies, listenDone, listenDoneOnce, listenError, listenProgress, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, setLogger };
|
|
3432
|
+
export { Backtest, type BacktestStatistics, type CandleInterval, type DoneContract, type EntityId, 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, type LiveStatistics, MethodContextService, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatistics, PersistBase, PersistSignalAdaper, type ProgressContract, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, addExchange, addFrame, addStrategy, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, backtest as lib, listExchanges, listFrames, listStrategies, listenDone, listenDoneOnce, listenError, listenPerformance, listenProgress, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, setLogger };
|