backtest-kit 1.5.37 → 1.5.39

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/build/index.cjs CHANGED
@@ -2879,6 +2879,9 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
2879
2879
  errors.push(`position must be "long" or "short", got "${signal.position}"`);
2880
2880
  }
2881
2881
  // ЗАЩИТА ОТ NaN/Infinity: currentPrice должна быть конечным числом
2882
+ if (typeof currentPrice !== "number") {
2883
+ errors.push(`currentPrice must be a number type, got ${currentPrice} (${typeof currentPrice})`);
2884
+ }
2882
2885
  if (!isFinite(currentPrice)) {
2883
2886
  errors.push(`currentPrice must be a finite number, got ${currentPrice} (${typeof currentPrice})`);
2884
2887
  }
@@ -2886,12 +2889,21 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
2886
2889
  errors.push(`currentPrice must be positive, got ${currentPrice}`);
2887
2890
  }
2888
2891
  // ЗАЩИТА ОТ NaN/Infinity: все цены должны быть конечными числами
2892
+ if (typeof signal.priceOpen !== "number") {
2893
+ errors.push(`priceOpen must be a number type, got ${signal.priceOpen} (${typeof signal.priceOpen})`);
2894
+ }
2889
2895
  if (!isFinite(signal.priceOpen)) {
2890
2896
  errors.push(`priceOpen must be a finite number, got ${signal.priceOpen} (${typeof signal.priceOpen})`);
2891
2897
  }
2898
+ if (typeof signal.priceTakeProfit !== "number") {
2899
+ errors.push(`priceTakeProfit must be a number type, got ${signal.priceTakeProfit} (${typeof signal.priceTakeProfit})`);
2900
+ }
2892
2901
  if (!isFinite(signal.priceTakeProfit)) {
2893
2902
  errors.push(`priceTakeProfit must be a finite number, got ${signal.priceTakeProfit} (${typeof signal.priceTakeProfit})`);
2894
2903
  }
2904
+ if (typeof signal.priceStopLoss !== "number") {
2905
+ errors.push(`priceStopLoss must be a number type, got ${signal.priceStopLoss} (${typeof signal.priceStopLoss})`);
2906
+ }
2895
2907
  if (!isFinite(signal.priceStopLoss)) {
2896
2908
  errors.push(`priceStopLoss must be a finite number, got ${signal.priceStopLoss} (${typeof signal.priceStopLoss})`);
2897
2909
  }
@@ -3030,12 +3042,18 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
3030
3042
  }
3031
3043
  }
3032
3044
  // Валидация временных параметров
3045
+ if (typeof signal.minuteEstimatedTime !== "number") {
3046
+ errors.push(`minuteEstimatedTime must be a number type, got ${signal.minuteEstimatedTime} (${typeof signal.minuteEstimatedTime})`);
3047
+ }
3033
3048
  if (signal.minuteEstimatedTime <= 0) {
3034
3049
  errors.push(`minuteEstimatedTime must be positive, got ${signal.minuteEstimatedTime}`);
3035
3050
  }
3036
3051
  if (!Number.isInteger(signal.minuteEstimatedTime)) {
3037
3052
  errors.push(`minuteEstimatedTime must be an integer (whole number), got ${signal.minuteEstimatedTime}`);
3038
3053
  }
3054
+ if (!isFinite(signal.minuteEstimatedTime)) {
3055
+ errors.push(`minuteEstimatedTime must be a finite number, got ${signal.minuteEstimatedTime}`);
3056
+ }
3039
3057
  // ЗАЩИТА ОТ ВЕЧНЫХ СИГНАЛОВ: ограничиваем максимальное время жизни сигнала
3040
3058
  if (GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES && GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES) {
3041
3059
  if (signal.minuteEstimatedTime > GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES) {
@@ -3046,9 +3064,15 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
3046
3064
  `Eternal signals block risk limits and prevent new trades.`);
3047
3065
  }
3048
3066
  }
3067
+ if (typeof signal.scheduledAt !== "number") {
3068
+ errors.push(`scheduledAt must be a number type, got ${signal.scheduledAt} (${typeof signal.scheduledAt})`);
3069
+ }
3049
3070
  if (signal.scheduledAt <= 0) {
3050
3071
  errors.push(`scheduledAt must be positive, got ${signal.scheduledAt}`);
3051
3072
  }
3073
+ if (typeof signal.pendingAt !== "number") {
3074
+ errors.push(`pendingAt must be a number type, got ${signal.pendingAt} (${typeof signal.pendingAt})`);
3075
+ }
3052
3076
  if (signal.pendingAt <= 0) {
3053
3077
  errors.push(`pendingAt must be positive, got ${signal.pendingAt}`);
3054
3078
  }
package/build/index.mjs CHANGED
@@ -2877,6 +2877,9 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
2877
2877
  errors.push(`position must be "long" or "short", got "${signal.position}"`);
2878
2878
  }
2879
2879
  // ЗАЩИТА ОТ NaN/Infinity: currentPrice должна быть конечным числом
2880
+ if (typeof currentPrice !== "number") {
2881
+ errors.push(`currentPrice must be a number type, got ${currentPrice} (${typeof currentPrice})`);
2882
+ }
2880
2883
  if (!isFinite(currentPrice)) {
2881
2884
  errors.push(`currentPrice must be a finite number, got ${currentPrice} (${typeof currentPrice})`);
2882
2885
  }
@@ -2884,12 +2887,21 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
2884
2887
  errors.push(`currentPrice must be positive, got ${currentPrice}`);
2885
2888
  }
2886
2889
  // ЗАЩИТА ОТ NaN/Infinity: все цены должны быть конечными числами
2890
+ if (typeof signal.priceOpen !== "number") {
2891
+ errors.push(`priceOpen must be a number type, got ${signal.priceOpen} (${typeof signal.priceOpen})`);
2892
+ }
2887
2893
  if (!isFinite(signal.priceOpen)) {
2888
2894
  errors.push(`priceOpen must be a finite number, got ${signal.priceOpen} (${typeof signal.priceOpen})`);
2889
2895
  }
2896
+ if (typeof signal.priceTakeProfit !== "number") {
2897
+ errors.push(`priceTakeProfit must be a number type, got ${signal.priceTakeProfit} (${typeof signal.priceTakeProfit})`);
2898
+ }
2890
2899
  if (!isFinite(signal.priceTakeProfit)) {
2891
2900
  errors.push(`priceTakeProfit must be a finite number, got ${signal.priceTakeProfit} (${typeof signal.priceTakeProfit})`);
2892
2901
  }
2902
+ if (typeof signal.priceStopLoss !== "number") {
2903
+ errors.push(`priceStopLoss must be a number type, got ${signal.priceStopLoss} (${typeof signal.priceStopLoss})`);
2904
+ }
2893
2905
  if (!isFinite(signal.priceStopLoss)) {
2894
2906
  errors.push(`priceStopLoss must be a finite number, got ${signal.priceStopLoss} (${typeof signal.priceStopLoss})`);
2895
2907
  }
@@ -3028,12 +3040,18 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
3028
3040
  }
3029
3041
  }
3030
3042
  // Валидация временных параметров
3043
+ if (typeof signal.minuteEstimatedTime !== "number") {
3044
+ errors.push(`minuteEstimatedTime must be a number type, got ${signal.minuteEstimatedTime} (${typeof signal.minuteEstimatedTime})`);
3045
+ }
3031
3046
  if (signal.minuteEstimatedTime <= 0) {
3032
3047
  errors.push(`minuteEstimatedTime must be positive, got ${signal.minuteEstimatedTime}`);
3033
3048
  }
3034
3049
  if (!Number.isInteger(signal.minuteEstimatedTime)) {
3035
3050
  errors.push(`minuteEstimatedTime must be an integer (whole number), got ${signal.minuteEstimatedTime}`);
3036
3051
  }
3052
+ if (!isFinite(signal.minuteEstimatedTime)) {
3053
+ errors.push(`minuteEstimatedTime must be a finite number, got ${signal.minuteEstimatedTime}`);
3054
+ }
3037
3055
  // ЗАЩИТА ОТ ВЕЧНЫХ СИГНАЛОВ: ограничиваем максимальное время жизни сигнала
3038
3056
  if (GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES && GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES) {
3039
3057
  if (signal.minuteEstimatedTime > GLOBAL_CONFIG.CC_MAX_SIGNAL_LIFETIME_MINUTES) {
@@ -3044,9 +3062,15 @@ const VALIDATE_SIGNAL_FN = (signal, currentPrice, isScheduled) => {
3044
3062
  `Eternal signals block risk limits and prevent new trades.`);
3045
3063
  }
3046
3064
  }
3065
+ if (typeof signal.scheduledAt !== "number") {
3066
+ errors.push(`scheduledAt must be a number type, got ${signal.scheduledAt} (${typeof signal.scheduledAt})`);
3067
+ }
3047
3068
  if (signal.scheduledAt <= 0) {
3048
3069
  errors.push(`scheduledAt must be positive, got ${signal.scheduledAt}`);
3049
3070
  }
3071
+ if (typeof signal.pendingAt !== "number") {
3072
+ errors.push(`pendingAt must be a number type, got ${signal.pendingAt} (${typeof signal.pendingAt})`);
3073
+ }
3050
3074
  if (signal.pendingAt <= 0) {
3051
3075
  errors.push(`pendingAt must be positive, got ${signal.pendingAt}`);
3052
3076
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "1.5.37",
3
+ "version": "1.5.39",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -1112,359 +1112,6 @@ interface WalkerStatisticsModel extends WalkerCompleteContract {
1112
1112
  strategyResults: IStrategyResult[];
1113
1113
  }
1114
1114
 
1115
- /**
1116
- * Unified scheduled signal event data for report generation.
1117
- * Contains all information about scheduled, opened and cancelled events.
1118
- */
1119
- interface ScheduledEvent {
1120
- /** Event timestamp in milliseconds (scheduledAt for scheduled/cancelled events) */
1121
- timestamp: number;
1122
- /** Event action type */
1123
- action: "scheduled" | "opened" | "cancelled";
1124
- /** Trading pair symbol */
1125
- symbol: string;
1126
- /** Signal ID */
1127
- signalId: string;
1128
- /** Position type */
1129
- position: string;
1130
- /** Signal note */
1131
- note?: string;
1132
- /** Current market price */
1133
- currentPrice: number;
1134
- /** Scheduled entry price */
1135
- priceOpen: number;
1136
- /** Take profit price */
1137
- takeProfit: number;
1138
- /** Stop loss price */
1139
- stopLoss: number;
1140
- /** Close timestamp (only for cancelled) */
1141
- closeTimestamp?: number;
1142
- /** Duration in minutes (only for cancelled/opened) */
1143
- duration?: number;
1144
- }
1145
- /**
1146
- * Statistical data calculated from scheduled signals.
1147
- *
1148
- * Provides metrics for scheduled signal tracking, activation and cancellation analysis.
1149
- *
1150
- * @example
1151
- * ```typescript
1152
- * const stats = await Schedule.getData("my-strategy");
1153
- *
1154
- * console.log(`Total events: ${stats.totalEvents}`);
1155
- * console.log(`Scheduled signals: ${stats.totalScheduled}`);
1156
- * console.log(`Opened signals: ${stats.totalOpened}`);
1157
- * console.log(`Cancelled signals: ${stats.totalCancelled}`);
1158
- * console.log(`Cancellation rate: ${stats.cancellationRate}%`);
1159
- *
1160
- * // Access raw event data (includes scheduled, opened, cancelled)
1161
- * stats.eventList.forEach(event => {
1162
- * if (event.action === "cancelled") {
1163
- * console.log(`Cancelled signal: ${event.signalId}`);
1164
- * }
1165
- * });
1166
- * ```
1167
- */
1168
- interface ScheduleStatisticsModel {
1169
- /** Array of all scheduled/opened/cancelled events with full details */
1170
- eventList: ScheduledEvent[];
1171
- /** Total number of all events (includes scheduled, opened, cancelled) */
1172
- totalEvents: number;
1173
- /** Total number of scheduled signals */
1174
- totalScheduled: number;
1175
- /** Total number of opened signals (activated from scheduled) */
1176
- totalOpened: number;
1177
- /** Total number of cancelled signals */
1178
- totalCancelled: number;
1179
- /** Cancellation rate as percentage (0-100), null if no scheduled signals. Lower is better. */
1180
- cancellationRate: number | null;
1181
- /** Activation rate as percentage (0-100), null if no scheduled signals. Higher is better. */
1182
- activationRate: number | null;
1183
- /** Average waiting time for cancelled signals in minutes, null if no cancelled signals */
1184
- avgWaitTime: number | null;
1185
- /** Average waiting time for opened signals in minutes, null if no opened signals */
1186
- avgActivationTime: number | null;
1187
- }
1188
-
1189
- /**
1190
- * Risk rejection event data for report generation.
1191
- * Contains all information about rejected signals due to risk limits.
1192
- */
1193
- interface RiskEvent {
1194
- /** Event timestamp in milliseconds */
1195
- timestamp: number;
1196
- /** Trading pair symbol */
1197
- symbol: string;
1198
- /** Pending signal details */
1199
- pendingSignal: ISignalDto;
1200
- /** Strategy name */
1201
- strategyName: string;
1202
- /** Exchange name */
1203
- exchangeName: string;
1204
- /** Current market price */
1205
- currentPrice: number;
1206
- /** Number of active positions at rejection time */
1207
- activePositionCount: number;
1208
- /** Rejection reason from validation note */
1209
- comment: string;
1210
- /** Whether this event is from backtest mode (true) or live mode (false) */
1211
- backtest: boolean;
1212
- }
1213
- /**
1214
- * Statistical data calculated from risk rejection events.
1215
- *
1216
- * Provides metrics for risk management tracking.
1217
- *
1218
- * @example
1219
- * ```typescript
1220
- * const stats = await Risk.getData("BTCUSDT", "my-strategy");
1221
- *
1222
- * console.log(`Total rejections: ${stats.totalRejections}`);
1223
- * console.log(`Rejections by symbol:`, stats.bySymbol);
1224
- * ```
1225
- */
1226
- interface RiskStatisticsModel {
1227
- /** Array of all risk rejection events with full details */
1228
- eventList: RiskEvent[];
1229
- /** Total number of risk rejections */
1230
- totalRejections: number;
1231
- /** Rejections grouped by symbol */
1232
- bySymbol: Record<string, number>;
1233
- /** Rejections grouped by strategy */
1234
- byStrategy: Record<string, number>;
1235
- }
1236
-
1237
- /**
1238
- * Performance metric types tracked by the system.
1239
- *
1240
- * Backtest metrics:
1241
- * - backtest_total: Total backtest duration from start to finish
1242
- * - backtest_timeframe: Duration to process a single timeframe iteration
1243
- * - backtest_signal: Duration to process a signal (tick + getNextCandles + backtest)
1244
- *
1245
- * Live metrics:
1246
- * - live_tick: Duration of a single live tick iteration
1247
- */
1248
- type PerformanceMetricType = "backtest_total" | "backtest_timeframe" | "backtest_signal" | "live_tick";
1249
- /**
1250
- * Contract for performance tracking events.
1251
- *
1252
- * Emitted during execution to track performance metrics for various operations.
1253
- * Useful for profiling and identifying bottlenecks.
1254
- *
1255
- * @example
1256
- * ```typescript
1257
- * import { listenPerformance } from "backtest-kit";
1258
- *
1259
- * listenPerformance((event) => {
1260
- * console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
1261
- * console.log(`${event.strategyName} @ ${event.exchangeName}`);
1262
- * });
1263
- * ```
1264
- */
1265
- interface PerformanceContract {
1266
- /** Timestamp when the metric was recorded (milliseconds since epoch) */
1267
- timestamp: number;
1268
- /** Timestamp of the previous event (milliseconds since epoch, null for first event) */
1269
- previousTimestamp: number | null;
1270
- /** Type of operation being measured */
1271
- metricType: PerformanceMetricType;
1272
- /** Duration of the operation in milliseconds */
1273
- duration: number;
1274
- /** Strategy name associated with this metric */
1275
- strategyName: string;
1276
- /** Exchange name associated with this metric */
1277
- exchangeName: string;
1278
- /** Trading symbol associated with this metric */
1279
- symbol: string;
1280
- /** Whether this metric is from backtest mode (true) or live mode (false) */
1281
- backtest: boolean;
1282
- }
1283
-
1284
- /**
1285
- * Aggregated statistics for a specific metric type.
1286
- */
1287
- interface MetricStats {
1288
- /** Type of metric */
1289
- metricType: PerformanceMetricType;
1290
- /** Number of recorded samples */
1291
- count: number;
1292
- /** Total duration across all samples (ms) */
1293
- totalDuration: number;
1294
- /** Average duration (ms) */
1295
- avgDuration: number;
1296
- /** Minimum duration (ms) */
1297
- minDuration: number;
1298
- /** Maximum duration (ms) */
1299
- maxDuration: number;
1300
- /** Standard deviation of duration (ms) */
1301
- stdDev: number;
1302
- /** Median duration (ms) */
1303
- median: number;
1304
- /** 95th percentile duration (ms) */
1305
- p95: number;
1306
- /** 99th percentile duration (ms) */
1307
- p99: number;
1308
- /** Average wait time between events (ms) */
1309
- avgWaitTime: number;
1310
- /** Minimum wait time between events (ms) */
1311
- minWaitTime: number;
1312
- /** Maximum wait time between events (ms) */
1313
- maxWaitTime: number;
1314
- }
1315
- /**
1316
- * Performance statistics aggregated by strategy.
1317
- */
1318
- interface PerformanceStatisticsModel {
1319
- /** Strategy name */
1320
- strategyName: string;
1321
- /** Total number of performance events recorded */
1322
- totalEvents: number;
1323
- /** Total execution time across all metrics (ms) */
1324
- totalDuration: number;
1325
- /** Statistics grouped by metric type */
1326
- metricStats: Record<string, MetricStats>;
1327
- /** All raw performance events */
1328
- events: PerformanceContract[];
1329
- }
1330
-
1331
- /**
1332
- * Unified partial profit/loss event data for report generation.
1333
- * Contains all information about profit and loss level milestones.
1334
- */
1335
- interface PartialEvent {
1336
- /** Event timestamp in milliseconds */
1337
- timestamp: number;
1338
- /** Event action type (profit or loss) */
1339
- action: "profit" | "loss";
1340
- /** Trading pair symbol */
1341
- symbol: string;
1342
- /** Strategy name */
1343
- strategyName: string;
1344
- /** Signal ID */
1345
- signalId: string;
1346
- /** Position type */
1347
- position: string;
1348
- /** Current market price */
1349
- currentPrice: number;
1350
- /** Profit/loss level reached (10, 20, 30, etc) */
1351
- level: PartialLevel;
1352
- /** True if backtest mode, false if live mode */
1353
- backtest: boolean;
1354
- }
1355
- /**
1356
- * Statistical data calculated from partial profit/loss events.
1357
- *
1358
- * Provides metrics for partial profit/loss milestone tracking.
1359
- *
1360
- * @example
1361
- * ```typescript
1362
- * const stats = await Partial.getData("BTCUSDT", "my-strategy");
1363
- *
1364
- * console.log(`Total events: ${stats.totalEvents}`);
1365
- * console.log(`Profit events: ${stats.totalProfit}`);
1366
- * console.log(`Loss events: ${stats.totalLoss}`);
1367
- * ```
1368
- */
1369
- interface PartialStatisticsModel {
1370
- /** Array of all profit/loss events with full details */
1371
- eventList: PartialEvent[];
1372
- /** Total number of all events (includes profit, loss) */
1373
- totalEvents: number;
1374
- /** Total number of profit events */
1375
- totalProfit: number;
1376
- /** Total number of loss events */
1377
- totalLoss: number;
1378
- }
1379
-
1380
- /**
1381
- * Unified tick event data for report generation.
1382
- * Contains all information about a tick event regardless of action type.
1383
- */
1384
- interface TickEvent {
1385
- /** Event timestamp in milliseconds (pendingAt for opened/closed events) */
1386
- timestamp: number;
1387
- /** Event action type */
1388
- action: "idle" | "opened" | "active" | "closed";
1389
- /** Trading pair symbol (only for non-idle events) */
1390
- symbol?: string;
1391
- /** Signal ID (only for opened/active/closed) */
1392
- signalId?: string;
1393
- /** Position type (only for opened/active/closed) */
1394
- position?: string;
1395
- /** Signal note (only for opened/active/closed) */
1396
- note?: string;
1397
- /** Current price */
1398
- currentPrice: number;
1399
- /** Open price (only for opened/active/closed) */
1400
- openPrice?: number;
1401
- /** Take profit price (only for opened/active/closed) */
1402
- takeProfit?: number;
1403
- /** Stop loss price (only for opened/active/closed) */
1404
- stopLoss?: number;
1405
- /** Percentage progress towards take profit (only for active) */
1406
- percentTp?: number;
1407
- /** Percentage progress towards stop loss (only for active) */
1408
- percentSl?: number;
1409
- /** PNL percentage (only for closed) */
1410
- pnl?: number;
1411
- /** Close reason (only for closed) */
1412
- closeReason?: string;
1413
- /** Duration in minutes (only for closed) */
1414
- duration?: number;
1415
- }
1416
- /**
1417
- * Statistical data calculated from live trading results.
1418
- *
1419
- * All numeric values are null if calculation is unsafe (NaN, Infinity, etc).
1420
- * Provides comprehensive metrics for live trading performance analysis.
1421
- *
1422
- * @example
1423
- * ```typescript
1424
- * const stats = await Live.getData("my-strategy");
1425
- *
1426
- * console.log(`Total events: ${stats.totalEvents}`);
1427
- * console.log(`Closed signals: ${stats.totalClosed}`);
1428
- * console.log(`Win rate: ${stats.winRate}%`);
1429
- * console.log(`Sharpe Ratio: ${stats.sharpeRatio}`);
1430
- *
1431
- * // Access raw event data (includes idle, opened, active, closed)
1432
- * stats.eventList.forEach(event => {
1433
- * if (event.action === "closed") {
1434
- * console.log(`Closed signal: ${event.pnl}%`);
1435
- * }
1436
- * });
1437
- * ```
1438
- */
1439
- interface LiveStatisticsModel {
1440
- /** Array of all events (idle, opened, active, closed) with full details */
1441
- eventList: TickEvent[];
1442
- /** Total number of all events (includes idle, opened, active, closed) */
1443
- totalEvents: number;
1444
- /** Total number of closed signals only */
1445
- totalClosed: number;
1446
- /** Number of winning closed signals (PNL > 0) */
1447
- winCount: number;
1448
- /** Number of losing closed signals (PNL < 0) */
1449
- lossCount: number;
1450
- /** Win rate as percentage (0-100) based on closed signals, null if unsafe. Higher is better. */
1451
- winRate: number | null;
1452
- /** Average PNL per closed signal as percentage, null if unsafe. Higher is better. */
1453
- avgPnl: number | null;
1454
- /** Cumulative PNL across all closed signals as percentage, null if unsafe. Higher is better. */
1455
- totalPnl: number | null;
1456
- /** Standard deviation of returns (volatility metric), null if unsafe. Lower is better. */
1457
- stdDev: number | null;
1458
- /** Sharpe Ratio (risk-adjusted return = avgPnl / stdDev), null if unsafe. Higher is better. */
1459
- sharpeRatio: number | null;
1460
- /** Annualized Sharpe Ratio (sharpeRatio × √365), null if unsafe. Higher is better. */
1461
- annualizedSharpeRatio: number | null;
1462
- /** Certainty Ratio (avgWin / |avgLoss|), null if unsafe. Higher is better. */
1463
- certaintyRatio: number | null;
1464
- /** Expected yearly returns based on average trade duration and PNL, null if unsafe. Higher is better. */
1465
- expectedYearlyReturns: number | null;
1466
- }
1467
-
1468
1115
  declare const GLOBAL_CONFIG: {
1469
1116
  /**
1470
1117
  * Time to wait for scheduled signal to activate (in minutes)
@@ -3068,12 +2715,59 @@ interface ProgressOptimizerContract {
3068
2715
  optimizerName: string;
3069
2716
  /** symbol - Trading symbol (e.g., "BTCUSDT") */
3070
2717
  symbol: string;
3071
- /** totalSources - Total number of sources to process */
3072
- totalSources: number;
3073
- /** processedSources - Number of sources processed so far */
3074
- processedSources: number;
3075
- /** progress - Completion percentage from 0.0 to 1.0 */
3076
- progress: number;
2718
+ /** totalSources - Total number of sources to process */
2719
+ totalSources: number;
2720
+ /** processedSources - Number of sources processed so far */
2721
+ processedSources: number;
2722
+ /** progress - Completion percentage from 0.0 to 1.0 */
2723
+ progress: number;
2724
+ }
2725
+
2726
+ /**
2727
+ * Performance metric types tracked by the system.
2728
+ *
2729
+ * Backtest metrics:
2730
+ * - backtest_total: Total backtest duration from start to finish
2731
+ * - backtest_timeframe: Duration to process a single timeframe iteration
2732
+ * - backtest_signal: Duration to process a signal (tick + getNextCandles + backtest)
2733
+ *
2734
+ * Live metrics:
2735
+ * - live_tick: Duration of a single live tick iteration
2736
+ */
2737
+ type PerformanceMetricType = "backtest_total" | "backtest_timeframe" | "backtest_signal" | "live_tick";
2738
+ /**
2739
+ * Contract for performance tracking events.
2740
+ *
2741
+ * Emitted during execution to track performance metrics for various operations.
2742
+ * Useful for profiling and identifying bottlenecks.
2743
+ *
2744
+ * @example
2745
+ * ```typescript
2746
+ * import { listenPerformance } from "backtest-kit";
2747
+ *
2748
+ * listenPerformance((event) => {
2749
+ * console.log(`${event.metricType}: ${event.duration.toFixed(2)}ms`);
2750
+ * console.log(`${event.strategyName} @ ${event.exchangeName}`);
2751
+ * });
2752
+ * ```
2753
+ */
2754
+ interface PerformanceContract {
2755
+ /** Timestamp when the metric was recorded (milliseconds since epoch) */
2756
+ timestamp: number;
2757
+ /** Timestamp of the previous event (milliseconds since epoch, null for first event) */
2758
+ previousTimestamp: number | null;
2759
+ /** Type of operation being measured */
2760
+ metricType: PerformanceMetricType;
2761
+ /** Duration of the operation in milliseconds */
2762
+ duration: number;
2763
+ /** Strategy name associated with this metric */
2764
+ strategyName: string;
2765
+ /** Exchange name associated with this metric */
2766
+ exchangeName: string;
2767
+ /** Trading symbol associated with this metric */
2768
+ symbol: string;
2769
+ /** Whether this metric is from backtest mode (true) or live mode (false) */
2770
+ backtest: boolean;
3077
2771
  }
3078
2772
 
3079
2773
  /**
@@ -4342,123 +4036,429 @@ declare function getMode(): Promise<"backtest" | "live">;
4342
4036
  * { role: "assistant", content: "Structure analyzed" }
4343
4037
  * );
4344
4038
  *
4345
- * // Request signal
4346
- * messages.push({
4347
- * role: "user",
4348
- * content: "Generate trading signal. Use position: 'wait' if uncertain."
4349
- * });
4039
+ * // Request signal
4040
+ * messages.push({
4041
+ * role: "user",
4042
+ * content: "Generate trading signal. Use position: 'wait' if uncertain."
4043
+ * });
4044
+ *
4045
+ * const resultId = uuid();
4046
+ * const signal = await llmRequest(messages);
4047
+ *
4048
+ * // Save conversation and result for debugging
4049
+ * await dumpSignal(resultId, messages, signal);
4050
+ *
4051
+ * return signal;
4052
+ * }
4053
+ * });
4054
+ *
4055
+ * // Creates: ./dump/strategy/{uuid}/00_system_prompt.md
4056
+ * // ./dump/strategy/{uuid}/01_user_message.md (1h analysis)
4057
+ * // ./dump/strategy/{uuid}/02_assistant_message.md
4058
+ * // ./dump/strategy/{uuid}/03_user_message.md (5m analysis)
4059
+ * // ./dump/strategy/{uuid}/04_assistant_message.md
4060
+ * // ./dump/strategy/{uuid}/05_user_message.md (signal request)
4061
+ * // ./dump/strategy/{uuid}/06_llm_output.md (final signal)
4062
+ * ```
4063
+ */
4064
+ declare function dumpSignal(signalId: string | number, history: MessageModel[], signal: ISignalDto, outputDir?: string): Promise<void>;
4065
+
4066
+ /**
4067
+ * Portfolio heatmap statistics for a single symbol.
4068
+ * Aggregated metrics across all strategies for one trading pair.
4069
+ */
4070
+ interface IHeatmapRow {
4071
+ /** Trading pair symbol (e.g., "BTCUSDT") */
4072
+ symbol: string;
4073
+ /** Total profit/loss percentage across all closed trades */
4074
+ totalPnl: number | null;
4075
+ /** Risk-adjusted return (Sharpe Ratio) */
4076
+ sharpeRatio: number | null;
4077
+ /** Maximum drawdown percentage (largest peak-to-trough decline) */
4078
+ maxDrawdown: number | null;
4079
+ /** Total number of closed trades */
4080
+ totalTrades: number;
4081
+ /** Number of winning trades */
4082
+ winCount: number;
4083
+ /** Number of losing trades */
4084
+ lossCount: number;
4085
+ /** Win rate percentage */
4086
+ winRate: number | null;
4087
+ /** Average PNL per trade */
4088
+ avgPnl: number | null;
4089
+ /** Standard deviation of PNL */
4090
+ stdDev: number | null;
4091
+ /** Profit factor: sum of wins / sum of losses */
4092
+ profitFactor: number | null;
4093
+ /** Average profit percentage on winning trades */
4094
+ avgWin: number | null;
4095
+ /** Average loss percentage on losing trades */
4096
+ avgLoss: number | null;
4097
+ /** Maximum consecutive winning trades */
4098
+ maxWinStreak: number;
4099
+ /** Maximum consecutive losing trades */
4100
+ maxLossStreak: number;
4101
+ /** Expectancy: (winRate * avgWin) - (lossRate * avgLoss) */
4102
+ expectancy: number | null;
4103
+ }
4104
+
4105
+ /**
4106
+ * Column configuration for markdown table generation.
4107
+ * Generic interface that defines how to extract and format data from any data type.
4108
+ *
4109
+ * @template T - The data type that this column will format
4110
+ *
4111
+ * @example
4112
+ * ```typescript
4113
+ * // Column for formatting signal data
4114
+ * const signalColumn: ColumnModel<IStrategyTickResultClosed> = {
4115
+ * key: "pnl",
4116
+ * label: "PNL",
4117
+ * format: (signal) => `${signal.pnl.pnlPercentage.toFixed(2)}%`,
4118
+ * isVisible: () => true
4119
+ * };
4120
+ *
4121
+ * // Column for formatting heatmap rows
4122
+ * const heatmapColumn: ColumnModel<IHeatmapRow> = {
4123
+ * key: "symbol",
4124
+ * label: "Symbol",
4125
+ * format: (row) => row.symbol,
4126
+ * isVisible: () => true
4127
+ * };
4128
+ * ```
4129
+ */
4130
+ interface ColumnModel<T extends object = any> {
4131
+ /** Unique column identifier */
4132
+ key: string;
4133
+ /** Display label for column header */
4134
+ label: string;
4135
+ /** Formatting function to convert data to string */
4136
+ format: (data: T, index: number) => string | Promise<string>;
4137
+ /** Function to determine if column should be visible */
4138
+ isVisible: () => boolean | Promise<boolean>;
4139
+ }
4140
+
4141
+ /**
4142
+ * Unified tick event data for report generation.
4143
+ * Contains all information about a tick event regardless of action type.
4144
+ */
4145
+ interface TickEvent {
4146
+ /** Event timestamp in milliseconds (pendingAt for opened/closed events) */
4147
+ timestamp: number;
4148
+ /** Event action type */
4149
+ action: "idle" | "opened" | "active" | "closed";
4150
+ /** Trading pair symbol (only for non-idle events) */
4151
+ symbol?: string;
4152
+ /** Signal ID (only for opened/active/closed) */
4153
+ signalId?: string;
4154
+ /** Position type (only for opened/active/closed) */
4155
+ position?: string;
4156
+ /** Signal note (only for opened/active/closed) */
4157
+ note?: string;
4158
+ /** Current price */
4159
+ currentPrice: number;
4160
+ /** Open price (only for opened/active/closed) */
4161
+ openPrice?: number;
4162
+ /** Take profit price (only for opened/active/closed) */
4163
+ takeProfit?: number;
4164
+ /** Stop loss price (only for opened/active/closed) */
4165
+ stopLoss?: number;
4166
+ /** Percentage progress towards take profit (only for active) */
4167
+ percentTp?: number;
4168
+ /** Percentage progress towards stop loss (only for active) */
4169
+ percentSl?: number;
4170
+ /** PNL percentage (only for closed) */
4171
+ pnl?: number;
4172
+ /** Close reason (only for closed) */
4173
+ closeReason?: string;
4174
+ /** Duration in minutes (only for closed) */
4175
+ duration?: number;
4176
+ }
4177
+ /**
4178
+ * Statistical data calculated from live trading results.
4179
+ *
4180
+ * All numeric values are null if calculation is unsafe (NaN, Infinity, etc).
4181
+ * Provides comprehensive metrics for live trading performance analysis.
4182
+ *
4183
+ * @example
4184
+ * ```typescript
4185
+ * const stats = await Live.getData("my-strategy");
4186
+ *
4187
+ * console.log(`Total events: ${stats.totalEvents}`);
4188
+ * console.log(`Closed signals: ${stats.totalClosed}`);
4189
+ * console.log(`Win rate: ${stats.winRate}%`);
4190
+ * console.log(`Sharpe Ratio: ${stats.sharpeRatio}`);
4191
+ *
4192
+ * // Access raw event data (includes idle, opened, active, closed)
4193
+ * stats.eventList.forEach(event => {
4194
+ * if (event.action === "closed") {
4195
+ * console.log(`Closed signal: ${event.pnl}%`);
4196
+ * }
4197
+ * });
4198
+ * ```
4199
+ */
4200
+ interface LiveStatisticsModel {
4201
+ /** Array of all events (idle, opened, active, closed) with full details */
4202
+ eventList: TickEvent[];
4203
+ /** Total number of all events (includes idle, opened, active, closed) */
4204
+ totalEvents: number;
4205
+ /** Total number of closed signals only */
4206
+ totalClosed: number;
4207
+ /** Number of winning closed signals (PNL > 0) */
4208
+ winCount: number;
4209
+ /** Number of losing closed signals (PNL < 0) */
4210
+ lossCount: number;
4211
+ /** Win rate as percentage (0-100) based on closed signals, null if unsafe. Higher is better. */
4212
+ winRate: number | null;
4213
+ /** Average PNL per closed signal as percentage, null if unsafe. Higher is better. */
4214
+ avgPnl: number | null;
4215
+ /** Cumulative PNL across all closed signals as percentage, null if unsafe. Higher is better. */
4216
+ totalPnl: number | null;
4217
+ /** Standard deviation of returns (volatility metric), null if unsafe. Lower is better. */
4218
+ stdDev: number | null;
4219
+ /** Sharpe Ratio (risk-adjusted return = avgPnl / stdDev), null if unsafe. Higher is better. */
4220
+ sharpeRatio: number | null;
4221
+ /** Annualized Sharpe Ratio (sharpeRatio × √365), null if unsafe. Higher is better. */
4222
+ annualizedSharpeRatio: number | null;
4223
+ /** Certainty Ratio (avgWin / |avgLoss|), null if unsafe. Higher is better. */
4224
+ certaintyRatio: number | null;
4225
+ /** Expected yearly returns based on average trade duration and PNL, null if unsafe. Higher is better. */
4226
+ expectedYearlyReturns: number | null;
4227
+ }
4228
+
4229
+ /**
4230
+ * Portfolio heatmap statistics structure.
4231
+ * Contains aggregated data for all symbols in the portfolio.
4232
+ */
4233
+ interface HeatmapStatisticsModel {
4234
+ /** Array of symbol statistics */
4235
+ symbols: IHeatmapRow[];
4236
+ /** Total number of symbols tracked */
4237
+ totalSymbols: number;
4238
+ /** Portfolio-wide total PNL */
4239
+ portfolioTotalPnl: number | null;
4240
+ /** Portfolio-wide Sharpe Ratio */
4241
+ portfolioSharpeRatio: number | null;
4242
+ /** Portfolio-wide total trades */
4243
+ portfolioTotalTrades: number;
4244
+ }
4245
+
4246
+ /**
4247
+ * Unified scheduled signal event data for report generation.
4248
+ * Contains all information about scheduled, opened and cancelled events.
4249
+ */
4250
+ interface ScheduledEvent {
4251
+ /** Event timestamp in milliseconds (scheduledAt for scheduled/cancelled events) */
4252
+ timestamp: number;
4253
+ /** Event action type */
4254
+ action: "scheduled" | "opened" | "cancelled";
4255
+ /** Trading pair symbol */
4256
+ symbol: string;
4257
+ /** Signal ID */
4258
+ signalId: string;
4259
+ /** Position type */
4260
+ position: string;
4261
+ /** Signal note */
4262
+ note?: string;
4263
+ /** Current market price */
4264
+ currentPrice: number;
4265
+ /** Scheduled entry price */
4266
+ priceOpen: number;
4267
+ /** Take profit price */
4268
+ takeProfit: number;
4269
+ /** Stop loss price */
4270
+ stopLoss: number;
4271
+ /** Close timestamp (only for cancelled) */
4272
+ closeTimestamp?: number;
4273
+ /** Duration in minutes (only for cancelled/opened) */
4274
+ duration?: number;
4275
+ }
4276
+ /**
4277
+ * Statistical data calculated from scheduled signals.
4278
+ *
4279
+ * Provides metrics for scheduled signal tracking, activation and cancellation analysis.
4350
4280
  *
4351
- * const resultId = uuid();
4352
- * const signal = await llmRequest(messages);
4281
+ * @example
4282
+ * ```typescript
4283
+ * const stats = await Schedule.getData("my-strategy");
4353
4284
  *
4354
- * // Save conversation and result for debugging
4355
- * await dumpSignal(resultId, messages, signal);
4285
+ * console.log(`Total events: ${stats.totalEvents}`);
4286
+ * console.log(`Scheduled signals: ${stats.totalScheduled}`);
4287
+ * console.log(`Opened signals: ${stats.totalOpened}`);
4288
+ * console.log(`Cancelled signals: ${stats.totalCancelled}`);
4289
+ * console.log(`Cancellation rate: ${stats.cancellationRate}%`);
4356
4290
  *
4357
- * return signal;
4291
+ * // Access raw event data (includes scheduled, opened, cancelled)
4292
+ * stats.eventList.forEach(event => {
4293
+ * if (event.action === "cancelled") {
4294
+ * console.log(`Cancelled signal: ${event.signalId}`);
4358
4295
  * }
4359
4296
  * });
4360
- *
4361
- * // Creates: ./dump/strategy/{uuid}/00_system_prompt.md
4362
- * // ./dump/strategy/{uuid}/01_user_message.md (1h analysis)
4363
- * // ./dump/strategy/{uuid}/02_assistant_message.md
4364
- * // ./dump/strategy/{uuid}/03_user_message.md (5m analysis)
4365
- * // ./dump/strategy/{uuid}/04_assistant_message.md
4366
- * // ./dump/strategy/{uuid}/05_user_message.md (signal request)
4367
- * // ./dump/strategy/{uuid}/06_llm_output.md (final signal)
4368
4297
  * ```
4369
4298
  */
4370
- declare function dumpSignal(signalId: string | number, history: MessageModel[], signal: ISignalDto, outputDir?: string): Promise<void>;
4299
+ interface ScheduleStatisticsModel {
4300
+ /** Array of all scheduled/opened/cancelled events with full details */
4301
+ eventList: ScheduledEvent[];
4302
+ /** Total number of all events (includes scheduled, opened, cancelled) */
4303
+ totalEvents: number;
4304
+ /** Total number of scheduled signals */
4305
+ totalScheduled: number;
4306
+ /** Total number of opened signals (activated from scheduled) */
4307
+ totalOpened: number;
4308
+ /** Total number of cancelled signals */
4309
+ totalCancelled: number;
4310
+ /** Cancellation rate as percentage (0-100), null if no scheduled signals. Lower is better. */
4311
+ cancellationRate: number | null;
4312
+ /** Activation rate as percentage (0-100), null if no scheduled signals. Higher is better. */
4313
+ activationRate: number | null;
4314
+ /** Average waiting time for cancelled signals in minutes, null if no cancelled signals */
4315
+ avgWaitTime: number | null;
4316
+ /** Average waiting time for opened signals in minutes, null if no opened signals */
4317
+ avgActivationTime: number | null;
4318
+ }
4371
4319
 
4372
4320
  /**
4373
- * Portfolio heatmap statistics for a single symbol.
4374
- * Aggregated metrics across all strategies for one trading pair.
4321
+ * Aggregated statistics for a specific metric type.
4375
4322
  */
4376
- interface IHeatmapRow {
4377
- /** Trading pair symbol (e.g., "BTCUSDT") */
4378
- symbol: string;
4379
- /** Total profit/loss percentage across all closed trades */
4380
- totalPnl: number | null;
4381
- /** Risk-adjusted return (Sharpe Ratio) */
4382
- sharpeRatio: number | null;
4383
- /** Maximum drawdown percentage (largest peak-to-trough decline) */
4384
- maxDrawdown: number | null;
4385
- /** Total number of closed trades */
4386
- totalTrades: number;
4387
- /** Number of winning trades */
4388
- winCount: number;
4389
- /** Number of losing trades */
4390
- lossCount: number;
4391
- /** Win rate percentage */
4392
- winRate: number | null;
4393
- /** Average PNL per trade */
4394
- avgPnl: number | null;
4395
- /** Standard deviation of PNL */
4396
- stdDev: number | null;
4397
- /** Profit factor: sum of wins / sum of losses */
4398
- profitFactor: number | null;
4399
- /** Average profit percentage on winning trades */
4400
- avgWin: number | null;
4401
- /** Average loss percentage on losing trades */
4402
- avgLoss: number | null;
4403
- /** Maximum consecutive winning trades */
4404
- maxWinStreak: number;
4405
- /** Maximum consecutive losing trades */
4406
- maxLossStreak: number;
4407
- /** Expectancy: (winRate * avgWin) - (lossRate * avgLoss) */
4408
- expectancy: number | null;
4323
+ interface MetricStats {
4324
+ /** Type of metric */
4325
+ metricType: PerformanceMetricType;
4326
+ /** Number of recorded samples */
4327
+ count: number;
4328
+ /** Total duration across all samples (ms) */
4329
+ totalDuration: number;
4330
+ /** Average duration (ms) */
4331
+ avgDuration: number;
4332
+ /** Minimum duration (ms) */
4333
+ minDuration: number;
4334
+ /** Maximum duration (ms) */
4335
+ maxDuration: number;
4336
+ /** Standard deviation of duration (ms) */
4337
+ stdDev: number;
4338
+ /** Median duration (ms) */
4339
+ median: number;
4340
+ /** 95th percentile duration (ms) */
4341
+ p95: number;
4342
+ /** 99th percentile duration (ms) */
4343
+ p99: number;
4344
+ /** Average wait time between events (ms) */
4345
+ avgWaitTime: number;
4346
+ /** Minimum wait time between events (ms) */
4347
+ minWaitTime: number;
4348
+ /** Maximum wait time between events (ms) */
4349
+ maxWaitTime: number;
4350
+ }
4351
+ /**
4352
+ * Performance statistics aggregated by strategy.
4353
+ */
4354
+ interface PerformanceStatisticsModel {
4355
+ /** Strategy name */
4356
+ strategyName: string;
4357
+ /** Total number of performance events recorded */
4358
+ totalEvents: number;
4359
+ /** Total execution time across all metrics (ms) */
4360
+ totalDuration: number;
4361
+ /** Statistics grouped by metric type */
4362
+ metricStats: Record<string, MetricStats>;
4363
+ /** All raw performance events */
4364
+ events: PerformanceContract[];
4409
4365
  }
4410
4366
 
4411
4367
  /**
4412
- * Column configuration for markdown table generation.
4413
- * Generic interface that defines how to extract and format data from any data type.
4368
+ * Unified partial profit/loss event data for report generation.
4369
+ * Contains all information about profit and loss level milestones.
4370
+ */
4371
+ interface PartialEvent {
4372
+ /** Event timestamp in milliseconds */
4373
+ timestamp: number;
4374
+ /** Event action type (profit or loss) */
4375
+ action: "profit" | "loss";
4376
+ /** Trading pair symbol */
4377
+ symbol: string;
4378
+ /** Strategy name */
4379
+ strategyName: string;
4380
+ /** Signal ID */
4381
+ signalId: string;
4382
+ /** Position type */
4383
+ position: string;
4384
+ /** Current market price */
4385
+ currentPrice: number;
4386
+ /** Profit/loss level reached (10, 20, 30, etc) */
4387
+ level: PartialLevel;
4388
+ /** True if backtest mode, false if live mode */
4389
+ backtest: boolean;
4390
+ }
4391
+ /**
4392
+ * Statistical data calculated from partial profit/loss events.
4414
4393
  *
4415
- * @template T - The data type that this column will format
4394
+ * Provides metrics for partial profit/loss milestone tracking.
4416
4395
  *
4417
4396
  * @example
4418
4397
  * ```typescript
4419
- * // Column for formatting signal data
4420
- * const signalColumn: ColumnModel<IStrategyTickResultClosed> = {
4421
- * key: "pnl",
4422
- * label: "PNL",
4423
- * format: (signal) => `${signal.pnl.pnlPercentage.toFixed(2)}%`,
4424
- * isVisible: () => true
4425
- * };
4398
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
4426
4399
  *
4427
- * // Column for formatting heatmap rows
4428
- * const heatmapColumn: ColumnModel<IHeatmapRow> = {
4429
- * key: "symbol",
4430
- * label: "Symbol",
4431
- * format: (row) => row.symbol,
4432
- * isVisible: () => true
4433
- * };
4400
+ * console.log(`Total events: ${stats.totalEvents}`);
4401
+ * console.log(`Profit events: ${stats.totalProfit}`);
4402
+ * console.log(`Loss events: ${stats.totalLoss}`);
4434
4403
  * ```
4435
4404
  */
4436
- interface ColumnModel<T extends object = any> {
4437
- /** Unique column identifier */
4438
- key: string;
4439
- /** Display label for column header */
4440
- label: string;
4441
- /** Formatting function to convert data to string */
4442
- format: (data: T, index: number) => string | Promise<string>;
4443
- /** Function to determine if column should be visible */
4444
- isVisible: () => boolean | Promise<boolean>;
4405
+ interface PartialStatisticsModel {
4406
+ /** Array of all profit/loss events with full details */
4407
+ eventList: PartialEvent[];
4408
+ /** Total number of all events (includes profit, loss) */
4409
+ totalEvents: number;
4410
+ /** Total number of profit events */
4411
+ totalProfit: number;
4412
+ /** Total number of loss events */
4413
+ totalLoss: number;
4445
4414
  }
4446
4415
 
4447
4416
  /**
4448
- * Portfolio heatmap statistics structure.
4449
- * Contains aggregated data for all symbols in the portfolio.
4417
+ * Risk rejection event data for report generation.
4418
+ * Contains all information about rejected signals due to risk limits.
4450
4419
  */
4451
- interface HeatmapStatisticsModel {
4452
- /** Array of symbol statistics */
4453
- symbols: IHeatmapRow[];
4454
- /** Total number of symbols tracked */
4455
- totalSymbols: number;
4456
- /** Portfolio-wide total PNL */
4457
- portfolioTotalPnl: number | null;
4458
- /** Portfolio-wide Sharpe Ratio */
4459
- portfolioSharpeRatio: number | null;
4460
- /** Portfolio-wide total trades */
4461
- portfolioTotalTrades: number;
4420
+ interface RiskEvent {
4421
+ /** Event timestamp in milliseconds */
4422
+ timestamp: number;
4423
+ /** Trading pair symbol */
4424
+ symbol: string;
4425
+ /** Pending signal details */
4426
+ pendingSignal: ISignalDto;
4427
+ /** Strategy name */
4428
+ strategyName: string;
4429
+ /** Exchange name */
4430
+ exchangeName: string;
4431
+ /** Current market price */
4432
+ currentPrice: number;
4433
+ /** Number of active positions at rejection time */
4434
+ activePositionCount: number;
4435
+ /** Rejection reason from validation note */
4436
+ comment: string;
4437
+ /** Whether this event is from backtest mode (true) or live mode (false) */
4438
+ backtest: boolean;
4439
+ }
4440
+ /**
4441
+ * Statistical data calculated from risk rejection events.
4442
+ *
4443
+ * Provides metrics for risk management tracking.
4444
+ *
4445
+ * @example
4446
+ * ```typescript
4447
+ * const stats = await Risk.getData("BTCUSDT", "my-strategy");
4448
+ *
4449
+ * console.log(`Total rejections: ${stats.totalRejections}`);
4450
+ * console.log(`Rejections by symbol:`, stats.bySymbol);
4451
+ * ```
4452
+ */
4453
+ interface RiskStatisticsModel {
4454
+ /** Array of all risk rejection events with full details */
4455
+ eventList: RiskEvent[];
4456
+ /** Total number of risk rejections */
4457
+ totalRejections: number;
4458
+ /** Rejections grouped by symbol */
4459
+ bySymbol: Record<string, number>;
4460
+ /** Rejections grouped by strategy */
4461
+ byStrategy: Record<string, number>;
4462
4462
  }
4463
4463
 
4464
4464
  declare const BASE_WAIT_FOR_INIT_SYMBOL: unique symbol;
@@ -10778,4 +10778,4 @@ declare const backtest: {
10778
10778
  loggerService: LoggerService;
10779
10779
  };
10780
10780
 
10781
- export { Backtest, type BacktestStatisticsModel, Cache, type CandleInterval, type ColumnConfig, type ColumnModel, Constant, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IOptimizerCallbacks, type IOptimizerData, type IOptimizerFetchArgs, type IOptimizerFilterArgs, type IOptimizerRange, type IOptimizerSchema, type IOptimizerSource, type IOptimizerStrategy, type IOptimizerTemplate, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStrategyPnL, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, Live, type LiveStatisticsModel, type MessageModel, type MessageRole, MethodContextService, Optimizer, Partial$1 as Partial, type PartialData, type PartialLossContract, type PartialProfitContract, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, type ProgressBacktestContract, type ProgressOptimizerContract, type ProgressWalkerContract, Risk, type RiskContract, type RiskData, type RiskStatisticsModel, Schedule, type ScheduleData, type ScheduleStatisticsModel, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type WalkerStatisticsModel, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger };
10781
+ export { Backtest, type BacktestStatisticsModel, Cache, type CandleInterval, type ColumnConfig, type ColumnModel, Constant, type DoneContract, type EntityId, Exchange, ExecutionContextService, type FrameInterval, type GlobalConfig, Heat, type HeatmapStatisticsModel, type ICandleData, type IExchangeSchema, type IFrameSchema, type IHeatmapRow, type IOptimizerCallbacks, type IOptimizerData, type IOptimizerFetchArgs, type IOptimizerFilterArgs, type IOptimizerRange, type IOptimizerSchema, type IOptimizerSource, type IOptimizerStrategy, type IOptimizerTemplate, type IPersistBase, type IPositionSizeATRParams, type IPositionSizeFixedPercentageParams, type IPositionSizeKellyParams, type IRiskActivePosition, type IRiskCheckArgs, type IRiskSchema, type IRiskValidation, type IRiskValidationFn, type IRiskValidationPayload, type IScheduledSignalRow, type ISignalDto, type ISignalRow, type ISizingCalculateParams, type ISizingCalculateParamsATR, type ISizingCalculateParamsFixedPercentage, type ISizingCalculateParamsKelly, type ISizingSchema, type ISizingSchemaATR, type ISizingSchemaFixedPercentage, type ISizingSchemaKelly, type IStrategyPnL, type IStrategyResult, type IStrategySchema, type IStrategyTickResult, type IStrategyTickResultActive, type IStrategyTickResultCancelled, type IStrategyTickResultClosed, type IStrategyTickResultIdle, type IStrategyTickResultOpened, type IStrategyTickResultScheduled, type IWalkerResults, type IWalkerSchema, type IWalkerStrategyResult, Live, type LiveStatisticsModel, type MessageModel, type MessageRole, MethodContextService, type MetricStats, Optimizer, Partial$1 as Partial, type PartialData, type PartialEvent, type PartialLossContract, type PartialProfitContract, type PartialStatisticsModel, Performance, type PerformanceContract, type PerformanceMetricType, type PerformanceStatisticsModel, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, type ProgressBacktestContract, type ProgressOptimizerContract, type ProgressWalkerContract, Risk, type RiskContract, type RiskData, type RiskEvent, type RiskStatisticsModel, Schedule, type ScheduleData, type ScheduleStatisticsModel, type ScheduledEvent, type SignalData, type SignalInterval, type TPersistBase, type TPersistBaseCtor, type TickEvent, Walker, type WalkerCompleteContract, type WalkerContract, type WalkerMetric, type WalkerStatisticsModel, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getColumns, getConfig, getDate, getDefaultColumns, getDefaultConfig, getMode, hasTradeContext, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenRisk, listenRiskOnce, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setColumns, setConfig, setLogger };