backtest-kit 1.1.5 → 1.1.7
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 +169 -32
- package/build/index.cjs +278 -36
- package/build/index.mjs +278 -36
- package/package.json +1 -1
- package/types.d.ts +448 -264
package/types.d.ts
CHANGED
|
@@ -370,7 +370,7 @@ interface ISignalDto {
|
|
|
370
370
|
/** Human-readable description of signal reason */
|
|
371
371
|
note?: string;
|
|
372
372
|
/** Entry price for the position */
|
|
373
|
-
priceOpen
|
|
373
|
+
priceOpen?: number;
|
|
374
374
|
/** Take profit target price (must be > priceOpen for long, < priceOpen for short) */
|
|
375
375
|
priceTakeProfit: number;
|
|
376
376
|
/** Stop loss exit price (must be < priceOpen for long, > priceOpen for short) */
|
|
@@ -385,6 +385,8 @@ interface ISignalDto {
|
|
|
385
385
|
interface ISignalRow extends ISignalDto {
|
|
386
386
|
/** Unique signal identifier (UUID v4 auto-generated) */
|
|
387
387
|
id: string;
|
|
388
|
+
/** Entry price for the position */
|
|
389
|
+
priceOpen: number;
|
|
388
390
|
/** Unique exchange identifier for execution */
|
|
389
391
|
exchangeName: ExchangeName;
|
|
390
392
|
/** Unique strategy identifier for execution */
|
|
@@ -597,8 +599,8 @@ type StrategyName = string;
|
|
|
597
599
|
* timestamp: Date.now(),
|
|
598
600
|
* }),
|
|
599
601
|
* callbacks: {
|
|
600
|
-
* onOpen: (
|
|
601
|
-
* onClose: (
|
|
602
|
+
* onOpen: (symbol, signal, currentPrice, backtest) => console.log("Signal opened"),
|
|
603
|
+
* onClose: (symbol, signal, priceClose, backtest) => console.log("Signal closed"),
|
|
602
604
|
* },
|
|
603
605
|
* });
|
|
604
606
|
* ```
|
|
@@ -1178,15 +1180,422 @@ declare function getDate(): Promise<Date>;
|
|
|
1178
1180
|
*/
|
|
1179
1181
|
declare function getMode(): Promise<"backtest" | "live">;
|
|
1180
1182
|
|
|
1183
|
+
/**
|
|
1184
|
+
* Statistical data calculated from backtest results.
|
|
1185
|
+
*
|
|
1186
|
+
* All numeric values are null if calculation is unsafe (NaN, Infinity, etc).
|
|
1187
|
+
* Provides comprehensive metrics for strategy performance analysis.
|
|
1188
|
+
*
|
|
1189
|
+
* @example
|
|
1190
|
+
* ```typescript
|
|
1191
|
+
* const stats = await Backtest.getData("my-strategy");
|
|
1192
|
+
*
|
|
1193
|
+
* console.log(`Total signals: ${stats.totalSignals}`);
|
|
1194
|
+
* console.log(`Win rate: ${stats.winRate}%`);
|
|
1195
|
+
* console.log(`Sharpe Ratio: ${stats.sharpeRatio}`);
|
|
1196
|
+
*
|
|
1197
|
+
* // Access raw signal data
|
|
1198
|
+
* stats.signalList.forEach(signal => {
|
|
1199
|
+
* console.log(`Signal ${signal.signal.id}: ${signal.pnl.pnlPercentage}%`);
|
|
1200
|
+
* });
|
|
1201
|
+
* ```
|
|
1202
|
+
*/
|
|
1203
|
+
interface BacktestStatistics {
|
|
1204
|
+
/** Array of all closed signals with full details (price, PNL, timestamps, etc.) */
|
|
1205
|
+
signalList: IStrategyTickResultClosed[];
|
|
1206
|
+
/** Total number of closed signals */
|
|
1207
|
+
totalSignals: number;
|
|
1208
|
+
/** Number of winning signals (PNL > 0) */
|
|
1209
|
+
winCount: number;
|
|
1210
|
+
/** Number of losing signals (PNL < 0) */
|
|
1211
|
+
lossCount: number;
|
|
1212
|
+
/** Win rate as percentage (0-100), null if unsafe. Higher is better. */
|
|
1213
|
+
winRate: number | null;
|
|
1214
|
+
/** Average PNL per signal as percentage, null if unsafe. Higher is better. */
|
|
1215
|
+
avgPnl: number | null;
|
|
1216
|
+
/** Cumulative PNL across all signals as percentage, null if unsafe. Higher is better. */
|
|
1217
|
+
totalPnl: number | null;
|
|
1218
|
+
/** Standard deviation of returns (volatility metric), null if unsafe. Lower is better. */
|
|
1219
|
+
stdDev: number | null;
|
|
1220
|
+
/** Sharpe Ratio (risk-adjusted return = avgPnl / stdDev), null if unsafe. Higher is better. */
|
|
1221
|
+
sharpeRatio: number | null;
|
|
1222
|
+
/** Annualized Sharpe Ratio (sharpeRatio × √365), null if unsafe. Higher is better. */
|
|
1223
|
+
annualizedSharpeRatio: number | null;
|
|
1224
|
+
/** Certainty Ratio (avgWin / |avgLoss|), null if unsafe. Higher is better. */
|
|
1225
|
+
certaintyRatio: number | null;
|
|
1226
|
+
/** Expected yearly returns based on average trade duration and PNL, null if unsafe. Higher is better. */
|
|
1227
|
+
expectedYearlyReturns: number | null;
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Service for generating and saving backtest markdown reports.
|
|
1231
|
+
*
|
|
1232
|
+
* Features:
|
|
1233
|
+
* - Listens to signal events via onTick callback
|
|
1234
|
+
* - Accumulates closed signals per strategy using memoized storage
|
|
1235
|
+
* - Generates markdown tables with detailed signal information
|
|
1236
|
+
* - Saves reports to disk in logs/backtest/{strategyName}.md
|
|
1237
|
+
*
|
|
1238
|
+
* @example
|
|
1239
|
+
* ```typescript
|
|
1240
|
+
* const service = new BacktestMarkdownService();
|
|
1241
|
+
*
|
|
1242
|
+
* // Add to strategy callbacks
|
|
1243
|
+
* addStrategy({
|
|
1244
|
+
* strategyName: "my-strategy",
|
|
1245
|
+
* callbacks: {
|
|
1246
|
+
* onTick: (symbol, result, backtest) => {
|
|
1247
|
+
* service.tick(result);
|
|
1248
|
+
* }
|
|
1249
|
+
* }
|
|
1250
|
+
* });
|
|
1251
|
+
*
|
|
1252
|
+
* // After backtest, generate and save report
|
|
1253
|
+
* await service.saveReport("my-strategy");
|
|
1254
|
+
* ```
|
|
1255
|
+
*/
|
|
1256
|
+
declare class BacktestMarkdownService {
|
|
1257
|
+
/** Logger service for debug output */
|
|
1258
|
+
private readonly loggerService;
|
|
1259
|
+
/**
|
|
1260
|
+
* Memoized function to get or create ReportStorage for a strategy.
|
|
1261
|
+
* Each strategy gets its own isolated storage instance.
|
|
1262
|
+
*/
|
|
1263
|
+
private getStorage;
|
|
1264
|
+
/**
|
|
1265
|
+
* Processes tick events and accumulates closed signals.
|
|
1266
|
+
* Should be called from IStrategyCallbacks.onTick.
|
|
1267
|
+
*
|
|
1268
|
+
* Only processes closed signals - opened signals are ignored.
|
|
1269
|
+
*
|
|
1270
|
+
* @param data - Tick result from strategy execution (opened or closed)
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* ```typescript
|
|
1274
|
+
* const service = new BacktestMarkdownService();
|
|
1275
|
+
*
|
|
1276
|
+
* callbacks: {
|
|
1277
|
+
* onTick: (symbol, result, backtest) => {
|
|
1278
|
+
* service.tick(result);
|
|
1279
|
+
* }
|
|
1280
|
+
* }
|
|
1281
|
+
* ```
|
|
1282
|
+
*/
|
|
1283
|
+
private tick;
|
|
1284
|
+
/**
|
|
1285
|
+
* Gets statistical data from all closed signals for a strategy.
|
|
1286
|
+
* Delegates to ReportStorage.getData().
|
|
1287
|
+
*
|
|
1288
|
+
* @param strategyName - Strategy name to get data for
|
|
1289
|
+
* @returns Statistical data object with all metrics
|
|
1290
|
+
*
|
|
1291
|
+
* @example
|
|
1292
|
+
* ```typescript
|
|
1293
|
+
* const service = new BacktestMarkdownService();
|
|
1294
|
+
* const stats = await service.getData("my-strategy");
|
|
1295
|
+
* console.log(stats.sharpeRatio, stats.winRate);
|
|
1296
|
+
* ```
|
|
1297
|
+
*/
|
|
1298
|
+
getData: (strategyName: StrategyName) => Promise<BacktestStatistics>;
|
|
1299
|
+
/**
|
|
1300
|
+
* Generates markdown report with all closed signals for a strategy.
|
|
1301
|
+
* Delegates to ReportStorage.generateReport().
|
|
1302
|
+
*
|
|
1303
|
+
* @param strategyName - Strategy name to generate report for
|
|
1304
|
+
* @returns Markdown formatted report string with table of all closed signals
|
|
1305
|
+
*
|
|
1306
|
+
* @example
|
|
1307
|
+
* ```typescript
|
|
1308
|
+
* const service = new BacktestMarkdownService();
|
|
1309
|
+
* const markdown = await service.getReport("my-strategy");
|
|
1310
|
+
* console.log(markdown);
|
|
1311
|
+
* ```
|
|
1312
|
+
*/
|
|
1313
|
+
getReport: (strategyName: StrategyName) => Promise<string>;
|
|
1314
|
+
/**
|
|
1315
|
+
* Saves strategy report to disk.
|
|
1316
|
+
* Creates directory if it doesn't exist.
|
|
1317
|
+
* Delegates to ReportStorage.dump().
|
|
1318
|
+
*
|
|
1319
|
+
* @param strategyName - Strategy name to save report for
|
|
1320
|
+
* @param path - Directory path to save report (default: "./logs/backtest")
|
|
1321
|
+
*
|
|
1322
|
+
* @example
|
|
1323
|
+
* ```typescript
|
|
1324
|
+
* const service = new BacktestMarkdownService();
|
|
1325
|
+
*
|
|
1326
|
+
* // Save to default path: ./logs/backtest/my-strategy.md
|
|
1327
|
+
* await service.dump("my-strategy");
|
|
1328
|
+
*
|
|
1329
|
+
* // Save to custom path: ./custom/path/my-strategy.md
|
|
1330
|
+
* await service.dump("my-strategy", "./custom/path");
|
|
1331
|
+
* ```
|
|
1332
|
+
*/
|
|
1333
|
+
dump: (strategyName: StrategyName, path?: string) => Promise<void>;
|
|
1334
|
+
/**
|
|
1335
|
+
* Clears accumulated signal data from storage.
|
|
1336
|
+
* If strategyName is provided, clears only that strategy's data.
|
|
1337
|
+
* If strategyName is omitted, clears all strategies' data.
|
|
1338
|
+
*
|
|
1339
|
+
* @param strategyName - Optional strategy name to clear specific strategy data
|
|
1340
|
+
*
|
|
1341
|
+
* @example
|
|
1342
|
+
* ```typescript
|
|
1343
|
+
* const service = new BacktestMarkdownService();
|
|
1344
|
+
*
|
|
1345
|
+
* // Clear specific strategy data
|
|
1346
|
+
* await service.clear("my-strategy");
|
|
1347
|
+
*
|
|
1348
|
+
* // Clear all strategies' data
|
|
1349
|
+
* await service.clear();
|
|
1350
|
+
* ```
|
|
1351
|
+
*/
|
|
1352
|
+
clear: (strategyName?: StrategyName) => Promise<void>;
|
|
1353
|
+
/**
|
|
1354
|
+
* Initializes the service by subscribing to backtest signal events.
|
|
1355
|
+
* Uses singleshot to ensure initialization happens only once.
|
|
1356
|
+
* Automatically called on first use.
|
|
1357
|
+
*
|
|
1358
|
+
* @example
|
|
1359
|
+
* ```typescript
|
|
1360
|
+
* const service = new BacktestMarkdownService();
|
|
1361
|
+
* await service.init(); // Subscribe to backtest events
|
|
1362
|
+
* ```
|
|
1363
|
+
*/
|
|
1364
|
+
protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
/**
|
|
1368
|
+
* Unified tick event data for report generation.
|
|
1369
|
+
* Contains all information about a tick event regardless of action type.
|
|
1370
|
+
*/
|
|
1371
|
+
interface TickEvent {
|
|
1372
|
+
/** Event timestamp in milliseconds */
|
|
1373
|
+
timestamp: number;
|
|
1374
|
+
/** Event action type */
|
|
1375
|
+
action: "idle" | "opened" | "active" | "closed";
|
|
1376
|
+
/** Trading pair symbol (only for non-idle events) */
|
|
1377
|
+
symbol?: string;
|
|
1378
|
+
/** Signal ID (only for opened/active/closed) */
|
|
1379
|
+
signalId?: string;
|
|
1380
|
+
/** Position type (only for opened/active/closed) */
|
|
1381
|
+
position?: string;
|
|
1382
|
+
/** Signal note (only for opened/active/closed) */
|
|
1383
|
+
note?: string;
|
|
1384
|
+
/** Current price */
|
|
1385
|
+
currentPrice: number;
|
|
1386
|
+
/** Open price (only for opened/active/closed) */
|
|
1387
|
+
openPrice?: number;
|
|
1388
|
+
/** Take profit price (only for opened/active/closed) */
|
|
1389
|
+
takeProfit?: number;
|
|
1390
|
+
/** Stop loss price (only for opened/active/closed) */
|
|
1391
|
+
stopLoss?: number;
|
|
1392
|
+
/** PNL percentage (only for closed) */
|
|
1393
|
+
pnl?: number;
|
|
1394
|
+
/** Close reason (only for closed) */
|
|
1395
|
+
closeReason?: string;
|
|
1396
|
+
/** Duration in minutes (only for closed) */
|
|
1397
|
+
duration?: number;
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* Statistical data calculated from live trading results.
|
|
1401
|
+
*
|
|
1402
|
+
* All numeric values are null if calculation is unsafe (NaN, Infinity, etc).
|
|
1403
|
+
* Provides comprehensive metrics for live trading performance analysis.
|
|
1404
|
+
*
|
|
1405
|
+
* @example
|
|
1406
|
+
* ```typescript
|
|
1407
|
+
* const stats = await Live.getData("my-strategy");
|
|
1408
|
+
*
|
|
1409
|
+
* console.log(`Total events: ${stats.totalEvents}`);
|
|
1410
|
+
* console.log(`Closed signals: ${stats.totalClosed}`);
|
|
1411
|
+
* console.log(`Win rate: ${stats.winRate}%`);
|
|
1412
|
+
* console.log(`Sharpe Ratio: ${stats.sharpeRatio}`);
|
|
1413
|
+
*
|
|
1414
|
+
* // Access raw event data (includes idle, opened, active, closed)
|
|
1415
|
+
* stats.eventList.forEach(event => {
|
|
1416
|
+
* if (event.action === "closed") {
|
|
1417
|
+
* console.log(`Closed signal: ${event.pnl}%`);
|
|
1418
|
+
* }
|
|
1419
|
+
* });
|
|
1420
|
+
* ```
|
|
1421
|
+
*/
|
|
1422
|
+
interface LiveStatistics {
|
|
1423
|
+
/** Array of all events (idle, opened, active, closed) with full details */
|
|
1424
|
+
eventList: TickEvent[];
|
|
1425
|
+
/** Total number of all events (includes idle, opened, active, closed) */
|
|
1426
|
+
totalEvents: number;
|
|
1427
|
+
/** Total number of closed signals only */
|
|
1428
|
+
totalClosed: number;
|
|
1429
|
+
/** Number of winning closed signals (PNL > 0) */
|
|
1430
|
+
winCount: number;
|
|
1431
|
+
/** Number of losing closed signals (PNL < 0) */
|
|
1432
|
+
lossCount: number;
|
|
1433
|
+
/** Win rate as percentage (0-100) based on closed signals, null if unsafe. Higher is better. */
|
|
1434
|
+
winRate: number | null;
|
|
1435
|
+
/** Average PNL per closed signal as percentage, null if unsafe. Higher is better. */
|
|
1436
|
+
avgPnl: number | null;
|
|
1437
|
+
/** Cumulative PNL across all closed signals as percentage, null if unsafe. Higher is better. */
|
|
1438
|
+
totalPnl: number | null;
|
|
1439
|
+
/** Standard deviation of returns (volatility metric), null if unsafe. Lower is better. */
|
|
1440
|
+
stdDev: number | null;
|
|
1441
|
+
/** Sharpe Ratio (risk-adjusted return = avgPnl / stdDev), null if unsafe. Higher is better. */
|
|
1442
|
+
sharpeRatio: number | null;
|
|
1443
|
+
/** Annualized Sharpe Ratio (sharpeRatio × √365), null if unsafe. Higher is better. */
|
|
1444
|
+
annualizedSharpeRatio: number | null;
|
|
1445
|
+
/** Certainty Ratio (avgWin / |avgLoss|), null if unsafe. Higher is better. */
|
|
1446
|
+
certaintyRatio: number | null;
|
|
1447
|
+
/** Expected yearly returns based on average trade duration and PNL, null if unsafe. Higher is better. */
|
|
1448
|
+
expectedYearlyReturns: number | null;
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Service for generating and saving live trading markdown reports.
|
|
1452
|
+
*
|
|
1453
|
+
* Features:
|
|
1454
|
+
* - Listens to all signal events via onTick callback
|
|
1455
|
+
* - Accumulates all events (idle, opened, active, closed) per strategy
|
|
1456
|
+
* - Generates markdown tables with detailed event information
|
|
1457
|
+
* - Provides trading statistics (win rate, average PNL)
|
|
1458
|
+
* - Saves reports to disk in logs/live/{strategyName}.md
|
|
1459
|
+
*
|
|
1460
|
+
* @example
|
|
1461
|
+
* ```typescript
|
|
1462
|
+
* const service = new LiveMarkdownService();
|
|
1463
|
+
*
|
|
1464
|
+
* // Add to strategy callbacks
|
|
1465
|
+
* addStrategy({
|
|
1466
|
+
* strategyName: "my-strategy",
|
|
1467
|
+
* callbacks: {
|
|
1468
|
+
* onTick: (symbol, result, backtest) => {
|
|
1469
|
+
* if (!backtest) {
|
|
1470
|
+
* service.tick(result);
|
|
1471
|
+
* }
|
|
1472
|
+
* }
|
|
1473
|
+
* }
|
|
1474
|
+
* });
|
|
1475
|
+
*
|
|
1476
|
+
* // Later: generate and save report
|
|
1477
|
+
* await service.dump("my-strategy");
|
|
1478
|
+
* ```
|
|
1479
|
+
*/
|
|
1480
|
+
declare class LiveMarkdownService {
|
|
1481
|
+
/** Logger service for debug output */
|
|
1482
|
+
private readonly loggerService;
|
|
1483
|
+
/**
|
|
1484
|
+
* Memoized function to get or create ReportStorage for a strategy.
|
|
1485
|
+
* Each strategy gets its own isolated storage instance.
|
|
1486
|
+
*/
|
|
1487
|
+
private getStorage;
|
|
1488
|
+
/**
|
|
1489
|
+
* Processes tick events and accumulates all event types.
|
|
1490
|
+
* Should be called from IStrategyCallbacks.onTick.
|
|
1491
|
+
*
|
|
1492
|
+
* Processes all event types: idle, opened, active, closed.
|
|
1493
|
+
*
|
|
1494
|
+
* @param data - Tick result from strategy execution
|
|
1495
|
+
*
|
|
1496
|
+
* @example
|
|
1497
|
+
* ```typescript
|
|
1498
|
+
* const service = new LiveMarkdownService();
|
|
1499
|
+
*
|
|
1500
|
+
* callbacks: {
|
|
1501
|
+
* onTick: (symbol, result, backtest) => {
|
|
1502
|
+
* if (!backtest) {
|
|
1503
|
+
* service.tick(result);
|
|
1504
|
+
* }
|
|
1505
|
+
* }
|
|
1506
|
+
* }
|
|
1507
|
+
* ```
|
|
1508
|
+
*/
|
|
1509
|
+
private tick;
|
|
1510
|
+
/**
|
|
1511
|
+
* Gets statistical data from all live trading events for a strategy.
|
|
1512
|
+
* Delegates to ReportStorage.getData().
|
|
1513
|
+
*
|
|
1514
|
+
* @param strategyName - Strategy name to get data for
|
|
1515
|
+
* @returns Statistical data object with all metrics
|
|
1516
|
+
*
|
|
1517
|
+
* @example
|
|
1518
|
+
* ```typescript
|
|
1519
|
+
* const service = new LiveMarkdownService();
|
|
1520
|
+
* const stats = await service.getData("my-strategy");
|
|
1521
|
+
* console.log(stats.sharpeRatio, stats.winRate);
|
|
1522
|
+
* ```
|
|
1523
|
+
*/
|
|
1524
|
+
getData: (strategyName: StrategyName) => Promise<LiveStatistics>;
|
|
1525
|
+
/**
|
|
1526
|
+
* Generates markdown report with all events for a strategy.
|
|
1527
|
+
* Delegates to ReportStorage.getReport().
|
|
1528
|
+
*
|
|
1529
|
+
* @param strategyName - Strategy name to generate report for
|
|
1530
|
+
* @returns Markdown formatted report string with table of all events
|
|
1531
|
+
*
|
|
1532
|
+
* @example
|
|
1533
|
+
* ```typescript
|
|
1534
|
+
* const service = new LiveMarkdownService();
|
|
1535
|
+
* const markdown = await service.getReport("my-strategy");
|
|
1536
|
+
* console.log(markdown);
|
|
1537
|
+
* ```
|
|
1538
|
+
*/
|
|
1539
|
+
getReport: (strategyName: StrategyName) => Promise<string>;
|
|
1540
|
+
/**
|
|
1541
|
+
* Saves strategy report to disk.
|
|
1542
|
+
* Creates directory if it doesn't exist.
|
|
1543
|
+
* Delegates to ReportStorage.dump().
|
|
1544
|
+
*
|
|
1545
|
+
* @param strategyName - Strategy name to save report for
|
|
1546
|
+
* @param path - Directory path to save report (default: "./logs/live")
|
|
1547
|
+
*
|
|
1548
|
+
* @example
|
|
1549
|
+
* ```typescript
|
|
1550
|
+
* const service = new LiveMarkdownService();
|
|
1551
|
+
*
|
|
1552
|
+
* // Save to default path: ./logs/live/my-strategy.md
|
|
1553
|
+
* await service.dump("my-strategy");
|
|
1554
|
+
*
|
|
1555
|
+
* // Save to custom path: ./custom/path/my-strategy.md
|
|
1556
|
+
* await service.dump("my-strategy", "./custom/path");
|
|
1557
|
+
* ```
|
|
1558
|
+
*/
|
|
1559
|
+
dump: (strategyName: StrategyName, path?: string) => Promise<void>;
|
|
1560
|
+
/**
|
|
1561
|
+
* Clears accumulated event data from storage.
|
|
1562
|
+
* If strategyName is provided, clears only that strategy's data.
|
|
1563
|
+
* If strategyName is omitted, clears all strategies' data.
|
|
1564
|
+
*
|
|
1565
|
+
* @param strategyName - Optional strategy name to clear specific strategy data
|
|
1566
|
+
*
|
|
1567
|
+
* @example
|
|
1568
|
+
* ```typescript
|
|
1569
|
+
* const service = new LiveMarkdownService();
|
|
1570
|
+
*
|
|
1571
|
+
* // Clear specific strategy data
|
|
1572
|
+
* await service.clear("my-strategy");
|
|
1573
|
+
*
|
|
1574
|
+
* // Clear all strategies' data
|
|
1575
|
+
* await service.clear();
|
|
1576
|
+
* ```
|
|
1577
|
+
*/
|
|
1578
|
+
clear: (strategyName?: StrategyName) => Promise<void>;
|
|
1579
|
+
/**
|
|
1580
|
+
* Initializes the service by subscribing to live signal events.
|
|
1581
|
+
* Uses singleshot to ensure initialization happens only once.
|
|
1582
|
+
* Automatically called on first use.
|
|
1583
|
+
*
|
|
1584
|
+
* @example
|
|
1585
|
+
* ```typescript
|
|
1586
|
+
* const service = new LiveMarkdownService();
|
|
1587
|
+
* await service.init(); // Subscribe to live events
|
|
1588
|
+
* ```
|
|
1589
|
+
*/
|
|
1590
|
+
protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1181
1593
|
declare const BASE_WAIT_FOR_INIT_SYMBOL: unique symbol;
|
|
1182
1594
|
/**
|
|
1183
1595
|
* Signal data stored in persistence layer.
|
|
1184
1596
|
* Contains nullable signal for atomic updates.
|
|
1185
1597
|
*/
|
|
1186
|
-
|
|
1187
|
-
/** Current signal state (null when no active signal) */
|
|
1188
|
-
signalRow: ISignalRow | null;
|
|
1189
|
-
}
|
|
1598
|
+
type SignalData = ISignalRow | null;
|
|
1190
1599
|
/**
|
|
1191
1600
|
* Type helper for PersistBase instance.
|
|
1192
1601
|
*/
|
|
@@ -1367,7 +1776,7 @@ declare class PersistSignalUtils {
|
|
|
1367
1776
|
* PersistSignalAdaper.usePersistSignalAdapter(RedisPersist);
|
|
1368
1777
|
* ```
|
|
1369
1778
|
*/
|
|
1370
|
-
usePersistSignalAdapter(Ctor: TPersistBaseCtor<StrategyName,
|
|
1779
|
+
usePersistSignalAdapter(Ctor: TPersistBaseCtor<StrategyName, SignalData>): void;
|
|
1371
1780
|
/**
|
|
1372
1781
|
* Reads persisted signal data for a strategy and symbol.
|
|
1373
1782
|
*
|
|
@@ -1468,6 +1877,19 @@ declare class BacktestUtils {
|
|
|
1468
1877
|
exchangeName: string;
|
|
1469
1878
|
frameName: string;
|
|
1470
1879
|
}) => () => void;
|
|
1880
|
+
/**
|
|
1881
|
+
* Gets statistical data from all closed signals for a strategy.
|
|
1882
|
+
*
|
|
1883
|
+
* @param strategyName - Strategy name to get data for
|
|
1884
|
+
* @returns Promise resolving to statistical data object
|
|
1885
|
+
*
|
|
1886
|
+
* @example
|
|
1887
|
+
* ```typescript
|
|
1888
|
+
* const stats = await Backtest.getData("my-strategy");
|
|
1889
|
+
* console.log(stats.sharpeRatio, stats.winRate);
|
|
1890
|
+
* ```
|
|
1891
|
+
*/
|
|
1892
|
+
getData: (strategyName: StrategyName) => Promise<BacktestStatistics>;
|
|
1471
1893
|
/**
|
|
1472
1894
|
* Generates markdown report with all closed signals for a strategy.
|
|
1473
1895
|
*
|
|
@@ -1583,10 +2005,23 @@ declare class LiveUtils {
|
|
|
1583
2005
|
* });
|
|
1584
2006
|
* ```
|
|
1585
2007
|
*/
|
|
1586
|
-
background: (symbol: string, context: {
|
|
1587
|
-
strategyName: string;
|
|
1588
|
-
exchangeName: string;
|
|
1589
|
-
}) => () => void;
|
|
2008
|
+
background: (symbol: string, context: {
|
|
2009
|
+
strategyName: string;
|
|
2010
|
+
exchangeName: string;
|
|
2011
|
+
}) => () => void;
|
|
2012
|
+
/**
|
|
2013
|
+
* Gets statistical data from all live trading events for a strategy.
|
|
2014
|
+
*
|
|
2015
|
+
* @param strategyName - Strategy name to get data for
|
|
2016
|
+
* @returns Promise resolving to statistical data object
|
|
2017
|
+
*
|
|
2018
|
+
* @example
|
|
2019
|
+
* ```typescript
|
|
2020
|
+
* const stats = await Live.getData("my-strategy");
|
|
2021
|
+
* console.log(stats.sharpeRatio, stats.winRate);
|
|
2022
|
+
* ```
|
|
2023
|
+
*/
|
|
2024
|
+
getData: (strategyName: StrategyName) => Promise<LiveStatistics>;
|
|
1590
2025
|
/**
|
|
1591
2026
|
* Generates markdown report with all events for a strategy.
|
|
1592
2027
|
*
|
|
@@ -2515,257 +2950,6 @@ declare class BacktestGlobalService {
|
|
|
2515
2950
|
}) => AsyncGenerator<IStrategyTickResultClosed, void, unknown>;
|
|
2516
2951
|
}
|
|
2517
2952
|
|
|
2518
|
-
/**
|
|
2519
|
-
* Service for generating and saving backtest markdown reports.
|
|
2520
|
-
*
|
|
2521
|
-
* Features:
|
|
2522
|
-
* - Listens to signal events via onTick callback
|
|
2523
|
-
* - Accumulates closed signals per strategy using memoized storage
|
|
2524
|
-
* - Generates markdown tables with detailed signal information
|
|
2525
|
-
* - Saves reports to disk in logs/backtest/{strategyName}.md
|
|
2526
|
-
*
|
|
2527
|
-
* @example
|
|
2528
|
-
* ```typescript
|
|
2529
|
-
* const service = new BacktestMarkdownService();
|
|
2530
|
-
*
|
|
2531
|
-
* // Add to strategy callbacks
|
|
2532
|
-
* addStrategy({
|
|
2533
|
-
* strategyName: "my-strategy",
|
|
2534
|
-
* callbacks: {
|
|
2535
|
-
* onTick: (symbol, result, backtest) => {
|
|
2536
|
-
* service.tick(result);
|
|
2537
|
-
* }
|
|
2538
|
-
* }
|
|
2539
|
-
* });
|
|
2540
|
-
*
|
|
2541
|
-
* // After backtest, generate and save report
|
|
2542
|
-
* await service.saveReport("my-strategy");
|
|
2543
|
-
* ```
|
|
2544
|
-
*/
|
|
2545
|
-
declare class BacktestMarkdownService {
|
|
2546
|
-
/** Logger service for debug output */
|
|
2547
|
-
private readonly loggerService;
|
|
2548
|
-
/**
|
|
2549
|
-
* Memoized function to get or create ReportStorage for a strategy.
|
|
2550
|
-
* Each strategy gets its own isolated storage instance.
|
|
2551
|
-
*/
|
|
2552
|
-
private getStorage;
|
|
2553
|
-
/**
|
|
2554
|
-
* Processes tick events and accumulates closed signals.
|
|
2555
|
-
* Should be called from IStrategyCallbacks.onTick.
|
|
2556
|
-
*
|
|
2557
|
-
* Only processes closed signals - opened signals are ignored.
|
|
2558
|
-
*
|
|
2559
|
-
* @param data - Tick result from strategy execution (opened or closed)
|
|
2560
|
-
*
|
|
2561
|
-
* @example
|
|
2562
|
-
* ```typescript
|
|
2563
|
-
* const service = new BacktestMarkdownService();
|
|
2564
|
-
*
|
|
2565
|
-
* callbacks: {
|
|
2566
|
-
* onTick: (symbol, result, backtest) => {
|
|
2567
|
-
* service.tick(result);
|
|
2568
|
-
* }
|
|
2569
|
-
* }
|
|
2570
|
-
* ```
|
|
2571
|
-
*/
|
|
2572
|
-
private tick;
|
|
2573
|
-
/**
|
|
2574
|
-
* Generates markdown report with all closed signals for a strategy.
|
|
2575
|
-
* Delegates to ReportStorage.generateReport().
|
|
2576
|
-
*
|
|
2577
|
-
* @param strategyName - Strategy name to generate report for
|
|
2578
|
-
* @returns Markdown formatted report string with table of all closed signals
|
|
2579
|
-
*
|
|
2580
|
-
* @example
|
|
2581
|
-
* ```typescript
|
|
2582
|
-
* const service = new BacktestMarkdownService();
|
|
2583
|
-
* const markdown = service.generateReport("my-strategy");
|
|
2584
|
-
* console.log(markdown);
|
|
2585
|
-
* ```
|
|
2586
|
-
*/
|
|
2587
|
-
getReport: (strategyName: StrategyName) => Promise<string>;
|
|
2588
|
-
/**
|
|
2589
|
-
* Saves strategy report to disk.
|
|
2590
|
-
* Creates directory if it doesn't exist.
|
|
2591
|
-
* Delegates to ReportStorage.dump().
|
|
2592
|
-
*
|
|
2593
|
-
* @param strategyName - Strategy name to save report for
|
|
2594
|
-
* @param path - Directory path to save report (default: "./logs/backtest")
|
|
2595
|
-
*
|
|
2596
|
-
* @example
|
|
2597
|
-
* ```typescript
|
|
2598
|
-
* const service = new BacktestMarkdownService();
|
|
2599
|
-
*
|
|
2600
|
-
* // Save to default path: ./logs/backtest/my-strategy.md
|
|
2601
|
-
* await service.dump("my-strategy");
|
|
2602
|
-
*
|
|
2603
|
-
* // Save to custom path: ./custom/path/my-strategy.md
|
|
2604
|
-
* await service.dump("my-strategy", "./custom/path");
|
|
2605
|
-
* ```
|
|
2606
|
-
*/
|
|
2607
|
-
dump: (strategyName: StrategyName, path?: string) => Promise<void>;
|
|
2608
|
-
/**
|
|
2609
|
-
* Clears accumulated signal data from storage.
|
|
2610
|
-
* If strategyName is provided, clears only that strategy's data.
|
|
2611
|
-
* If strategyName is omitted, clears all strategies' data.
|
|
2612
|
-
*
|
|
2613
|
-
* @param strategyName - Optional strategy name to clear specific strategy data
|
|
2614
|
-
*
|
|
2615
|
-
* @example
|
|
2616
|
-
* ```typescript
|
|
2617
|
-
* const service = new BacktestMarkdownService();
|
|
2618
|
-
*
|
|
2619
|
-
* // Clear specific strategy data
|
|
2620
|
-
* await service.clear("my-strategy");
|
|
2621
|
-
*
|
|
2622
|
-
* // Clear all strategies' data
|
|
2623
|
-
* await service.clear();
|
|
2624
|
-
* ```
|
|
2625
|
-
*/
|
|
2626
|
-
clear: (strategyName?: StrategyName) => Promise<void>;
|
|
2627
|
-
/**
|
|
2628
|
-
* Initializes the service by subscribing to backtest signal events.
|
|
2629
|
-
* Uses singleshot to ensure initialization happens only once.
|
|
2630
|
-
* Automatically called on first use.
|
|
2631
|
-
*
|
|
2632
|
-
* @example
|
|
2633
|
-
* ```typescript
|
|
2634
|
-
* const service = new BacktestMarkdownService();
|
|
2635
|
-
* await service.init(); // Subscribe to backtest events
|
|
2636
|
-
* ```
|
|
2637
|
-
*/
|
|
2638
|
-
protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
|
-
/**
|
|
2642
|
-
* Service for generating and saving live trading markdown reports.
|
|
2643
|
-
*
|
|
2644
|
-
* Features:
|
|
2645
|
-
* - Listens to all signal events via onTick callback
|
|
2646
|
-
* - Accumulates all events (idle, opened, active, closed) per strategy
|
|
2647
|
-
* - Generates markdown tables with detailed event information
|
|
2648
|
-
* - Provides trading statistics (win rate, average PNL)
|
|
2649
|
-
* - Saves reports to disk in logs/live/{strategyName}.md
|
|
2650
|
-
*
|
|
2651
|
-
* @example
|
|
2652
|
-
* ```typescript
|
|
2653
|
-
* const service = new LiveMarkdownService();
|
|
2654
|
-
*
|
|
2655
|
-
* // Add to strategy callbacks
|
|
2656
|
-
* addStrategy({
|
|
2657
|
-
* strategyName: "my-strategy",
|
|
2658
|
-
* callbacks: {
|
|
2659
|
-
* onTick: (symbol, result, backtest) => {
|
|
2660
|
-
* if (!backtest) {
|
|
2661
|
-
* service.tick(result);
|
|
2662
|
-
* }
|
|
2663
|
-
* }
|
|
2664
|
-
* }
|
|
2665
|
-
* });
|
|
2666
|
-
*
|
|
2667
|
-
* // Later: generate and save report
|
|
2668
|
-
* await service.dump("my-strategy");
|
|
2669
|
-
* ```
|
|
2670
|
-
*/
|
|
2671
|
-
declare class LiveMarkdownService {
|
|
2672
|
-
/** Logger service for debug output */
|
|
2673
|
-
private readonly loggerService;
|
|
2674
|
-
/**
|
|
2675
|
-
* Memoized function to get or create ReportStorage for a strategy.
|
|
2676
|
-
* Each strategy gets its own isolated storage instance.
|
|
2677
|
-
*/
|
|
2678
|
-
private getStorage;
|
|
2679
|
-
/**
|
|
2680
|
-
* Processes tick events and accumulates all event types.
|
|
2681
|
-
* Should be called from IStrategyCallbacks.onTick.
|
|
2682
|
-
*
|
|
2683
|
-
* Processes all event types: idle, opened, active, closed.
|
|
2684
|
-
*
|
|
2685
|
-
* @param data - Tick result from strategy execution
|
|
2686
|
-
*
|
|
2687
|
-
* @example
|
|
2688
|
-
* ```typescript
|
|
2689
|
-
* const service = new LiveMarkdownService();
|
|
2690
|
-
*
|
|
2691
|
-
* callbacks: {
|
|
2692
|
-
* onTick: (symbol, result, backtest) => {
|
|
2693
|
-
* if (!backtest) {
|
|
2694
|
-
* service.tick(result);
|
|
2695
|
-
* }
|
|
2696
|
-
* }
|
|
2697
|
-
* }
|
|
2698
|
-
* ```
|
|
2699
|
-
*/
|
|
2700
|
-
private tick;
|
|
2701
|
-
/**
|
|
2702
|
-
* Generates markdown report with all events for a strategy.
|
|
2703
|
-
* Delegates to ReportStorage.getReport().
|
|
2704
|
-
*
|
|
2705
|
-
* @param strategyName - Strategy name to generate report for
|
|
2706
|
-
* @returns Markdown formatted report string with table of all events
|
|
2707
|
-
*
|
|
2708
|
-
* @example
|
|
2709
|
-
* ```typescript
|
|
2710
|
-
* const service = new LiveMarkdownService();
|
|
2711
|
-
* const markdown = await service.getReport("my-strategy");
|
|
2712
|
-
* console.log(markdown);
|
|
2713
|
-
* ```
|
|
2714
|
-
*/
|
|
2715
|
-
getReport: (strategyName: StrategyName) => Promise<string>;
|
|
2716
|
-
/**
|
|
2717
|
-
* Saves strategy report to disk.
|
|
2718
|
-
* Creates directory if it doesn't exist.
|
|
2719
|
-
* Delegates to ReportStorage.dump().
|
|
2720
|
-
*
|
|
2721
|
-
* @param strategyName - Strategy name to save report for
|
|
2722
|
-
* @param path - Directory path to save report (default: "./logs/live")
|
|
2723
|
-
*
|
|
2724
|
-
* @example
|
|
2725
|
-
* ```typescript
|
|
2726
|
-
* const service = new LiveMarkdownService();
|
|
2727
|
-
*
|
|
2728
|
-
* // Save to default path: ./logs/live/my-strategy.md
|
|
2729
|
-
* await service.dump("my-strategy");
|
|
2730
|
-
*
|
|
2731
|
-
* // Save to custom path: ./custom/path/my-strategy.md
|
|
2732
|
-
* await service.dump("my-strategy", "./custom/path");
|
|
2733
|
-
* ```
|
|
2734
|
-
*/
|
|
2735
|
-
dump: (strategyName: StrategyName, path?: string) => Promise<void>;
|
|
2736
|
-
/**
|
|
2737
|
-
* Clears accumulated event data from storage.
|
|
2738
|
-
* If strategyName is provided, clears only that strategy's data.
|
|
2739
|
-
* If strategyName is omitted, clears all strategies' data.
|
|
2740
|
-
*
|
|
2741
|
-
* @param strategyName - Optional strategy name to clear specific strategy data
|
|
2742
|
-
*
|
|
2743
|
-
* @example
|
|
2744
|
-
* ```typescript
|
|
2745
|
-
* const service = new LiveMarkdownService();
|
|
2746
|
-
*
|
|
2747
|
-
* // Clear specific strategy data
|
|
2748
|
-
* await service.clear("my-strategy");
|
|
2749
|
-
*
|
|
2750
|
-
* // Clear all strategies' data
|
|
2751
|
-
* await service.clear();
|
|
2752
|
-
* ```
|
|
2753
|
-
*/
|
|
2754
|
-
clear: (strategyName?: StrategyName) => Promise<void>;
|
|
2755
|
-
/**
|
|
2756
|
-
* Initializes the service by subscribing to live signal events.
|
|
2757
|
-
* Uses singleshot to ensure initialization happens only once.
|
|
2758
|
-
* Automatically called on first use.
|
|
2759
|
-
*
|
|
2760
|
-
* @example
|
|
2761
|
-
* ```typescript
|
|
2762
|
-
* const service = new LiveMarkdownService();
|
|
2763
|
-
* await service.init(); // Subscribe to live events
|
|
2764
|
-
* ```
|
|
2765
|
-
*/
|
|
2766
|
-
protected init: (() => Promise<void>) & functools_kit.ISingleshotClearable;
|
|
2767
|
-
}
|
|
2768
|
-
|
|
2769
2953
|
/**
|
|
2770
2954
|
* @class ExchangeValidationService
|
|
2771
2955
|
* Service for managing and validating exchange configurations
|
|
@@ -2907,4 +3091,4 @@ declare const backtest: {
|
|
|
2907
3091
|
loggerService: LoggerService;
|
|
2908
3092
|
};
|
|
2909
3093
|
|
|
2910
|
-
export { Backtest, type CandleInterval, type DoneContract, type EntityId, ExecutionContextService, type FrameInterval, type ICandleData, type IExchangeSchema, type IFrameSchema, type IPersistBase, type
|
|
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 };
|