backtest-kit 1.4.12 → 1.4.13

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
@@ -10464,6 +10464,11 @@ const columns = [
10464
10464
  label: "Symbol",
10465
10465
  format: (data) => data.symbol,
10466
10466
  },
10467
+ {
10468
+ key: "strategyName",
10469
+ label: "Strategy",
10470
+ format: (data) => data.strategyName,
10471
+ },
10467
10472
  {
10468
10473
  key: "signalId",
10469
10474
  label: "Signal ID",
@@ -10498,7 +10503,7 @@ const columns = [
10498
10503
  /** Maximum number of events to store in partial reports */
10499
10504
  const MAX_EVENTS = 250;
10500
10505
  /**
10501
- * Storage class for accumulating partial profit/loss events per symbol.
10506
+ * Storage class for accumulating partial profit/loss events per symbol-strategy pair.
10502
10507
  * Maintains a chronological list of profit and loss level events.
10503
10508
  */
10504
10509
  class ReportStorage {
@@ -10509,17 +10514,17 @@ class ReportStorage {
10509
10514
  /**
10510
10515
  * Adds a profit event to the storage.
10511
10516
  *
10512
- * @param symbol - Trading pair symbol
10513
10517
  * @param data - Signal row data
10514
10518
  * @param currentPrice - Current market price
10515
10519
  * @param level - Profit level reached
10516
10520
  * @param backtest - True if backtest mode
10517
10521
  */
10518
- addProfitEvent(symbol, data, currentPrice, level, backtest, timestamp) {
10522
+ addProfitEvent(data, currentPrice, level, backtest, timestamp) {
10519
10523
  this._eventList.push({
10520
10524
  timestamp,
10521
10525
  action: "profit",
10522
- symbol,
10526
+ symbol: data.symbol,
10527
+ strategyName: data.strategyName,
10523
10528
  signalId: data.id,
10524
10529
  position: data.position,
10525
10530
  currentPrice,
@@ -10534,17 +10539,17 @@ class ReportStorage {
10534
10539
  /**
10535
10540
  * Adds a loss event to the storage.
10536
10541
  *
10537
- * @param symbol - Trading pair symbol
10538
10542
  * @param data - Signal row data
10539
10543
  * @param currentPrice - Current market price
10540
10544
  * @param level - Loss level reached
10541
10545
  * @param backtest - True if backtest mode
10542
10546
  */
10543
- addLossEvent(symbol, data, currentPrice, level, backtest, timestamp) {
10547
+ addLossEvent(data, currentPrice, level, backtest, timestamp) {
10544
10548
  this._eventList.push({
10545
10549
  timestamp,
10546
10550
  action: "loss",
10547
- symbol,
10551
+ symbol: data.symbol,
10552
+ strategyName: data.strategyName,
10548
10553
  signalId: data.id,
10549
10554
  position: data.position,
10550
10555
  currentPrice,
@@ -10580,35 +10585,37 @@ class ReportStorage {
10580
10585
  };
10581
10586
  }
10582
10587
  /**
10583
- * Generates markdown report with all partial events for a symbol (View).
10588
+ * Generates markdown report with all partial events for a symbol-strategy pair (View).
10584
10589
  *
10585
10590
  * @param symbol - Trading pair symbol
10591
+ * @param strategyName - Strategy name
10586
10592
  * @returns Markdown formatted report with all events
10587
10593
  */
10588
- async getReport(symbol) {
10594
+ async getReport(symbol, strategyName) {
10589
10595
  const stats = await this.getData();
10590
10596
  if (stats.totalEvents === 0) {
10591
- return functoolsKit.str.newline(`# Partial Profit/Loss Report: ${symbol}`, "", "No partial profit/loss events recorded yet.");
10597
+ return functoolsKit.str.newline(`# Partial Profit/Loss Report: ${symbol}:${strategyName}`, "", "No partial profit/loss events recorded yet.");
10592
10598
  }
10593
10599
  const header = columns.map((col) => col.label);
10594
10600
  const separator = columns.map(() => "---");
10595
10601
  const rows = this._eventList.map((event) => columns.map((col) => col.format(event)));
10596
10602
  const tableData = [header, separator, ...rows];
10597
10603
  const table = functoolsKit.str.newline(tableData.map((row) => `| ${row.join(" | ")} |`));
10598
- return functoolsKit.str.newline(`# Partial Profit/Loss Report: ${symbol}`, "", table, "", `**Total events:** ${stats.totalEvents}`, `**Profit events:** ${stats.totalProfit}`, `**Loss events:** ${stats.totalLoss}`);
10604
+ return functoolsKit.str.newline(`# Partial Profit/Loss Report: ${symbol}:${strategyName}`, "", table, "", `**Total events:** ${stats.totalEvents}`, `**Profit events:** ${stats.totalProfit}`, `**Loss events:** ${stats.totalLoss}`);
10599
10605
  }
10600
10606
  /**
10601
- * Saves symbol report to disk.
10607
+ * Saves symbol-strategy report to disk.
10602
10608
  *
10603
10609
  * @param symbol - Trading pair symbol
10610
+ * @param strategyName - Strategy name
10604
10611
  * @param path - Directory path to save report (default: "./dump/partial")
10605
10612
  */
10606
- async dump(symbol, path$1 = "./dump/partial") {
10607
- const markdown = await this.getReport(symbol);
10613
+ async dump(symbol, strategyName, path$1 = "./dump/partial") {
10614
+ const markdown = await this.getReport(symbol, strategyName);
10608
10615
  try {
10609
10616
  const dir = path.join(process.cwd(), path$1);
10610
10617
  await fs.mkdir(dir, { recursive: true });
10611
- const filename = `${symbol}.md`;
10618
+ const filename = `${symbol}_${strategyName}.md`;
10612
10619
  const filepath = path.join(dir, filename);
10613
10620
  await fs.writeFile(filepath, markdown, "utf-8");
10614
10621
  console.log(`Partial profit/loss report saved: ${filepath}`);
@@ -10623,10 +10630,10 @@ class ReportStorage {
10623
10630
  *
10624
10631
  * Features:
10625
10632
  * - Listens to partial profit and loss events via partialProfitSubject/partialLossSubject
10626
- * - Accumulates all events (profit, loss) per symbol
10633
+ * - Accumulates all events (profit, loss) per symbol-strategy pair
10627
10634
  * - Generates markdown tables with detailed event information
10628
10635
  * - Provides statistics (total profit/loss events)
10629
- * - Saves reports to disk in dump/partial/{symbol}.md
10636
+ * - Saves reports to disk in dump/partial/{symbol}_{strategyName}.md
10630
10637
  *
10631
10638
  * @example
10632
10639
  * ```typescript
@@ -10636,7 +10643,7 @@ class ReportStorage {
10636
10643
  * // No manual callback setup needed
10637
10644
  *
10638
10645
  * // Later: generate and save report
10639
- * await service.dump("BTCUSDT");
10646
+ * await service.dump("BTCUSDT", "my-strategy");
10640
10647
  * ```
10641
10648
  */
10642
10649
  class PartialMarkdownService {
@@ -10644,10 +10651,10 @@ class PartialMarkdownService {
10644
10651
  /** Logger service for debug output */
10645
10652
  this.loggerService = inject(TYPES.loggerService);
10646
10653
  /**
10647
- * Memoized function to get or create ReportStorage for a symbol.
10648
- * Each symbol gets its own isolated storage instance.
10654
+ * Memoized function to get or create ReportStorage for a symbol-strategy pair.
10655
+ * Each symbol-strategy combination gets its own isolated storage instance.
10649
10656
  */
10650
- this.getStorage = functoolsKit.memoize(([symbol]) => `${symbol}`, () => new ReportStorage());
10657
+ this.getStorage = functoolsKit.memoize(([symbol, strategyName]) => JSON.stringify([symbol, strategyName]), () => new ReportStorage());
10651
10658
  /**
10652
10659
  * Processes profit events and accumulates them.
10653
10660
  * Should be called from partialProfitSubject subscription.
@@ -10664,8 +10671,8 @@ class PartialMarkdownService {
10664
10671
  this.loggerService.log("partialMarkdownService tickProfit", {
10665
10672
  data,
10666
10673
  });
10667
- const storage = this.getStorage(data.symbol);
10668
- storage.addProfitEvent(data.symbol, data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10674
+ const storage = this.getStorage(data.symbol, data.data.strategyName);
10675
+ storage.addProfitEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10669
10676
  };
10670
10677
  /**
10671
10678
  * Processes loss events and accumulates them.
@@ -10683,101 +10690,113 @@ class PartialMarkdownService {
10683
10690
  this.loggerService.log("partialMarkdownService tickLoss", {
10684
10691
  data,
10685
10692
  });
10686
- const storage = this.getStorage(data.symbol);
10687
- storage.addLossEvent(data.symbol, data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10693
+ const storage = this.getStorage(data.symbol, data.data.strategyName);
10694
+ storage.addLossEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10688
10695
  };
10689
10696
  /**
10690
- * Gets statistical data from all partial profit/loss events for a symbol.
10697
+ * Gets statistical data from all partial profit/loss events for a symbol-strategy pair.
10691
10698
  * Delegates to ReportStorage.getData().
10692
10699
  *
10693
10700
  * @param symbol - Trading pair symbol to get data for
10701
+ * @param strategyName - Strategy name to get data for
10694
10702
  * @returns Statistical data object with all metrics
10695
10703
  *
10696
10704
  * @example
10697
10705
  * ```typescript
10698
10706
  * const service = new PartialMarkdownService();
10699
- * const stats = await service.getData("BTCUSDT");
10707
+ * const stats = await service.getData("BTCUSDT", "my-strategy");
10700
10708
  * console.log(stats.totalProfit, stats.totalLoss);
10701
10709
  * ```
10702
10710
  */
10703
- this.getData = async (symbol) => {
10711
+ this.getData = async (symbol, strategyName) => {
10704
10712
  this.loggerService.log("partialMarkdownService getData", {
10705
10713
  symbol,
10714
+ strategyName,
10706
10715
  });
10707
- const storage = this.getStorage(symbol);
10716
+ const storage = this.getStorage(symbol, strategyName);
10708
10717
  return storage.getData();
10709
10718
  };
10710
10719
  /**
10711
- * Generates markdown report with all partial events for a symbol.
10720
+ * Generates markdown report with all partial events for a symbol-strategy pair.
10712
10721
  * Delegates to ReportStorage.getReport().
10713
10722
  *
10714
10723
  * @param symbol - Trading pair symbol to generate report for
10724
+ * @param strategyName - Strategy name to generate report for
10715
10725
  * @returns Markdown formatted report string with table of all events
10716
10726
  *
10717
10727
  * @example
10718
10728
  * ```typescript
10719
10729
  * const service = new PartialMarkdownService();
10720
- * const markdown = await service.getReport("BTCUSDT");
10730
+ * const markdown = await service.getReport("BTCUSDT", "my-strategy");
10721
10731
  * console.log(markdown);
10722
10732
  * ```
10723
10733
  */
10724
- this.getReport = async (symbol) => {
10734
+ this.getReport = async (symbol, strategyName) => {
10725
10735
  this.loggerService.log("partialMarkdownService getReport", {
10726
10736
  symbol,
10737
+ strategyName,
10727
10738
  });
10728
- const storage = this.getStorage(symbol);
10729
- return storage.getReport(symbol);
10739
+ const storage = this.getStorage(symbol, strategyName);
10740
+ return storage.getReport(symbol, strategyName);
10730
10741
  };
10731
10742
  /**
10732
- * Saves symbol report to disk.
10743
+ * Saves symbol-strategy report to disk.
10733
10744
  * Creates directory if it doesn't exist.
10734
10745
  * Delegates to ReportStorage.dump().
10735
10746
  *
10736
10747
  * @param symbol - Trading pair symbol to save report for
10748
+ * @param strategyName - Strategy name to save report for
10737
10749
  * @param path - Directory path to save report (default: "./dump/partial")
10738
10750
  *
10739
10751
  * @example
10740
10752
  * ```typescript
10741
10753
  * const service = new PartialMarkdownService();
10742
10754
  *
10743
- * // Save to default path: ./dump/partial/BTCUSDT.md
10744
- * await service.dump("BTCUSDT");
10755
+ * // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
10756
+ * await service.dump("BTCUSDT", "my-strategy");
10745
10757
  *
10746
- * // Save to custom path: ./custom/path/BTCUSDT.md
10747
- * await service.dump("BTCUSDT", "./custom/path");
10758
+ * // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
10759
+ * await service.dump("BTCUSDT", "my-strategy", "./custom/path");
10748
10760
  * ```
10749
10761
  */
10750
- this.dump = async (symbol, path = "./dump/partial") => {
10762
+ this.dump = async (symbol, strategyName, path = "./dump/partial") => {
10751
10763
  this.loggerService.log("partialMarkdownService dump", {
10752
10764
  symbol,
10765
+ strategyName,
10753
10766
  path,
10754
10767
  });
10755
- const storage = this.getStorage(symbol);
10756
- await storage.dump(symbol, path);
10768
+ const storage = this.getStorage(symbol, strategyName);
10769
+ await storage.dump(symbol, strategyName, path);
10757
10770
  };
10758
10771
  /**
10759
10772
  * Clears accumulated event data from storage.
10760
- * If symbol is provided, clears only that symbol's data.
10761
- * If symbol is omitted, clears all symbols' data.
10773
+ * If ctx is provided, clears only that specific symbol-strategy pair's data.
10774
+ * If nothing is provided, clears all data.
10762
10775
  *
10763
- * @param symbol - Optional symbol to clear specific symbol data
10776
+ * @param ctx - Optional context with symbol and strategyName
10764
10777
  *
10765
10778
  * @example
10766
10779
  * ```typescript
10767
10780
  * const service = new PartialMarkdownService();
10768
10781
  *
10769
- * // Clear specific symbol data
10770
- * await service.clear("BTCUSDT");
10782
+ * // Clear specific symbol-strategy pair
10783
+ * await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
10771
10784
  *
10772
- * // Clear all symbols' data
10785
+ * // Clear all data
10773
10786
  * await service.clear();
10774
10787
  * ```
10775
10788
  */
10776
- this.clear = async (symbol) => {
10789
+ this.clear = async (ctx) => {
10777
10790
  this.loggerService.log("partialMarkdownService clear", {
10778
- symbol,
10791
+ ctx,
10779
10792
  });
10780
- this.getStorage.clear(symbol);
10793
+ if (ctx) {
10794
+ const key = JSON.stringify([ctx.symbol, ctx.strategyName]);
10795
+ this.getStorage.clear(key);
10796
+ }
10797
+ else {
10798
+ this.getStorage.clear();
10799
+ }
10781
10800
  };
10782
10801
  /**
10783
10802
  * Initializes the service by subscribing to partial profit/loss events.
@@ -14140,26 +14159,26 @@ const PARTIAL_METHOD_NAME_DUMP = "PartialUtils.dump";
14140
14159
  *
14141
14160
  * Data source:
14142
14161
  * - PartialMarkdownService listens to partialProfitSubject/partialLossSubject
14143
- * - Accumulates events in ReportStorage (max 250 events per symbol)
14144
- * - Events include: timestamp, action, symbol, signalId, position, level, price, mode
14162
+ * - Accumulates events in ReportStorage (max 250 events per symbol-strategy pair)
14163
+ * - Events include: timestamp, action, symbol, strategyName, signalId, position, level, price, mode
14145
14164
  *
14146
14165
  * @example
14147
14166
  * ```typescript
14148
14167
  * import { Partial } from "./classes/Partial";
14149
14168
  *
14150
- * // Get statistical data for BTCUSDT
14151
- * const stats = await Partial.getData("BTCUSDT");
14169
+ * // Get statistical data for BTCUSDT:my-strategy
14170
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
14152
14171
  * console.log(`Total events: ${stats.totalEvents}`);
14153
14172
  * console.log(`Profit events: ${stats.totalProfit}`);
14154
14173
  * console.log(`Loss events: ${stats.totalLoss}`);
14155
14174
  *
14156
14175
  * // Generate markdown report
14157
- * const markdown = await Partial.getReport("BTCUSDT");
14176
+ * const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
14158
14177
  * console.log(markdown); // Formatted table with all events
14159
14178
  *
14160
14179
  * // Export report to file
14161
- * await Partial.dump("BTCUSDT"); // Saves to ./dump/partial/BTCUSDT.md
14162
- * await Partial.dump("BTCUSDT", "./custom/path"); // Custom directory
14180
+ * await Partial.dump("BTCUSDT", "my-strategy"); // Saves to ./dump/partial/BTCUSDT_my-strategy.md
14181
+ * await Partial.dump("BTCUSDT", "my-strategy", "./custom/path"); // Custom directory
14163
14182
  * ```
14164
14183
  */
14165
14184
  class PartialUtils {
@@ -14171,11 +14190,12 @@ class PartialUtils {
14171
14190
  * Returns aggregated metrics calculated from all profit and loss events.
14172
14191
  *
14173
14192
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
14193
+ * @param strategyName - Strategy name (e.g., "my-strategy")
14174
14194
  * @returns Promise resolving to PartialStatistics object with counts and event list
14175
14195
  *
14176
14196
  * @example
14177
14197
  * ```typescript
14178
- * const stats = await Partial.getData("BTCUSDT");
14198
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
14179
14199
  *
14180
14200
  * console.log(`Total events: ${stats.totalEvents}`);
14181
14201
  * console.log(`Profit events: ${stats.totalProfit} (${(stats.totalProfit / stats.totalEvents * 100).toFixed(1)}%)`);
@@ -14187,16 +14207,17 @@ class PartialUtils {
14187
14207
  * }
14188
14208
  * ```
14189
14209
  */
14190
- this.getData = async (symbol) => {
14191
- backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol });
14192
- return await backtest$1.partialMarkdownService.getData(symbol);
14210
+ this.getData = async (symbol, strategyName) => {
14211
+ backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
14212
+ return await backtest$1.partialMarkdownService.getData(symbol, strategyName);
14193
14213
  };
14194
14214
  /**
14195
- * Generates markdown report with all partial profit/loss events for a symbol.
14215
+ * Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
14196
14216
  *
14197
14217
  * Creates formatted table containing:
14198
14218
  * - Action (PROFIT/LOSS)
14199
14219
  * - Symbol
14220
+ * - Strategy
14200
14221
  * - Signal ID
14201
14222
  * - Position (LONG/SHORT)
14202
14223
  * - Level % (+10%, -20%, etc)
@@ -14207,35 +14228,36 @@ class PartialUtils {
14207
14228
  * Also includes summary statistics at the end.
14208
14229
  *
14209
14230
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
14231
+ * @param strategyName - Strategy name (e.g., "my-strategy")
14210
14232
  * @returns Promise resolving to markdown formatted report string
14211
14233
  *
14212
14234
  * @example
14213
14235
  * ```typescript
14214
- * const markdown = await Partial.getReport("BTCUSDT");
14236
+ * const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
14215
14237
  * console.log(markdown);
14216
14238
  *
14217
14239
  * // Output:
14218
- * // # Partial Profit/Loss Report: BTCUSDT
14240
+ * // # Partial Profit/Loss Report: BTCUSDT:my-strategy
14219
14241
  * //
14220
- * // | Action | Symbol | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
14221
- * // | --- | --- | --- | --- | --- | --- | --- | --- |
14222
- * // | PROFIT | BTCUSDT | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
14223
- * // | LOSS | BTCUSDT | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
14242
+ * // | Action | Symbol | Strategy | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
14243
+ * // | --- | --- | --- | --- | --- | --- | --- | --- | --- |
14244
+ * // | PROFIT | BTCUSDT | my-strategy | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
14245
+ * // | LOSS | BTCUSDT | my-strategy | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
14224
14246
  * //
14225
14247
  * // **Total events:** 2
14226
14248
  * // **Profit events:** 1
14227
14249
  * // **Loss events:** 1
14228
14250
  * ```
14229
14251
  */
14230
- this.getReport = async (symbol) => {
14231
- backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol });
14232
- return await backtest$1.partialMarkdownService.getReport(symbol);
14252
+ this.getReport = async (symbol, strategyName) => {
14253
+ backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
14254
+ return await backtest$1.partialMarkdownService.getReport(symbol, strategyName);
14233
14255
  };
14234
14256
  /**
14235
14257
  * Generates and saves markdown report to file.
14236
14258
  *
14237
14259
  * Creates directory if it doesn't exist.
14238
- * Filename format: {symbol}.md (e.g., "BTCUSDT.md")
14260
+ * Filename format: {symbol}_{strategyName}.md (e.g., "BTCUSDT_my-strategy.md")
14239
14261
  *
14240
14262
  * Delegates to PartialMarkdownService.dump() which:
14241
14263
  * 1. Generates markdown report via getReport()
@@ -14244,26 +14266,27 @@ class PartialUtils {
14244
14266
  * 4. Logs success/failure to console
14245
14267
  *
14246
14268
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
14269
+ * @param strategyName - Strategy name (e.g., "my-strategy")
14247
14270
  * @param path - Output directory path (default: "./dump/partial")
14248
14271
  * @returns Promise that resolves when file is written
14249
14272
  *
14250
14273
  * @example
14251
14274
  * ```typescript
14252
- * // Save to default path: ./dump/partial/BTCUSDT.md
14253
- * await Partial.dump("BTCUSDT");
14275
+ * // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
14276
+ * await Partial.dump("BTCUSDT", "my-strategy");
14254
14277
  *
14255
- * // Save to custom path: ./reports/partial/BTCUSDT.md
14256
- * await Partial.dump("BTCUSDT", "./reports/partial");
14278
+ * // Save to custom path: ./reports/partial/BTCUSDT_my-strategy.md
14279
+ * await Partial.dump("BTCUSDT", "my-strategy", "./reports/partial");
14257
14280
  *
14258
14281
  * // After multiple symbols backtested, export all reports
14259
14282
  * for (const symbol of ["BTCUSDT", "ETHUSDT", "BNBUSDT"]) {
14260
- * await Partial.dump(symbol, "./backtest-results");
14283
+ * await Partial.dump(symbol, "my-strategy", "./backtest-results");
14261
14284
  * }
14262
14285
  * ```
14263
14286
  */
14264
- this.dump = async (symbol, path) => {
14265
- backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, path });
14266
- await backtest$1.partialMarkdownService.dump(symbol, path);
14287
+ this.dump = async (symbol, strategyName, path) => {
14288
+ backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
14289
+ await backtest$1.partialMarkdownService.dump(symbol, strategyName, path);
14267
14290
  };
14268
14291
  }
14269
14292
  }
@@ -14276,9 +14299,9 @@ class PartialUtils {
14276
14299
  * import { Partial } from "backtest-kit";
14277
14300
  *
14278
14301
  * // Usage same as PartialUtils methods
14279
- * const stats = await Partial.getData("BTCUSDT");
14280
- * const report = await Partial.getReport("BTCUSDT");
14281
- * await Partial.dump("BTCUSDT");
14302
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
14303
+ * const report = await Partial.getReport("BTCUSDT", "my-strategy");
14304
+ * await Partial.dump("BTCUSDT", "my-strategy");
14282
14305
  * ```
14283
14306
  */
14284
14307
  const Partial = new PartialUtils();
package/build/index.mjs CHANGED
@@ -10462,6 +10462,11 @@ const columns = [
10462
10462
  label: "Symbol",
10463
10463
  format: (data) => data.symbol,
10464
10464
  },
10465
+ {
10466
+ key: "strategyName",
10467
+ label: "Strategy",
10468
+ format: (data) => data.strategyName,
10469
+ },
10465
10470
  {
10466
10471
  key: "signalId",
10467
10472
  label: "Signal ID",
@@ -10496,7 +10501,7 @@ const columns = [
10496
10501
  /** Maximum number of events to store in partial reports */
10497
10502
  const MAX_EVENTS = 250;
10498
10503
  /**
10499
- * Storage class for accumulating partial profit/loss events per symbol.
10504
+ * Storage class for accumulating partial profit/loss events per symbol-strategy pair.
10500
10505
  * Maintains a chronological list of profit and loss level events.
10501
10506
  */
10502
10507
  class ReportStorage {
@@ -10507,17 +10512,17 @@ class ReportStorage {
10507
10512
  /**
10508
10513
  * Adds a profit event to the storage.
10509
10514
  *
10510
- * @param symbol - Trading pair symbol
10511
10515
  * @param data - Signal row data
10512
10516
  * @param currentPrice - Current market price
10513
10517
  * @param level - Profit level reached
10514
10518
  * @param backtest - True if backtest mode
10515
10519
  */
10516
- addProfitEvent(symbol, data, currentPrice, level, backtest, timestamp) {
10520
+ addProfitEvent(data, currentPrice, level, backtest, timestamp) {
10517
10521
  this._eventList.push({
10518
10522
  timestamp,
10519
10523
  action: "profit",
10520
- symbol,
10524
+ symbol: data.symbol,
10525
+ strategyName: data.strategyName,
10521
10526
  signalId: data.id,
10522
10527
  position: data.position,
10523
10528
  currentPrice,
@@ -10532,17 +10537,17 @@ class ReportStorage {
10532
10537
  /**
10533
10538
  * Adds a loss event to the storage.
10534
10539
  *
10535
- * @param symbol - Trading pair symbol
10536
10540
  * @param data - Signal row data
10537
10541
  * @param currentPrice - Current market price
10538
10542
  * @param level - Loss level reached
10539
10543
  * @param backtest - True if backtest mode
10540
10544
  */
10541
- addLossEvent(symbol, data, currentPrice, level, backtest, timestamp) {
10545
+ addLossEvent(data, currentPrice, level, backtest, timestamp) {
10542
10546
  this._eventList.push({
10543
10547
  timestamp,
10544
10548
  action: "loss",
10545
- symbol,
10549
+ symbol: data.symbol,
10550
+ strategyName: data.strategyName,
10546
10551
  signalId: data.id,
10547
10552
  position: data.position,
10548
10553
  currentPrice,
@@ -10578,35 +10583,37 @@ class ReportStorage {
10578
10583
  };
10579
10584
  }
10580
10585
  /**
10581
- * Generates markdown report with all partial events for a symbol (View).
10586
+ * Generates markdown report with all partial events for a symbol-strategy pair (View).
10582
10587
  *
10583
10588
  * @param symbol - Trading pair symbol
10589
+ * @param strategyName - Strategy name
10584
10590
  * @returns Markdown formatted report with all events
10585
10591
  */
10586
- async getReport(symbol) {
10592
+ async getReport(symbol, strategyName) {
10587
10593
  const stats = await this.getData();
10588
10594
  if (stats.totalEvents === 0) {
10589
- return str.newline(`# Partial Profit/Loss Report: ${symbol}`, "", "No partial profit/loss events recorded yet.");
10595
+ return str.newline(`# Partial Profit/Loss Report: ${symbol}:${strategyName}`, "", "No partial profit/loss events recorded yet.");
10590
10596
  }
10591
10597
  const header = columns.map((col) => col.label);
10592
10598
  const separator = columns.map(() => "---");
10593
10599
  const rows = this._eventList.map((event) => columns.map((col) => col.format(event)));
10594
10600
  const tableData = [header, separator, ...rows];
10595
10601
  const table = str.newline(tableData.map((row) => `| ${row.join(" | ")} |`));
10596
- return str.newline(`# Partial Profit/Loss Report: ${symbol}`, "", table, "", `**Total events:** ${stats.totalEvents}`, `**Profit events:** ${stats.totalProfit}`, `**Loss events:** ${stats.totalLoss}`);
10602
+ return str.newline(`# Partial Profit/Loss Report: ${symbol}:${strategyName}`, "", table, "", `**Total events:** ${stats.totalEvents}`, `**Profit events:** ${stats.totalProfit}`, `**Loss events:** ${stats.totalLoss}`);
10597
10603
  }
10598
10604
  /**
10599
- * Saves symbol report to disk.
10605
+ * Saves symbol-strategy report to disk.
10600
10606
  *
10601
10607
  * @param symbol - Trading pair symbol
10608
+ * @param strategyName - Strategy name
10602
10609
  * @param path - Directory path to save report (default: "./dump/partial")
10603
10610
  */
10604
- async dump(symbol, path = "./dump/partial") {
10605
- const markdown = await this.getReport(symbol);
10611
+ async dump(symbol, strategyName, path = "./dump/partial") {
10612
+ const markdown = await this.getReport(symbol, strategyName);
10606
10613
  try {
10607
10614
  const dir = join(process.cwd(), path);
10608
10615
  await mkdir(dir, { recursive: true });
10609
- const filename = `${symbol}.md`;
10616
+ const filename = `${symbol}_${strategyName}.md`;
10610
10617
  const filepath = join(dir, filename);
10611
10618
  await writeFile(filepath, markdown, "utf-8");
10612
10619
  console.log(`Partial profit/loss report saved: ${filepath}`);
@@ -10621,10 +10628,10 @@ class ReportStorage {
10621
10628
  *
10622
10629
  * Features:
10623
10630
  * - Listens to partial profit and loss events via partialProfitSubject/partialLossSubject
10624
- * - Accumulates all events (profit, loss) per symbol
10631
+ * - Accumulates all events (profit, loss) per symbol-strategy pair
10625
10632
  * - Generates markdown tables with detailed event information
10626
10633
  * - Provides statistics (total profit/loss events)
10627
- * - Saves reports to disk in dump/partial/{symbol}.md
10634
+ * - Saves reports to disk in dump/partial/{symbol}_{strategyName}.md
10628
10635
  *
10629
10636
  * @example
10630
10637
  * ```typescript
@@ -10634,7 +10641,7 @@ class ReportStorage {
10634
10641
  * // No manual callback setup needed
10635
10642
  *
10636
10643
  * // Later: generate and save report
10637
- * await service.dump("BTCUSDT");
10644
+ * await service.dump("BTCUSDT", "my-strategy");
10638
10645
  * ```
10639
10646
  */
10640
10647
  class PartialMarkdownService {
@@ -10642,10 +10649,10 @@ class PartialMarkdownService {
10642
10649
  /** Logger service for debug output */
10643
10650
  this.loggerService = inject(TYPES.loggerService);
10644
10651
  /**
10645
- * Memoized function to get or create ReportStorage for a symbol.
10646
- * Each symbol gets its own isolated storage instance.
10652
+ * Memoized function to get or create ReportStorage for a symbol-strategy pair.
10653
+ * Each symbol-strategy combination gets its own isolated storage instance.
10647
10654
  */
10648
- this.getStorage = memoize(([symbol]) => `${symbol}`, () => new ReportStorage());
10655
+ this.getStorage = memoize(([symbol, strategyName]) => JSON.stringify([symbol, strategyName]), () => new ReportStorage());
10649
10656
  /**
10650
10657
  * Processes profit events and accumulates them.
10651
10658
  * Should be called from partialProfitSubject subscription.
@@ -10662,8 +10669,8 @@ class PartialMarkdownService {
10662
10669
  this.loggerService.log("partialMarkdownService tickProfit", {
10663
10670
  data,
10664
10671
  });
10665
- const storage = this.getStorage(data.symbol);
10666
- storage.addProfitEvent(data.symbol, data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10672
+ const storage = this.getStorage(data.symbol, data.data.strategyName);
10673
+ storage.addProfitEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10667
10674
  };
10668
10675
  /**
10669
10676
  * Processes loss events and accumulates them.
@@ -10681,101 +10688,113 @@ class PartialMarkdownService {
10681
10688
  this.loggerService.log("partialMarkdownService tickLoss", {
10682
10689
  data,
10683
10690
  });
10684
- const storage = this.getStorage(data.symbol);
10685
- storage.addLossEvent(data.symbol, data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10691
+ const storage = this.getStorage(data.symbol, data.data.strategyName);
10692
+ storage.addLossEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
10686
10693
  };
10687
10694
  /**
10688
- * Gets statistical data from all partial profit/loss events for a symbol.
10695
+ * Gets statistical data from all partial profit/loss events for a symbol-strategy pair.
10689
10696
  * Delegates to ReportStorage.getData().
10690
10697
  *
10691
10698
  * @param symbol - Trading pair symbol to get data for
10699
+ * @param strategyName - Strategy name to get data for
10692
10700
  * @returns Statistical data object with all metrics
10693
10701
  *
10694
10702
  * @example
10695
10703
  * ```typescript
10696
10704
  * const service = new PartialMarkdownService();
10697
- * const stats = await service.getData("BTCUSDT");
10705
+ * const stats = await service.getData("BTCUSDT", "my-strategy");
10698
10706
  * console.log(stats.totalProfit, stats.totalLoss);
10699
10707
  * ```
10700
10708
  */
10701
- this.getData = async (symbol) => {
10709
+ this.getData = async (symbol, strategyName) => {
10702
10710
  this.loggerService.log("partialMarkdownService getData", {
10703
10711
  symbol,
10712
+ strategyName,
10704
10713
  });
10705
- const storage = this.getStorage(symbol);
10714
+ const storage = this.getStorage(symbol, strategyName);
10706
10715
  return storage.getData();
10707
10716
  };
10708
10717
  /**
10709
- * Generates markdown report with all partial events for a symbol.
10718
+ * Generates markdown report with all partial events for a symbol-strategy pair.
10710
10719
  * Delegates to ReportStorage.getReport().
10711
10720
  *
10712
10721
  * @param symbol - Trading pair symbol to generate report for
10722
+ * @param strategyName - Strategy name to generate report for
10713
10723
  * @returns Markdown formatted report string with table of all events
10714
10724
  *
10715
10725
  * @example
10716
10726
  * ```typescript
10717
10727
  * const service = new PartialMarkdownService();
10718
- * const markdown = await service.getReport("BTCUSDT");
10728
+ * const markdown = await service.getReport("BTCUSDT", "my-strategy");
10719
10729
  * console.log(markdown);
10720
10730
  * ```
10721
10731
  */
10722
- this.getReport = async (symbol) => {
10732
+ this.getReport = async (symbol, strategyName) => {
10723
10733
  this.loggerService.log("partialMarkdownService getReport", {
10724
10734
  symbol,
10735
+ strategyName,
10725
10736
  });
10726
- const storage = this.getStorage(symbol);
10727
- return storage.getReport(symbol);
10737
+ const storage = this.getStorage(symbol, strategyName);
10738
+ return storage.getReport(symbol, strategyName);
10728
10739
  };
10729
10740
  /**
10730
- * Saves symbol report to disk.
10741
+ * Saves symbol-strategy report to disk.
10731
10742
  * Creates directory if it doesn't exist.
10732
10743
  * Delegates to ReportStorage.dump().
10733
10744
  *
10734
10745
  * @param symbol - Trading pair symbol to save report for
10746
+ * @param strategyName - Strategy name to save report for
10735
10747
  * @param path - Directory path to save report (default: "./dump/partial")
10736
10748
  *
10737
10749
  * @example
10738
10750
  * ```typescript
10739
10751
  * const service = new PartialMarkdownService();
10740
10752
  *
10741
- * // Save to default path: ./dump/partial/BTCUSDT.md
10742
- * await service.dump("BTCUSDT");
10753
+ * // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
10754
+ * await service.dump("BTCUSDT", "my-strategy");
10743
10755
  *
10744
- * // Save to custom path: ./custom/path/BTCUSDT.md
10745
- * await service.dump("BTCUSDT", "./custom/path");
10756
+ * // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
10757
+ * await service.dump("BTCUSDT", "my-strategy", "./custom/path");
10746
10758
  * ```
10747
10759
  */
10748
- this.dump = async (symbol, path = "./dump/partial") => {
10760
+ this.dump = async (symbol, strategyName, path = "./dump/partial") => {
10749
10761
  this.loggerService.log("partialMarkdownService dump", {
10750
10762
  symbol,
10763
+ strategyName,
10751
10764
  path,
10752
10765
  });
10753
- const storage = this.getStorage(symbol);
10754
- await storage.dump(symbol, path);
10766
+ const storage = this.getStorage(symbol, strategyName);
10767
+ await storage.dump(symbol, strategyName, path);
10755
10768
  };
10756
10769
  /**
10757
10770
  * Clears accumulated event data from storage.
10758
- * If symbol is provided, clears only that symbol's data.
10759
- * If symbol is omitted, clears all symbols' data.
10771
+ * If ctx is provided, clears only that specific symbol-strategy pair's data.
10772
+ * If nothing is provided, clears all data.
10760
10773
  *
10761
- * @param symbol - Optional symbol to clear specific symbol data
10774
+ * @param ctx - Optional context with symbol and strategyName
10762
10775
  *
10763
10776
  * @example
10764
10777
  * ```typescript
10765
10778
  * const service = new PartialMarkdownService();
10766
10779
  *
10767
- * // Clear specific symbol data
10768
- * await service.clear("BTCUSDT");
10780
+ * // Clear specific symbol-strategy pair
10781
+ * await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
10769
10782
  *
10770
- * // Clear all symbols' data
10783
+ * // Clear all data
10771
10784
  * await service.clear();
10772
10785
  * ```
10773
10786
  */
10774
- this.clear = async (symbol) => {
10787
+ this.clear = async (ctx) => {
10775
10788
  this.loggerService.log("partialMarkdownService clear", {
10776
- symbol,
10789
+ ctx,
10777
10790
  });
10778
- this.getStorage.clear(symbol);
10791
+ if (ctx) {
10792
+ const key = JSON.stringify([ctx.symbol, ctx.strategyName]);
10793
+ this.getStorage.clear(key);
10794
+ }
10795
+ else {
10796
+ this.getStorage.clear();
10797
+ }
10779
10798
  };
10780
10799
  /**
10781
10800
  * Initializes the service by subscribing to partial profit/loss events.
@@ -14138,26 +14157,26 @@ const PARTIAL_METHOD_NAME_DUMP = "PartialUtils.dump";
14138
14157
  *
14139
14158
  * Data source:
14140
14159
  * - PartialMarkdownService listens to partialProfitSubject/partialLossSubject
14141
- * - Accumulates events in ReportStorage (max 250 events per symbol)
14142
- * - Events include: timestamp, action, symbol, signalId, position, level, price, mode
14160
+ * - Accumulates events in ReportStorage (max 250 events per symbol-strategy pair)
14161
+ * - Events include: timestamp, action, symbol, strategyName, signalId, position, level, price, mode
14143
14162
  *
14144
14163
  * @example
14145
14164
  * ```typescript
14146
14165
  * import { Partial } from "./classes/Partial";
14147
14166
  *
14148
- * // Get statistical data for BTCUSDT
14149
- * const stats = await Partial.getData("BTCUSDT");
14167
+ * // Get statistical data for BTCUSDT:my-strategy
14168
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
14150
14169
  * console.log(`Total events: ${stats.totalEvents}`);
14151
14170
  * console.log(`Profit events: ${stats.totalProfit}`);
14152
14171
  * console.log(`Loss events: ${stats.totalLoss}`);
14153
14172
  *
14154
14173
  * // Generate markdown report
14155
- * const markdown = await Partial.getReport("BTCUSDT");
14174
+ * const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
14156
14175
  * console.log(markdown); // Formatted table with all events
14157
14176
  *
14158
14177
  * // Export report to file
14159
- * await Partial.dump("BTCUSDT"); // Saves to ./dump/partial/BTCUSDT.md
14160
- * await Partial.dump("BTCUSDT", "./custom/path"); // Custom directory
14178
+ * await Partial.dump("BTCUSDT", "my-strategy"); // Saves to ./dump/partial/BTCUSDT_my-strategy.md
14179
+ * await Partial.dump("BTCUSDT", "my-strategy", "./custom/path"); // Custom directory
14161
14180
  * ```
14162
14181
  */
14163
14182
  class PartialUtils {
@@ -14169,11 +14188,12 @@ class PartialUtils {
14169
14188
  * Returns aggregated metrics calculated from all profit and loss events.
14170
14189
  *
14171
14190
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
14191
+ * @param strategyName - Strategy name (e.g., "my-strategy")
14172
14192
  * @returns Promise resolving to PartialStatistics object with counts and event list
14173
14193
  *
14174
14194
  * @example
14175
14195
  * ```typescript
14176
- * const stats = await Partial.getData("BTCUSDT");
14196
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
14177
14197
  *
14178
14198
  * console.log(`Total events: ${stats.totalEvents}`);
14179
14199
  * console.log(`Profit events: ${stats.totalProfit} (${(stats.totalProfit / stats.totalEvents * 100).toFixed(1)}%)`);
@@ -14185,16 +14205,17 @@ class PartialUtils {
14185
14205
  * }
14186
14206
  * ```
14187
14207
  */
14188
- this.getData = async (symbol) => {
14189
- backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol });
14190
- return await backtest$1.partialMarkdownService.getData(symbol);
14208
+ this.getData = async (symbol, strategyName) => {
14209
+ backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
14210
+ return await backtest$1.partialMarkdownService.getData(symbol, strategyName);
14191
14211
  };
14192
14212
  /**
14193
- * Generates markdown report with all partial profit/loss events for a symbol.
14213
+ * Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
14194
14214
  *
14195
14215
  * Creates formatted table containing:
14196
14216
  * - Action (PROFIT/LOSS)
14197
14217
  * - Symbol
14218
+ * - Strategy
14198
14219
  * - Signal ID
14199
14220
  * - Position (LONG/SHORT)
14200
14221
  * - Level % (+10%, -20%, etc)
@@ -14205,35 +14226,36 @@ class PartialUtils {
14205
14226
  * Also includes summary statistics at the end.
14206
14227
  *
14207
14228
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
14229
+ * @param strategyName - Strategy name (e.g., "my-strategy")
14208
14230
  * @returns Promise resolving to markdown formatted report string
14209
14231
  *
14210
14232
  * @example
14211
14233
  * ```typescript
14212
- * const markdown = await Partial.getReport("BTCUSDT");
14234
+ * const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
14213
14235
  * console.log(markdown);
14214
14236
  *
14215
14237
  * // Output:
14216
- * // # Partial Profit/Loss Report: BTCUSDT
14238
+ * // # Partial Profit/Loss Report: BTCUSDT:my-strategy
14217
14239
  * //
14218
- * // | Action | Symbol | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
14219
- * // | --- | --- | --- | --- | --- | --- | --- | --- |
14220
- * // | PROFIT | BTCUSDT | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
14221
- * // | LOSS | BTCUSDT | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
14240
+ * // | Action | Symbol | Strategy | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
14241
+ * // | --- | --- | --- | --- | --- | --- | --- | --- | --- |
14242
+ * // | PROFIT | BTCUSDT | my-strategy | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
14243
+ * // | LOSS | BTCUSDT | my-strategy | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
14222
14244
  * //
14223
14245
  * // **Total events:** 2
14224
14246
  * // **Profit events:** 1
14225
14247
  * // **Loss events:** 1
14226
14248
  * ```
14227
14249
  */
14228
- this.getReport = async (symbol) => {
14229
- backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol });
14230
- return await backtest$1.partialMarkdownService.getReport(symbol);
14250
+ this.getReport = async (symbol, strategyName) => {
14251
+ backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
14252
+ return await backtest$1.partialMarkdownService.getReport(symbol, strategyName);
14231
14253
  };
14232
14254
  /**
14233
14255
  * Generates and saves markdown report to file.
14234
14256
  *
14235
14257
  * Creates directory if it doesn't exist.
14236
- * Filename format: {symbol}.md (e.g., "BTCUSDT.md")
14258
+ * Filename format: {symbol}_{strategyName}.md (e.g., "BTCUSDT_my-strategy.md")
14237
14259
  *
14238
14260
  * Delegates to PartialMarkdownService.dump() which:
14239
14261
  * 1. Generates markdown report via getReport()
@@ -14242,26 +14264,27 @@ class PartialUtils {
14242
14264
  * 4. Logs success/failure to console
14243
14265
  *
14244
14266
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
14267
+ * @param strategyName - Strategy name (e.g., "my-strategy")
14245
14268
  * @param path - Output directory path (default: "./dump/partial")
14246
14269
  * @returns Promise that resolves when file is written
14247
14270
  *
14248
14271
  * @example
14249
14272
  * ```typescript
14250
- * // Save to default path: ./dump/partial/BTCUSDT.md
14251
- * await Partial.dump("BTCUSDT");
14273
+ * // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
14274
+ * await Partial.dump("BTCUSDT", "my-strategy");
14252
14275
  *
14253
- * // Save to custom path: ./reports/partial/BTCUSDT.md
14254
- * await Partial.dump("BTCUSDT", "./reports/partial");
14276
+ * // Save to custom path: ./reports/partial/BTCUSDT_my-strategy.md
14277
+ * await Partial.dump("BTCUSDT", "my-strategy", "./reports/partial");
14255
14278
  *
14256
14279
  * // After multiple symbols backtested, export all reports
14257
14280
  * for (const symbol of ["BTCUSDT", "ETHUSDT", "BNBUSDT"]) {
14258
- * await Partial.dump(symbol, "./backtest-results");
14281
+ * await Partial.dump(symbol, "my-strategy", "./backtest-results");
14259
14282
  * }
14260
14283
  * ```
14261
14284
  */
14262
- this.dump = async (symbol, path) => {
14263
- backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, path });
14264
- await backtest$1.partialMarkdownService.dump(symbol, path);
14285
+ this.dump = async (symbol, strategyName, path) => {
14286
+ backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
14287
+ await backtest$1.partialMarkdownService.dump(symbol, strategyName, path);
14265
14288
  };
14266
14289
  }
14267
14290
  }
@@ -14274,9 +14297,9 @@ class PartialUtils {
14274
14297
  * import { Partial } from "backtest-kit";
14275
14298
  *
14276
14299
  * // Usage same as PartialUtils methods
14277
- * const stats = await Partial.getData("BTCUSDT");
14278
- * const report = await Partial.getReport("BTCUSDT");
14279
- * await Partial.dump("BTCUSDT");
14300
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
14301
+ * const report = await Partial.getReport("BTCUSDT", "my-strategy");
14302
+ * await Partial.dump("BTCUSDT", "my-strategy");
14280
14303
  * ```
14281
14304
  */
14282
14305
  const Partial = new PartialUtils();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "1.4.12",
3
+ "version": "1.4.13",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",
package/types.d.ts CHANGED
@@ -4493,6 +4493,8 @@ interface PartialEvent {
4493
4493
  action: "profit" | "loss";
4494
4494
  /** Trading pair symbol */
4495
4495
  symbol: string;
4496
+ /** Strategy name */
4497
+ strategyName: string;
4496
4498
  /** Signal ID */
4497
4499
  signalId: string;
4498
4500
  /** Position type */
@@ -4511,7 +4513,7 @@ interface PartialEvent {
4511
4513
  *
4512
4514
  * @example
4513
4515
  * ```typescript
4514
- * const stats = await Partial.getData("my-strategy");
4516
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
4515
4517
  *
4516
4518
  * console.log(`Total events: ${stats.totalEvents}`);
4517
4519
  * console.log(`Profit events: ${stats.totalProfit}`);
@@ -4533,10 +4535,10 @@ interface PartialStatistics {
4533
4535
  *
4534
4536
  * Features:
4535
4537
  * - Listens to partial profit and loss events via partialProfitSubject/partialLossSubject
4536
- * - Accumulates all events (profit, loss) per symbol
4538
+ * - Accumulates all events (profit, loss) per symbol-strategy pair
4537
4539
  * - Generates markdown tables with detailed event information
4538
4540
  * - Provides statistics (total profit/loss events)
4539
- * - Saves reports to disk in dump/partial/{symbol}.md
4541
+ * - Saves reports to disk in dump/partial/{symbol}_{strategyName}.md
4540
4542
  *
4541
4543
  * @example
4542
4544
  * ```typescript
@@ -4546,15 +4548,15 @@ interface PartialStatistics {
4546
4548
  * // No manual callback setup needed
4547
4549
  *
4548
4550
  * // Later: generate and save report
4549
- * await service.dump("BTCUSDT");
4551
+ * await service.dump("BTCUSDT", "my-strategy");
4550
4552
  * ```
4551
4553
  */
4552
4554
  declare class PartialMarkdownService {
4553
4555
  /** Logger service for debug output */
4554
4556
  private readonly loggerService;
4555
4557
  /**
4556
- * Memoized function to get or create ReportStorage for a symbol.
4557
- * Each symbol gets its own isolated storage instance.
4558
+ * Memoized function to get or create ReportStorage for a symbol-strategy pair.
4559
+ * Each symbol-strategy combination gets its own isolated storage instance.
4558
4560
  */
4559
4561
  private getStorage;
4560
4562
  /**
@@ -4584,74 +4586,80 @@ declare class PartialMarkdownService {
4584
4586
  */
4585
4587
  private tickLoss;
4586
4588
  /**
4587
- * Gets statistical data from all partial profit/loss events for a symbol.
4589
+ * Gets statistical data from all partial profit/loss events for a symbol-strategy pair.
4588
4590
  * Delegates to ReportStorage.getData().
4589
4591
  *
4590
4592
  * @param symbol - Trading pair symbol to get data for
4593
+ * @param strategyName - Strategy name to get data for
4591
4594
  * @returns Statistical data object with all metrics
4592
4595
  *
4593
4596
  * @example
4594
4597
  * ```typescript
4595
4598
  * const service = new PartialMarkdownService();
4596
- * const stats = await service.getData("BTCUSDT");
4599
+ * const stats = await service.getData("BTCUSDT", "my-strategy");
4597
4600
  * console.log(stats.totalProfit, stats.totalLoss);
4598
4601
  * ```
4599
4602
  */
4600
- getData: (symbol: string) => Promise<PartialStatistics>;
4603
+ getData: (symbol: string, strategyName: string) => Promise<PartialStatistics>;
4601
4604
  /**
4602
- * Generates markdown report with all partial events for a symbol.
4605
+ * Generates markdown report with all partial events for a symbol-strategy pair.
4603
4606
  * Delegates to ReportStorage.getReport().
4604
4607
  *
4605
4608
  * @param symbol - Trading pair symbol to generate report for
4609
+ * @param strategyName - Strategy name to generate report for
4606
4610
  * @returns Markdown formatted report string with table of all events
4607
4611
  *
4608
4612
  * @example
4609
4613
  * ```typescript
4610
4614
  * const service = new PartialMarkdownService();
4611
- * const markdown = await service.getReport("BTCUSDT");
4615
+ * const markdown = await service.getReport("BTCUSDT", "my-strategy");
4612
4616
  * console.log(markdown);
4613
4617
  * ```
4614
4618
  */
4615
- getReport: (symbol: string) => Promise<string>;
4619
+ getReport: (symbol: string, strategyName: string) => Promise<string>;
4616
4620
  /**
4617
- * Saves symbol report to disk.
4621
+ * Saves symbol-strategy report to disk.
4618
4622
  * Creates directory if it doesn't exist.
4619
4623
  * Delegates to ReportStorage.dump().
4620
4624
  *
4621
4625
  * @param symbol - Trading pair symbol to save report for
4626
+ * @param strategyName - Strategy name to save report for
4622
4627
  * @param path - Directory path to save report (default: "./dump/partial")
4623
4628
  *
4624
4629
  * @example
4625
4630
  * ```typescript
4626
4631
  * const service = new PartialMarkdownService();
4627
4632
  *
4628
- * // Save to default path: ./dump/partial/BTCUSDT.md
4629
- * await service.dump("BTCUSDT");
4633
+ * // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
4634
+ * await service.dump("BTCUSDT", "my-strategy");
4630
4635
  *
4631
- * // Save to custom path: ./custom/path/BTCUSDT.md
4632
- * await service.dump("BTCUSDT", "./custom/path");
4636
+ * // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
4637
+ * await service.dump("BTCUSDT", "my-strategy", "./custom/path");
4633
4638
  * ```
4634
4639
  */
4635
- dump: (symbol: string, path?: string) => Promise<void>;
4640
+ dump: (symbol: string, strategyName: string, path?: string) => Promise<void>;
4636
4641
  /**
4637
4642
  * Clears accumulated event data from storage.
4638
- * If symbol is provided, clears only that symbol's data.
4639
- * If symbol is omitted, clears all symbols' data.
4643
+ * If ctx is provided, clears only that specific symbol-strategy pair's data.
4644
+ * If nothing is provided, clears all data.
4640
4645
  *
4641
- * @param symbol - Optional symbol to clear specific symbol data
4646
+ * @param ctx - Optional context with symbol and strategyName
4642
4647
  *
4643
4648
  * @example
4644
4649
  * ```typescript
4645
4650
  * const service = new PartialMarkdownService();
4646
4651
  *
4647
- * // Clear specific symbol data
4648
- * await service.clear("BTCUSDT");
4652
+ * // Clear specific symbol-strategy pair
4653
+ * await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
4649
4654
  *
4650
- * // Clear all symbols' data
4655
+ * // Clear all data
4651
4656
  * await service.clear();
4652
4657
  * ```
4653
4658
  */
4654
- clear: (symbol?: string) => Promise<void>;
4659
+ clear: (ctx?: {
4660
+ symbol: string;
4661
+ strategyName: string;
4662
+ }) => Promise<void>;
4655
4663
  /**
4656
4664
  * Initializes the service by subscribing to partial profit/loss events.
4657
4665
  * Uses singleshot to ensure initialization happens only once.
@@ -5972,26 +5980,26 @@ declare const Optimizer: OptimizerUtils;
5972
5980
  *
5973
5981
  * Data source:
5974
5982
  * - PartialMarkdownService listens to partialProfitSubject/partialLossSubject
5975
- * - Accumulates events in ReportStorage (max 250 events per symbol)
5976
- * - Events include: timestamp, action, symbol, signalId, position, level, price, mode
5983
+ * - Accumulates events in ReportStorage (max 250 events per symbol-strategy pair)
5984
+ * - Events include: timestamp, action, symbol, strategyName, signalId, position, level, price, mode
5977
5985
  *
5978
5986
  * @example
5979
5987
  * ```typescript
5980
5988
  * import { Partial } from "./classes/Partial";
5981
5989
  *
5982
- * // Get statistical data for BTCUSDT
5983
- * const stats = await Partial.getData("BTCUSDT");
5990
+ * // Get statistical data for BTCUSDT:my-strategy
5991
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
5984
5992
  * console.log(`Total events: ${stats.totalEvents}`);
5985
5993
  * console.log(`Profit events: ${stats.totalProfit}`);
5986
5994
  * console.log(`Loss events: ${stats.totalLoss}`);
5987
5995
  *
5988
5996
  * // Generate markdown report
5989
- * const markdown = await Partial.getReport("BTCUSDT");
5997
+ * const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
5990
5998
  * console.log(markdown); // Formatted table with all events
5991
5999
  *
5992
6000
  * // Export report to file
5993
- * await Partial.dump("BTCUSDT"); // Saves to ./dump/partial/BTCUSDT.md
5994
- * await Partial.dump("BTCUSDT", "./custom/path"); // Custom directory
6001
+ * await Partial.dump("BTCUSDT", "my-strategy"); // Saves to ./dump/partial/BTCUSDT_my-strategy.md
6002
+ * await Partial.dump("BTCUSDT", "my-strategy", "./custom/path"); // Custom directory
5995
6003
  * ```
5996
6004
  */
5997
6005
  declare class PartialUtils {
@@ -6002,11 +6010,12 @@ declare class PartialUtils {
6002
6010
  * Returns aggregated metrics calculated from all profit and loss events.
6003
6011
  *
6004
6012
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
6013
+ * @param strategyName - Strategy name (e.g., "my-strategy")
6005
6014
  * @returns Promise resolving to PartialStatistics object with counts and event list
6006
6015
  *
6007
6016
  * @example
6008
6017
  * ```typescript
6009
- * const stats = await Partial.getData("BTCUSDT");
6018
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
6010
6019
  *
6011
6020
  * console.log(`Total events: ${stats.totalEvents}`);
6012
6021
  * console.log(`Profit events: ${stats.totalProfit} (${(stats.totalProfit / stats.totalEvents * 100).toFixed(1)}%)`);
@@ -6018,13 +6027,14 @@ declare class PartialUtils {
6018
6027
  * }
6019
6028
  * ```
6020
6029
  */
6021
- getData: (symbol: string) => Promise<PartialStatistics>;
6030
+ getData: (symbol: string, strategyName: string) => Promise<PartialStatistics>;
6022
6031
  /**
6023
- * Generates markdown report with all partial profit/loss events for a symbol.
6032
+ * Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
6024
6033
  *
6025
6034
  * Creates formatted table containing:
6026
6035
  * - Action (PROFIT/LOSS)
6027
6036
  * - Symbol
6037
+ * - Strategy
6028
6038
  * - Signal ID
6029
6039
  * - Position (LONG/SHORT)
6030
6040
  * - Level % (+10%, -20%, etc)
@@ -6035,32 +6045,33 @@ declare class PartialUtils {
6035
6045
  * Also includes summary statistics at the end.
6036
6046
  *
6037
6047
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
6048
+ * @param strategyName - Strategy name (e.g., "my-strategy")
6038
6049
  * @returns Promise resolving to markdown formatted report string
6039
6050
  *
6040
6051
  * @example
6041
6052
  * ```typescript
6042
- * const markdown = await Partial.getReport("BTCUSDT");
6053
+ * const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
6043
6054
  * console.log(markdown);
6044
6055
  *
6045
6056
  * // Output:
6046
- * // # Partial Profit/Loss Report: BTCUSDT
6057
+ * // # Partial Profit/Loss Report: BTCUSDT:my-strategy
6047
6058
  * //
6048
- * // | Action | Symbol | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
6049
- * // | --- | --- | --- | --- | --- | --- | --- | --- |
6050
- * // | PROFIT | BTCUSDT | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
6051
- * // | LOSS | BTCUSDT | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
6059
+ * // | Action | Symbol | Strategy | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
6060
+ * // | --- | --- | --- | --- | --- | --- | --- | --- | --- |
6061
+ * // | PROFIT | BTCUSDT | my-strategy | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
6062
+ * // | LOSS | BTCUSDT | my-strategy | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
6052
6063
  * //
6053
6064
  * // **Total events:** 2
6054
6065
  * // **Profit events:** 1
6055
6066
  * // **Loss events:** 1
6056
6067
  * ```
6057
6068
  */
6058
- getReport: (symbol: string) => Promise<string>;
6069
+ getReport: (symbol: string, strategyName: string) => Promise<string>;
6059
6070
  /**
6060
6071
  * Generates and saves markdown report to file.
6061
6072
  *
6062
6073
  * Creates directory if it doesn't exist.
6063
- * Filename format: {symbol}.md (e.g., "BTCUSDT.md")
6074
+ * Filename format: {symbol}_{strategyName}.md (e.g., "BTCUSDT_my-strategy.md")
6064
6075
  *
6065
6076
  * Delegates to PartialMarkdownService.dump() which:
6066
6077
  * 1. Generates markdown report via getReport()
@@ -6069,24 +6080,25 @@ declare class PartialUtils {
6069
6080
  * 4. Logs success/failure to console
6070
6081
  *
6071
6082
  * @param symbol - Trading pair symbol (e.g., "BTCUSDT")
6083
+ * @param strategyName - Strategy name (e.g., "my-strategy")
6072
6084
  * @param path - Output directory path (default: "./dump/partial")
6073
6085
  * @returns Promise that resolves when file is written
6074
6086
  *
6075
6087
  * @example
6076
6088
  * ```typescript
6077
- * // Save to default path: ./dump/partial/BTCUSDT.md
6078
- * await Partial.dump("BTCUSDT");
6089
+ * // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
6090
+ * await Partial.dump("BTCUSDT", "my-strategy");
6079
6091
  *
6080
- * // Save to custom path: ./reports/partial/BTCUSDT.md
6081
- * await Partial.dump("BTCUSDT", "./reports/partial");
6092
+ * // Save to custom path: ./reports/partial/BTCUSDT_my-strategy.md
6093
+ * await Partial.dump("BTCUSDT", "my-strategy", "./reports/partial");
6082
6094
  *
6083
6095
  * // After multiple symbols backtested, export all reports
6084
6096
  * for (const symbol of ["BTCUSDT", "ETHUSDT", "BNBUSDT"]) {
6085
- * await Partial.dump(symbol, "./backtest-results");
6097
+ * await Partial.dump(symbol, "my-strategy", "./backtest-results");
6086
6098
  * }
6087
6099
  * ```
6088
6100
  */
6089
- dump: (symbol: string, path?: string) => Promise<void>;
6101
+ dump: (symbol: string, strategyName: string, path?: string) => Promise<void>;
6090
6102
  }
6091
6103
  /**
6092
6104
  * Global singleton instance of PartialUtils.
@@ -6097,9 +6109,9 @@ declare class PartialUtils {
6097
6109
  * import { Partial } from "backtest-kit";
6098
6110
  *
6099
6111
  * // Usage same as PartialUtils methods
6100
- * const stats = await Partial.getData("BTCUSDT");
6101
- * const report = await Partial.getReport("BTCUSDT");
6102
- * await Partial.dump("BTCUSDT");
6112
+ * const stats = await Partial.getData("BTCUSDT", "my-strategy");
6113
+ * const report = await Partial.getReport("BTCUSDT", "my-strategy");
6114
+ * await Partial.dump("BTCUSDT", "my-strategy");
6103
6115
  * ```
6104
6116
  */
6105
6117
  declare const Partial$1: PartialUtils;