backtest-kit 1.11.5 → 1.11.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.cjs CHANGED
@@ -10217,6 +10217,48 @@ const partial_columns = [
10217
10217
  format: (data) => `${data.currentPrice.toFixed(8)} USD`,
10218
10218
  isVisible: () => true,
10219
10219
  },
10220
+ {
10221
+ key: "priceOpen",
10222
+ label: "Entry Price",
10223
+ format: (data) => (data.priceOpen ? `${data.priceOpen.toFixed(8)} USD` : "N/A"),
10224
+ isVisible: () => true,
10225
+ },
10226
+ {
10227
+ key: "priceTakeProfit",
10228
+ label: "Take Profit",
10229
+ format: (data) => (data.priceTakeProfit ? `${data.priceTakeProfit.toFixed(8)} USD` : "N/A"),
10230
+ isVisible: () => true,
10231
+ },
10232
+ {
10233
+ key: "priceStopLoss",
10234
+ label: "Stop Loss",
10235
+ format: (data) => (data.priceStopLoss ? `${data.priceStopLoss.toFixed(8)} USD` : "N/A"),
10236
+ isVisible: () => true,
10237
+ },
10238
+ {
10239
+ key: "originalPriceTakeProfit",
10240
+ label: "Original TP",
10241
+ format: (data) => (data.originalPriceTakeProfit ? `${data.originalPriceTakeProfit.toFixed(8)} USD` : "N/A"),
10242
+ isVisible: () => true,
10243
+ },
10244
+ {
10245
+ key: "originalPriceStopLoss",
10246
+ label: "Original SL",
10247
+ format: (data) => (data.originalPriceStopLoss ? `${data.originalPriceStopLoss.toFixed(8)} USD` : "N/A"),
10248
+ isVisible: () => true,
10249
+ },
10250
+ {
10251
+ key: "totalExecuted",
10252
+ label: "Total Executed %",
10253
+ format: (data) => (data.totalExecuted !== undefined ? `${data.totalExecuted.toFixed(2)}%` : "N/A"),
10254
+ isVisible: () => true,
10255
+ },
10256
+ {
10257
+ key: "note",
10258
+ label: "Note",
10259
+ format: (data) => data.note || "",
10260
+ isVisible: () => GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE,
10261
+ },
10220
10262
  {
10221
10263
  key: "timestamp",
10222
10264
  label: "Timestamp",
@@ -10303,6 +10345,42 @@ const breakeven_columns = [
10303
10345
  format: (data) => `${data.currentPrice.toFixed(8)} USD`,
10304
10346
  isVisible: () => true,
10305
10347
  },
10348
+ {
10349
+ key: "priceTakeProfit",
10350
+ label: "Take Profit",
10351
+ format: (data) => (data.priceTakeProfit ? `${data.priceTakeProfit.toFixed(8)} USD` : "N/A"),
10352
+ isVisible: () => true,
10353
+ },
10354
+ {
10355
+ key: "priceStopLoss",
10356
+ label: "Stop Loss",
10357
+ format: (data) => (data.priceStopLoss ? `${data.priceStopLoss.toFixed(8)} USD` : "N/A"),
10358
+ isVisible: () => true,
10359
+ },
10360
+ {
10361
+ key: "originalPriceTakeProfit",
10362
+ label: "Original TP",
10363
+ format: (data) => (data.originalPriceTakeProfit ? `${data.originalPriceTakeProfit.toFixed(8)} USD` : "N/A"),
10364
+ isVisible: () => true,
10365
+ },
10366
+ {
10367
+ key: "originalPriceStopLoss",
10368
+ label: "Original SL",
10369
+ format: (data) => (data.originalPriceStopLoss ? `${data.originalPriceStopLoss.toFixed(8)} USD` : "N/A"),
10370
+ isVisible: () => true,
10371
+ },
10372
+ {
10373
+ key: "totalExecuted",
10374
+ label: "Total Executed %",
10375
+ format: (data) => (data.totalExecuted !== undefined ? `${data.totalExecuted.toFixed(2)}%` : "N/A"),
10376
+ isVisible: () => true,
10377
+ },
10378
+ {
10379
+ key: "note",
10380
+ label: "Note",
10381
+ format: (data) => data.note || "",
10382
+ isVisible: () => GLOBAL_CONFIG.CC_REPORT_SHOW_SIGNAL_NOTE,
10383
+ },
10306
10384
  {
10307
10385
  key: "timestamp",
10308
10386
  label: "Timestamp",
@@ -10960,6 +11038,7 @@ const DEFAULT_COLUMNS = Object.freeze({ ...COLUMN_CONFIG });
10960
11038
 
10961
11039
  var _a$1, _b$1, _c$1;
10962
11040
  const MARKDOWN_METHOD_NAME_ENABLE = "MarkdownUtils.enable";
11041
+ const MARKDOWN_METHOD_NAME_DISABLE = "MarkdownUtils.disable";
10963
11042
  const MARKDOWN_METHOD_NAME_USE_ADAPTER = "MarkdownAdapter.useMarkdownAdapter";
10964
11043
  const WAIT_FOR_INIT_SYMBOL$1 = Symbol("wait-for-init");
10965
11044
  const WRITE_SAFE_SYMBOL$1 = Symbol("write-safe");
@@ -11244,6 +11323,83 @@ class MarkdownUtils {
11244
11323
  }
11245
11324
  return functoolsKit.compose(...unList.map((un) => () => void un()));
11246
11325
  };
11326
+ /**
11327
+ * Disables markdown report services selectively.
11328
+ *
11329
+ * Unsubscribes from specified markdown services to stop report generation.
11330
+ * Use this method to stop markdown report generation for specific services while keeping others active.
11331
+ *
11332
+ * Each disabled service will:
11333
+ * - Stop listening to events immediately
11334
+ * - Stop accumulating data for reports
11335
+ * - Stop generating markdown files
11336
+ * - Free up event listener and memory resources
11337
+ *
11338
+ * Unlike enable(), this method does NOT return an unsubscribe function.
11339
+ * Services are unsubscribed immediately upon calling this method.
11340
+ *
11341
+ * @param config - Service configuration object specifying which services to disable. Defaults to disabling all services.
11342
+ * @param config.backtest - Disable backtest result reports with full trade history
11343
+ * @param config.breakeven - Disable breakeven event tracking
11344
+ * @param config.partial - Disable partial profit/loss event tracking
11345
+ * @param config.heat - Disable portfolio heatmap analysis
11346
+ * @param config.walker - Disable walker strategy comparison reports
11347
+ * @param config.performance - Disable performance bottleneck analysis
11348
+ * @param config.risk - Disable risk rejection tracking
11349
+ * @param config.schedule - Disable scheduled signal tracking
11350
+ * @param config.live - Disable live trading event reports
11351
+ *
11352
+ * @example
11353
+ * ```typescript
11354
+ * import { Markdown } from "backtest-kit";
11355
+ *
11356
+ * // Disable specific services
11357
+ * Markdown.disable({ backtest: true, walker: true });
11358
+ *
11359
+ * // Disable all services
11360
+ * Markdown.disable();
11361
+ * ```
11362
+ */
11363
+ this.disable = ({ backtest: bt$1 = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, } = WILDCARD_TARGET$1) => {
11364
+ bt.loggerService.debug(MARKDOWN_METHOD_NAME_DISABLE, {
11365
+ backtest: bt$1,
11366
+ breakeven,
11367
+ heat,
11368
+ live,
11369
+ partial,
11370
+ performance,
11371
+ risk,
11372
+ schedule,
11373
+ walker,
11374
+ });
11375
+ if (bt$1) {
11376
+ bt.backtestMarkdownService.unsubscribe();
11377
+ }
11378
+ if (breakeven) {
11379
+ bt.breakevenMarkdownService.unsubscribe();
11380
+ }
11381
+ if (heat) {
11382
+ bt.heatMarkdownService.unsubscribe();
11383
+ }
11384
+ if (live) {
11385
+ bt.liveMarkdownService.unsubscribe();
11386
+ }
11387
+ if (partial) {
11388
+ bt.partialMarkdownService.unsubscribe();
11389
+ }
11390
+ if (performance) {
11391
+ bt.performanceMarkdownService.unsubscribe();
11392
+ }
11393
+ if (risk) {
11394
+ bt.riskMarkdownService.unsubscribe();
11395
+ }
11396
+ if (schedule) {
11397
+ bt.scheduleMarkdownService.unsubscribe();
11398
+ }
11399
+ if (walker) {
11400
+ bt.walkerMarkdownService.unsubscribe();
11401
+ }
11402
+ };
11247
11403
  }
11248
11404
  }
11249
11405
  /**
@@ -16824,6 +16980,13 @@ let ReportStorage$2 = class ReportStorage {
16824
16980
  position: data.position,
16825
16981
  currentPrice,
16826
16982
  level,
16983
+ priceOpen: data.priceOpen,
16984
+ priceTakeProfit: data.priceTakeProfit,
16985
+ priceStopLoss: data.priceStopLoss,
16986
+ originalPriceTakeProfit: data.originalPriceTakeProfit,
16987
+ originalPriceStopLoss: data.originalPriceStopLoss,
16988
+ totalExecuted: data.totalExecuted,
16989
+ note: data.note,
16827
16990
  backtest,
16828
16991
  });
16829
16992
  // Trim queue if exceeded MAX_EVENTS
@@ -16849,6 +17012,13 @@ let ReportStorage$2 = class ReportStorage {
16849
17012
  position: data.position,
16850
17013
  currentPrice,
16851
17014
  level,
17015
+ priceOpen: data.priceOpen,
17016
+ priceTakeProfit: data.priceTakeProfit,
17017
+ priceStopLoss: data.priceStopLoss,
17018
+ originalPriceTakeProfit: data.originalPriceTakeProfit,
17019
+ originalPriceStopLoss: data.originalPriceStopLoss,
17020
+ totalExecuted: data.totalExecuted,
17021
+ note: data.note,
16852
17022
  backtest,
16853
17023
  });
16854
17024
  // Trim queue if exceeded MAX_EVENTS
@@ -17901,7 +18071,7 @@ let ReportStorage$1 = class ReportStorage {
17901
18071
  /**
17902
18072
  * Adds a breakeven event to the storage.
17903
18073
  *
17904
- * @param data - Signal row data
18074
+ * @param data - Signal row data with original prices
17905
18075
  * @param currentPrice - Current market price when breakeven was reached
17906
18076
  * @param backtest - True if backtest mode
17907
18077
  * @param timestamp - Event timestamp in milliseconds
@@ -17915,6 +18085,12 @@ let ReportStorage$1 = class ReportStorage {
17915
18085
  position: data.position,
17916
18086
  currentPrice,
17917
18087
  priceOpen: data.priceOpen,
18088
+ priceTakeProfit: data.priceTakeProfit,
18089
+ priceStopLoss: data.priceStopLoss,
18090
+ originalPriceTakeProfit: data.originalPriceTakeProfit,
18091
+ originalPriceStopLoss: data.originalPriceStopLoss,
18092
+ totalExecuted: data.totalExecuted,
18093
+ note: data.note,
17918
18094
  backtest,
17919
18095
  });
17920
18096
  // Trim queue if exceeded MAX_EVENTS
@@ -19147,6 +19323,7 @@ const REPORT_BASE_METHOD_NAME_WRITE = "ReportBase.write";
19147
19323
  const REPORT_UTILS_METHOD_NAME_USE_REPORT_ADAPTER = "ReportUtils.useReportAdapter";
19148
19324
  const REPORT_UTILS_METHOD_NAME_WRITE_DATA = "ReportUtils.writeReportData";
19149
19325
  const REPORT_UTILS_METHOD_NAME_ENABLE = "ReportUtils.enable";
19326
+ const REPORT_UTILS_METHOD_NAME_DISABLE = "ReportUtils.disable";
19150
19327
  const REPORT_UTILS_METHOD_NAME_USE_DUMMY = "ReportUtils.useDummy";
19151
19328
  const REPORT_UTILS_METHOD_NAME_USE_JSONL = "ReportUtils.useJsonl";
19152
19329
  const WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
@@ -19388,6 +19565,82 @@ class ReportUtils {
19388
19565
  }
19389
19566
  return functoolsKit.compose(...unList.map((un) => () => void un()));
19390
19567
  };
19568
+ /**
19569
+ * Disables report services selectively.
19570
+ *
19571
+ * Unsubscribes from specified report services to stop event logging.
19572
+ * Use this method to stop JSONL logging for specific services while keeping others active.
19573
+ *
19574
+ * Each disabled service will:
19575
+ * - Stop listening to events immediately
19576
+ * - Stop writing to JSONL files
19577
+ * - Free up event listener resources
19578
+ *
19579
+ * Unlike enable(), this method does NOT return an unsubscribe function.
19580
+ * Services are unsubscribed immediately upon calling this method.
19581
+ *
19582
+ * @param config - Service configuration object specifying which services to disable. Defaults to disabling all services.
19583
+ * @param config.backtest - Disable backtest closed signal logging
19584
+ * @param config.breakeven - Disable breakeven event logging
19585
+ * @param config.partial - Disable partial close event logging
19586
+ * @param config.heat - Disable heatmap data logging
19587
+ * @param config.walker - Disable walker iteration logging
19588
+ * @param config.performance - Disable performance metrics logging
19589
+ * @param config.risk - Disable risk rejection logging
19590
+ * @param config.schedule - Disable scheduled signal logging
19591
+ * @param config.live - Disable live trading event logging
19592
+ *
19593
+ * @example
19594
+ * ```typescript
19595
+ * import { Report } from "backtest-kit";
19596
+ *
19597
+ * // Disable specific services
19598
+ * Report.disable({ backtest: true, live: true });
19599
+ *
19600
+ * // Disable all services
19601
+ * Report.disable();
19602
+ * ```
19603
+ */
19604
+ this.disable = ({ backtest: bt$1 = false, breakeven = false, heat = false, live = false, partial = false, performance = false, risk = false, schedule = false, walker = false, } = WILDCARD_TARGET) => {
19605
+ bt.loggerService.debug(REPORT_UTILS_METHOD_NAME_DISABLE, {
19606
+ backtest: bt$1,
19607
+ breakeven,
19608
+ heat,
19609
+ live,
19610
+ partial,
19611
+ performance,
19612
+ risk,
19613
+ schedule,
19614
+ walker,
19615
+ });
19616
+ if (bt$1) {
19617
+ bt.backtestReportService.unsubscribe();
19618
+ }
19619
+ if (breakeven) {
19620
+ bt.breakevenReportService.unsubscribe();
19621
+ }
19622
+ if (heat) {
19623
+ bt.heatReportService.unsubscribe();
19624
+ }
19625
+ if (live) {
19626
+ bt.liveReportService.unsubscribe();
19627
+ }
19628
+ if (partial) {
19629
+ bt.partialReportService.unsubscribe();
19630
+ }
19631
+ if (performance) {
19632
+ bt.performanceReportService.unsubscribe();
19633
+ }
19634
+ if (risk) {
19635
+ bt.riskReportService.unsubscribe();
19636
+ }
19637
+ if (schedule) {
19638
+ bt.scheduleReportService.unsubscribe();
19639
+ }
19640
+ if (walker) {
19641
+ bt.walkerReportService.unsubscribe();
19642
+ }
19643
+ };
19391
19644
  }
19392
19645
  }
19393
19646
  /**
@@ -19477,9 +19730,46 @@ const Report = new ReportAdapter();
19477
19730
  const BACKTEST_REPORT_METHOD_NAME_SUBSCRIBE = "BacktestReportService.subscribe";
19478
19731
  const BACKTEST_REPORT_METHOD_NAME_UNSUBSCRIBE = "BacktestReportService.unsubscribe";
19479
19732
  const BACKTEST_REPORT_METHOD_NAME_TICK = "BacktestReportService.tick";
19733
+ /**
19734
+ * Service for logging backtest strategy tick events to SQLite database.
19735
+ *
19736
+ * Captures all backtest signal lifecycle events (idle, opened, active, closed)
19737
+ * and stores them in the Report database for analysis and debugging.
19738
+ *
19739
+ * Features:
19740
+ * - Listens to backtest signal events via signalBacktestEmitter
19741
+ * - Logs all tick event types with full signal details
19742
+ * - Stores events in Report.writeData() for persistence
19743
+ * - Protected against multiple subscriptions using singleshot
19744
+ *
19745
+ * @example
19746
+ * ```typescript
19747
+ * import { BacktestReportService } from "backtest-kit";
19748
+ *
19749
+ * const reportService = new BacktestReportService();
19750
+ *
19751
+ * // Subscribe to backtest events
19752
+ * const unsubscribe = reportService.subscribe();
19753
+ *
19754
+ * // Run backtest...
19755
+ * // Events are automatically logged
19756
+ *
19757
+ * // Later: unsubscribe
19758
+ * await reportService.unsubscribe();
19759
+ * ```
19760
+ */
19480
19761
  class BacktestReportService {
19481
19762
  constructor() {
19763
+ /** Logger service for debug output */
19482
19764
  this.loggerService = inject(TYPES.loggerService);
19765
+ /**
19766
+ * Processes backtest tick events and logs them to the database.
19767
+ * Handles all event types: idle, opened, active, closed.
19768
+ *
19769
+ * @param data - Backtest tick result with signal lifecycle information
19770
+ *
19771
+ * @internal
19772
+ */
19483
19773
  this.tick = async (data) => {
19484
19774
  this.loggerService.log(BACKTEST_REPORT_METHOD_NAME_TICK, { data });
19485
19775
  const baseEvent = {
@@ -19570,6 +19860,21 @@ class BacktestReportService {
19570
19860
  }, { ...searchOptions, signalId: data.signal?.id });
19571
19861
  }
19572
19862
  };
19863
+ /**
19864
+ * Subscribes to backtest signal emitter to receive tick events.
19865
+ * Protected against multiple subscriptions.
19866
+ * Returns an unsubscribe function to stop receiving events.
19867
+ *
19868
+ * @returns Unsubscribe function to stop receiving backtest events
19869
+ *
19870
+ * @example
19871
+ * ```typescript
19872
+ * const service = new BacktestReportService();
19873
+ * const unsubscribe = service.subscribe();
19874
+ * // ... later
19875
+ * unsubscribe();
19876
+ * ```
19877
+ */
19573
19878
  this.subscribe = functoolsKit.singleshot(() => {
19574
19879
  this.loggerService.log(BACKTEST_REPORT_METHOD_NAME_SUBSCRIBE);
19575
19880
  const unsubscribe = signalBacktestEmitter.subscribe(this.tick);
@@ -19578,6 +19883,19 @@ class BacktestReportService {
19578
19883
  unsubscribe();
19579
19884
  };
19580
19885
  });
19886
+ /**
19887
+ * Unsubscribes from backtest signal emitter to stop receiving tick events.
19888
+ * Calls the unsubscribe function returned by subscribe().
19889
+ * If not subscribed, does nothing.
19890
+ *
19891
+ * @example
19892
+ * ```typescript
19893
+ * const service = new BacktestReportService();
19894
+ * service.subscribe();
19895
+ * // ... later
19896
+ * await service.unsubscribe();
19897
+ * ```
19898
+ */
19581
19899
  this.unsubscribe = async () => {
19582
19900
  this.loggerService.log(BACKTEST_REPORT_METHOD_NAME_UNSUBSCRIBE);
19583
19901
  if (this.subscribe.hasValue()) {
@@ -19591,9 +19909,46 @@ class BacktestReportService {
19591
19909
  const LIVE_REPORT_METHOD_NAME_SUBSCRIBE = "LiveReportService.subscribe";
19592
19910
  const LIVE_REPORT_METHOD_NAME_UNSUBSCRIBE = "LiveReportService.unsubscribe";
19593
19911
  const LIVE_REPORT_METHOD_NAME_TICK = "LiveReportService.tick";
19912
+ /**
19913
+ * Service for logging live trading strategy tick events to SQLite database.
19914
+ *
19915
+ * Captures all live trading signal lifecycle events (idle, opened, active, closed)
19916
+ * and stores them in the Report database for real-time monitoring and analysis.
19917
+ *
19918
+ * Features:
19919
+ * - Listens to live signal events via signalLiveEmitter
19920
+ * - Logs all tick event types with full signal details
19921
+ * - Stores events in Report.writeData() for persistence
19922
+ * - Protected against multiple subscriptions using singleshot
19923
+ *
19924
+ * @example
19925
+ * ```typescript
19926
+ * import { LiveReportService } from "backtest-kit";
19927
+ *
19928
+ * const reportService = new LiveReportService();
19929
+ *
19930
+ * // Subscribe to live trading events
19931
+ * const unsubscribe = reportService.subscribe();
19932
+ *
19933
+ * // Run live trading...
19934
+ * // Events are automatically logged
19935
+ *
19936
+ * // Later: unsubscribe
19937
+ * await reportService.unsubscribe();
19938
+ * ```
19939
+ */
19594
19940
  class LiveReportService {
19595
19941
  constructor() {
19942
+ /** Logger service for debug output */
19596
19943
  this.loggerService = inject(TYPES.loggerService);
19944
+ /**
19945
+ * Processes live trading tick events and logs them to the database.
19946
+ * Handles all event types: idle, opened, active, closed.
19947
+ *
19948
+ * @param data - Live trading tick result with signal lifecycle information
19949
+ *
19950
+ * @internal
19951
+ */
19597
19952
  this.tick = async (data) => {
19598
19953
  this.loggerService.log(LIVE_REPORT_METHOD_NAME_TICK, { data });
19599
19954
  const baseEvent = {
@@ -19684,6 +20039,21 @@ class LiveReportService {
19684
20039
  }, { ...searchOptions, signalId: data.signal?.id });
19685
20040
  }
19686
20041
  };
20042
+ /**
20043
+ * Subscribes to live signal emitter to receive tick events.
20044
+ * Protected against multiple subscriptions.
20045
+ * Returns an unsubscribe function to stop receiving events.
20046
+ *
20047
+ * @returns Unsubscribe function to stop receiving live trading events
20048
+ *
20049
+ * @example
20050
+ * ```typescript
20051
+ * const service = new LiveReportService();
20052
+ * const unsubscribe = service.subscribe();
20053
+ * // ... later
20054
+ * unsubscribe();
20055
+ * ```
20056
+ */
19687
20057
  this.subscribe = functoolsKit.singleshot(() => {
19688
20058
  this.loggerService.log(LIVE_REPORT_METHOD_NAME_SUBSCRIBE);
19689
20059
  const unsubscribe = signalLiveEmitter.subscribe(this.tick);
@@ -19692,6 +20062,19 @@ class LiveReportService {
19692
20062
  unsubscribe();
19693
20063
  };
19694
20064
  });
20065
+ /**
20066
+ * Unsubscribes from live signal emitter to stop receiving tick events.
20067
+ * Calls the unsubscribe function returned by subscribe().
20068
+ * If not subscribed, does nothing.
20069
+ *
20070
+ * @example
20071
+ * ```typescript
20072
+ * const service = new LiveReportService();
20073
+ * service.subscribe();
20074
+ * // ... later
20075
+ * await service.unsubscribe();
20076
+ * ```
20077
+ */
19695
20078
  this.unsubscribe = async () => {
19696
20079
  this.loggerService.log(LIVE_REPORT_METHOD_NAME_UNSUBSCRIBE);
19697
20080
  if (this.subscribe.hasValue()) {
@@ -19705,9 +20088,47 @@ class LiveReportService {
19705
20088
  const SCHEDULE_REPORT_METHOD_NAME_SUBSCRIBE = "ScheduleReportService.subscribe";
19706
20089
  const SCHEDULE_REPORT_METHOD_NAME_UNSUBSCRIBE = "ScheduleReportService.unsubscribe";
19707
20090
  const SCHEDULE_REPORT_METHOD_NAME_TICK = "ScheduleReportService.tick";
20091
+ /**
20092
+ * Service for logging scheduled signal events to SQLite database.
20093
+ *
20094
+ * Captures all scheduled signal lifecycle events (scheduled, opened, cancelled)
20095
+ * and stores them in the Report database for tracking delayed order execution.
20096
+ *
20097
+ * Features:
20098
+ * - Listens to signal events via signalEmitter
20099
+ * - Logs scheduled, opened (from scheduled), and cancelled events
20100
+ * - Calculates duration between scheduling and execution/cancellation
20101
+ * - Stores events in Report.writeData() for schedule tracking
20102
+ * - Protected against multiple subscriptions using singleshot
20103
+ *
20104
+ * @example
20105
+ * ```typescript
20106
+ * import { ScheduleReportService } from "backtest-kit";
20107
+ *
20108
+ * const reportService = new ScheduleReportService();
20109
+ *
20110
+ * // Subscribe to scheduled signal events
20111
+ * const unsubscribe = reportService.subscribe();
20112
+ *
20113
+ * // Run strategy with scheduled orders...
20114
+ * // Scheduled events are automatically logged
20115
+ *
20116
+ * // Later: unsubscribe
20117
+ * await reportService.unsubscribe();
20118
+ * ```
20119
+ */
19708
20120
  class ScheduleReportService {
19709
20121
  constructor() {
20122
+ /** Logger service for debug output */
19710
20123
  this.loggerService = inject(TYPES.loggerService);
20124
+ /**
20125
+ * Processes signal tick events and logs scheduled signal lifecycle to the database.
20126
+ * Handles scheduled, opened (from scheduled), and cancelled event types.
20127
+ *
20128
+ * @param data - Strategy tick result with signal lifecycle information
20129
+ *
20130
+ * @internal
20131
+ */
19711
20132
  this.tick = async (data) => {
19712
20133
  this.loggerService.log(SCHEDULE_REPORT_METHOD_NAME_TICK, { data });
19713
20134
  const baseEvent = {
@@ -19794,14 +20215,42 @@ class ScheduleReportService {
19794
20215
  }, searchOptions);
19795
20216
  }
19796
20217
  };
19797
- this.subscribe = functoolsKit.singleshot(() => {
19798
- this.loggerService.log(SCHEDULE_REPORT_METHOD_NAME_SUBSCRIBE);
19799
- const unsubscribe = signalEmitter.subscribe(this.tick);
19800
- return () => {
19801
- this.subscribe.clear();
19802
- unsubscribe();
19803
- };
20218
+ /**
20219
+ * Subscribes to signal emitter to receive scheduled signal events.
20220
+ * Protected against multiple subscriptions.
20221
+ * Returns an unsubscribe function to stop receiving events.
20222
+ *
20223
+ * @returns Unsubscribe function to stop receiving scheduled signal events
20224
+ *
20225
+ * @example
20226
+ * ```typescript
20227
+ * const service = new ScheduleReportService();
20228
+ * const unsubscribe = service.subscribe();
20229
+ * // ... later
20230
+ * unsubscribe();
20231
+ * ```
20232
+ */
20233
+ this.subscribe = functoolsKit.singleshot(() => {
20234
+ this.loggerService.log(SCHEDULE_REPORT_METHOD_NAME_SUBSCRIBE);
20235
+ const unsubscribe = signalEmitter.subscribe(this.tick);
20236
+ return () => {
20237
+ this.subscribe.clear();
20238
+ unsubscribe();
20239
+ };
19804
20240
  });
20241
+ /**
20242
+ * Unsubscribes from signal emitter to stop receiving events.
20243
+ * Calls the unsubscribe function returned by subscribe().
20244
+ * If not subscribed, does nothing.
20245
+ *
20246
+ * @example
20247
+ * ```typescript
20248
+ * const service = new ScheduleReportService();
20249
+ * service.subscribe();
20250
+ * // ... later
20251
+ * await service.unsubscribe();
20252
+ * ```
20253
+ */
19805
20254
  this.unsubscribe = async () => {
19806
20255
  this.loggerService.log(SCHEDULE_REPORT_METHOD_NAME_UNSUBSCRIBE);
19807
20256
  if (this.subscribe.hasValue()) {
@@ -19815,9 +20264,45 @@ class ScheduleReportService {
19815
20264
  const PERFORMANCE_REPORT_METHOD_NAME_SUBSCRIBE = "PerformanceReportService.subscribe";
19816
20265
  const PERFORMANCE_REPORT_METHOD_NAME_UNSUBSCRIBE = "PerformanceReportService.unsubscribe";
19817
20266
  const PERFORMANCE_REPORT_METHOD_NAME_TRACK = "PerformanceReportService.track";
20267
+ /**
20268
+ * Service for logging performance metrics to SQLite database.
20269
+ *
20270
+ * Captures all performance timing events from strategy execution
20271
+ * and stores them in the Report database for bottleneck analysis and optimization.
20272
+ *
20273
+ * Features:
20274
+ * - Listens to performance events via performanceEmitter
20275
+ * - Logs all timing metrics with duration and metadata
20276
+ * - Stores events in Report.writeData() for performance analysis
20277
+ * - Protected against multiple subscriptions using singleshot
20278
+ *
20279
+ * @example
20280
+ * ```typescript
20281
+ * import { PerformanceReportService } from "backtest-kit";
20282
+ *
20283
+ * const reportService = new PerformanceReportService();
20284
+ *
20285
+ * // Subscribe to performance events
20286
+ * const unsubscribe = reportService.subscribe();
20287
+ *
20288
+ * // Run strategy...
20289
+ * // Performance metrics are automatically logged
20290
+ *
20291
+ * // Later: unsubscribe
20292
+ * await reportService.unsubscribe();
20293
+ * ```
20294
+ */
19818
20295
  class PerformanceReportService {
19819
20296
  constructor() {
20297
+ /** Logger service for debug output */
19820
20298
  this.loggerService = inject(TYPES.loggerService);
20299
+ /**
20300
+ * Processes performance tracking events and logs them to the database.
20301
+ *
20302
+ * @param event - Performance contract with timing and metric information
20303
+ *
20304
+ * @internal
20305
+ */
19821
20306
  this.track = async (event) => {
19822
20307
  this.loggerService.log(PERFORMANCE_REPORT_METHOD_NAME_TRACK, { event });
19823
20308
  await Report.writeData("performance", {
@@ -19839,6 +20324,21 @@ class PerformanceReportService {
19839
20324
  walkerName: "",
19840
20325
  });
19841
20326
  };
20327
+ /**
20328
+ * Subscribes to performance emitter to receive timing events.
20329
+ * Protected against multiple subscriptions.
20330
+ * Returns an unsubscribe function to stop receiving events.
20331
+ *
20332
+ * @returns Unsubscribe function to stop receiving performance events
20333
+ *
20334
+ * @example
20335
+ * ```typescript
20336
+ * const service = new PerformanceReportService();
20337
+ * const unsubscribe = service.subscribe();
20338
+ * // ... later
20339
+ * unsubscribe();
20340
+ * ```
20341
+ */
19842
20342
  this.subscribe = functoolsKit.singleshot(() => {
19843
20343
  this.loggerService.log(PERFORMANCE_REPORT_METHOD_NAME_SUBSCRIBE);
19844
20344
  const unsubscribe = performanceEmitter.subscribe(this.track);
@@ -19847,6 +20347,19 @@ class PerformanceReportService {
19847
20347
  unsubscribe();
19848
20348
  };
19849
20349
  });
20350
+ /**
20351
+ * Unsubscribes from performance emitter to stop receiving events.
20352
+ * Calls the unsubscribe function returned by subscribe().
20353
+ * If not subscribed, does nothing.
20354
+ *
20355
+ * @example
20356
+ * ```typescript
20357
+ * const service = new PerformanceReportService();
20358
+ * service.subscribe();
20359
+ * // ... later
20360
+ * await service.unsubscribe();
20361
+ * ```
20362
+ */
19850
20363
  this.unsubscribe = async () => {
19851
20364
  this.loggerService.log(PERFORMANCE_REPORT_METHOD_NAME_UNSUBSCRIBE);
19852
20365
  if (this.subscribe.hasValue()) {
@@ -19860,9 +20373,46 @@ class PerformanceReportService {
19860
20373
  const WALKER_REPORT_METHOD_NAME_SUBSCRIBE = "WalkerReportService.subscribe";
19861
20374
  const WALKER_REPORT_METHOD_NAME_UNSUBSCRIBE = "WalkerReportService.unsubscribe";
19862
20375
  const WALKER_REPORT_METHOD_NAME_TICK = "WalkerReportService.tick";
20376
+ /**
20377
+ * Service for logging walker optimization progress to SQLite database.
20378
+ *
20379
+ * Captures walker strategy optimization results and stores them in the Report database
20380
+ * for tracking parameter optimization and comparing strategy performance.
20381
+ *
20382
+ * Features:
20383
+ * - Listens to walker events via walkerEmitter
20384
+ * - Logs each strategy test result with metrics and statistics
20385
+ * - Tracks best strategy and optimization progress
20386
+ * - Stores events in Report.writeData() for optimization analysis
20387
+ * - Protected against multiple subscriptions using singleshot
20388
+ *
20389
+ * @example
20390
+ * ```typescript
20391
+ * import { WalkerReportService } from "backtest-kit";
20392
+ *
20393
+ * const reportService = new WalkerReportService();
20394
+ *
20395
+ * // Subscribe to walker optimization events
20396
+ * const unsubscribe = reportService.subscribe();
20397
+ *
20398
+ * // Run walker optimization...
20399
+ * // Each strategy result is automatically logged
20400
+ *
20401
+ * // Later: unsubscribe
20402
+ * await reportService.unsubscribe();
20403
+ * ```
20404
+ */
19863
20405
  class WalkerReportService {
19864
20406
  constructor() {
20407
+ /** Logger service for debug output */
19865
20408
  this.loggerService = inject(TYPES.loggerService);
20409
+ /**
20410
+ * Processes walker optimization events and logs them to the database.
20411
+ *
20412
+ * @param data - Walker contract with strategy optimization results
20413
+ *
20414
+ * @internal
20415
+ */
19866
20416
  this.tick = async (data) => {
19867
20417
  this.loggerService.log(WALKER_REPORT_METHOD_NAME_TICK, { data });
19868
20418
  await Report.writeData("walker", {
@@ -19898,6 +20448,21 @@ class WalkerReportService {
19898
20448
  walkerName: data.walkerName,
19899
20449
  });
19900
20450
  };
20451
+ /**
20452
+ * Subscribes to walker emitter to receive optimization progress events.
20453
+ * Protected against multiple subscriptions.
20454
+ * Returns an unsubscribe function to stop receiving events.
20455
+ *
20456
+ * @returns Unsubscribe function to stop receiving walker optimization events
20457
+ *
20458
+ * @example
20459
+ * ```typescript
20460
+ * const service = new WalkerReportService();
20461
+ * const unsubscribe = service.subscribe();
20462
+ * // ... later
20463
+ * unsubscribe();
20464
+ * ```
20465
+ */
19901
20466
  this.subscribe = functoolsKit.singleshot(() => {
19902
20467
  this.loggerService.log(WALKER_REPORT_METHOD_NAME_SUBSCRIBE);
19903
20468
  const unsubscribe = walkerEmitter.subscribe(this.tick);
@@ -19906,6 +20471,19 @@ class WalkerReportService {
19906
20471
  unsubscribe();
19907
20472
  };
19908
20473
  });
20474
+ /**
20475
+ * Unsubscribes from walker emitter to stop receiving events.
20476
+ * Calls the unsubscribe function returned by subscribe().
20477
+ * If not subscribed, does nothing.
20478
+ *
20479
+ * @example
20480
+ * ```typescript
20481
+ * const service = new WalkerReportService();
20482
+ * service.subscribe();
20483
+ * // ... later
20484
+ * await service.unsubscribe();
20485
+ * ```
20486
+ */
19909
20487
  this.unsubscribe = async () => {
19910
20488
  this.loggerService.log(WALKER_REPORT_METHOD_NAME_UNSUBSCRIBE);
19911
20489
  if (this.subscribe.hasValue()) {
@@ -19919,9 +20497,46 @@ class WalkerReportService {
19919
20497
  const HEAT_REPORT_METHOD_NAME_SUBSCRIBE = "HeatReportService.subscribe";
19920
20498
  const HEAT_REPORT_METHOD_NAME_UNSUBSCRIBE = "HeatReportService.unsubscribe";
19921
20499
  const HEAT_REPORT_METHOD_NAME_TICK = "HeatReportService.tick";
20500
+ /**
20501
+ * Service for logging heatmap (closed signals) events to SQLite database.
20502
+ *
20503
+ * Captures closed signal events across all symbols for portfolio-wide
20504
+ * heatmap analysis and stores them in the Report database.
20505
+ *
20506
+ * Features:
20507
+ * - Listens to signal events via signalEmitter
20508
+ * - Logs only closed signals with PNL data
20509
+ * - Stores events in Report.writeData() for heatmap generation
20510
+ * - Protected against multiple subscriptions using singleshot
20511
+ *
20512
+ * @example
20513
+ * ```typescript
20514
+ * import { HeatReportService } from "backtest-kit";
20515
+ *
20516
+ * const reportService = new HeatReportService();
20517
+ *
20518
+ * // Subscribe to signal events
20519
+ * const unsubscribe = reportService.subscribe();
20520
+ *
20521
+ * // Run strategy...
20522
+ * // Closed signals are automatically logged
20523
+ *
20524
+ * // Later: unsubscribe
20525
+ * await reportService.unsubscribe();
20526
+ * ```
20527
+ */
19922
20528
  class HeatReportService {
19923
20529
  constructor() {
20530
+ /** Logger service for debug output */
19924
20531
  this.loggerService = inject(TYPES.loggerService);
20532
+ /**
20533
+ * Processes signal tick events and logs closed signals to the database.
20534
+ * Only processes closed signals - other actions are ignored.
20535
+ *
20536
+ * @param data - Strategy tick result with signal lifecycle information
20537
+ *
20538
+ * @internal
20539
+ */
19925
20540
  this.tick = async (data) => {
19926
20541
  this.loggerService.log(HEAT_REPORT_METHOD_NAME_TICK, { data });
19927
20542
  if (data.action !== "closed") {
@@ -19951,6 +20566,21 @@ class HeatReportService {
19951
20566
  walkerName: "",
19952
20567
  });
19953
20568
  };
20569
+ /**
20570
+ * Subscribes to signal emitter to receive closed signal events.
20571
+ * Protected against multiple subscriptions.
20572
+ * Returns an unsubscribe function to stop receiving events.
20573
+ *
20574
+ * @returns Unsubscribe function to stop receiving signal events
20575
+ *
20576
+ * @example
20577
+ * ```typescript
20578
+ * const service = new HeatReportService();
20579
+ * const unsubscribe = service.subscribe();
20580
+ * // ... later
20581
+ * unsubscribe();
20582
+ * ```
20583
+ */
19954
20584
  this.subscribe = functoolsKit.singleshot(() => {
19955
20585
  this.loggerService.log(HEAT_REPORT_METHOD_NAME_SUBSCRIBE);
19956
20586
  const unsubscribe = signalEmitter.subscribe(this.tick);
@@ -19959,6 +20589,19 @@ class HeatReportService {
19959
20589
  unsubscribe();
19960
20590
  };
19961
20591
  });
20592
+ /**
20593
+ * Unsubscribes from signal emitter to stop receiving events.
20594
+ * Calls the unsubscribe function returned by subscribe().
20595
+ * If not subscribed, does nothing.
20596
+ *
20597
+ * @example
20598
+ * ```typescript
20599
+ * const service = new HeatReportService();
20600
+ * service.subscribe();
20601
+ * // ... later
20602
+ * await service.unsubscribe();
20603
+ * ```
20604
+ */
19962
20605
  this.unsubscribe = async () => {
19963
20606
  this.loggerService.log(HEAT_REPORT_METHOD_NAME_UNSUBSCRIBE);
19964
20607
  if (this.subscribe.hasValue()) {
@@ -19973,9 +20616,46 @@ const PARTIAL_REPORT_METHOD_NAME_SUBSCRIBE = "PartialReportService.subscribe";
19973
20616
  const PARTIAL_REPORT_METHOD_NAME_UNSUBSCRIBE = "PartialReportService.unsubscribe";
19974
20617
  const PARTIAL_REPORT_METHOD_NAME_TICK_PROFIT = "PartialReportService.tickProfit";
19975
20618
  const PARTIAL_REPORT_METHOD_NAME_TICK_LOSS = "PartialReportService.tickLoss";
20619
+ /**
20620
+ * Service for logging partial profit/loss events to SQLite database.
20621
+ *
20622
+ * Captures all partial position exit events (profit and loss levels)
20623
+ * and stores them in the Report database for tracking partial closures.
20624
+ *
20625
+ * Features:
20626
+ * - Listens to partial profit events via partialProfitSubject
20627
+ * - Listens to partial loss events via partialLossSubject
20628
+ * - Logs all partial exit events with level and price information
20629
+ * - Stores events in Report.writeData() for persistence
20630
+ * - Protected against multiple subscriptions using singleshot
20631
+ *
20632
+ * @example
20633
+ * ```typescript
20634
+ * import { PartialReportService } from "backtest-kit";
20635
+ *
20636
+ * const reportService = new PartialReportService();
20637
+ *
20638
+ * // Subscribe to partial events
20639
+ * const unsubscribe = reportService.subscribe();
20640
+ *
20641
+ * // Run strategy with partial exits...
20642
+ * // Partial events are automatically logged
20643
+ *
20644
+ * // Later: unsubscribe
20645
+ * await reportService.unsubscribe();
20646
+ * ```
20647
+ */
19976
20648
  class PartialReportService {
19977
20649
  constructor() {
20650
+ /** Logger service for debug output */
19978
20651
  this.loggerService = inject(TYPES.loggerService);
20652
+ /**
20653
+ * Processes partial profit events and logs them to the database.
20654
+ *
20655
+ * @param data - Partial profit event data with signal, level, and price information
20656
+ *
20657
+ * @internal
20658
+ */
19979
20659
  this.tickProfit = async (data) => {
19980
20660
  this.loggerService.log(PARTIAL_REPORT_METHOD_NAME_TICK_PROFIT, { data });
19981
20661
  await Report.writeData("partial", {
@@ -19993,6 +20673,9 @@ class PartialReportService {
19993
20673
  priceOpen: data.data.priceOpen,
19994
20674
  priceTakeProfit: data.data.priceTakeProfit,
19995
20675
  priceStopLoss: data.data.priceStopLoss,
20676
+ originalPriceTakeProfit: data.data.originalPriceTakeProfit,
20677
+ originalPriceStopLoss: data.data.originalPriceStopLoss,
20678
+ totalExecuted: data.data.totalExecuted,
19996
20679
  _partial: data.data._partial,
19997
20680
  note: data.data.note,
19998
20681
  pendingAt: data.data.pendingAt,
@@ -20007,6 +20690,13 @@ class PartialReportService {
20007
20690
  walkerName: "",
20008
20691
  });
20009
20692
  };
20693
+ /**
20694
+ * Processes partial loss events and logs them to the database.
20695
+ *
20696
+ * @param data - Partial loss event data with signal, level, and price information
20697
+ *
20698
+ * @internal
20699
+ */
20010
20700
  this.tickLoss = async (data) => {
20011
20701
  this.loggerService.log(PARTIAL_REPORT_METHOD_NAME_TICK_LOSS, { data });
20012
20702
  await Report.writeData("partial", {
@@ -20024,6 +20714,9 @@ class PartialReportService {
20024
20714
  priceOpen: data.data.priceOpen,
20025
20715
  priceTakeProfit: data.data.priceTakeProfit,
20026
20716
  priceStopLoss: data.data.priceStopLoss,
20717
+ originalPriceTakeProfit: data.data.originalPriceTakeProfit,
20718
+ originalPriceStopLoss: data.data.originalPriceStopLoss,
20719
+ totalExecuted: data.data.totalExecuted,
20027
20720
  _partial: data.data._partial,
20028
20721
  note: data.data.note,
20029
20722
  pendingAt: data.data.pendingAt,
@@ -20038,6 +20731,21 @@ class PartialReportService {
20038
20731
  walkerName: "",
20039
20732
  });
20040
20733
  };
20734
+ /**
20735
+ * Subscribes to partial profit/loss emitters to receive partial exit events.
20736
+ * Protected against multiple subscriptions.
20737
+ * Returns an unsubscribe function to stop receiving events.
20738
+ *
20739
+ * @returns Unsubscribe function to stop receiving partial events
20740
+ *
20741
+ * @example
20742
+ * ```typescript
20743
+ * const service = new PartialReportService();
20744
+ * const unsubscribe = service.subscribe();
20745
+ * // ... later
20746
+ * unsubscribe();
20747
+ * ```
20748
+ */
20041
20749
  this.subscribe = functoolsKit.singleshot(() => {
20042
20750
  this.loggerService.log(PARTIAL_REPORT_METHOD_NAME_SUBSCRIBE);
20043
20751
  const unProfit = partialProfitSubject.subscribe(this.tickProfit);
@@ -20048,6 +20756,19 @@ class PartialReportService {
20048
20756
  unLoss();
20049
20757
  };
20050
20758
  });
20759
+ /**
20760
+ * Unsubscribes from partial profit/loss emitters to stop receiving events.
20761
+ * Calls the unsubscribe function returned by subscribe().
20762
+ * If not subscribed, does nothing.
20763
+ *
20764
+ * @example
20765
+ * ```typescript
20766
+ * const service = new PartialReportService();
20767
+ * service.subscribe();
20768
+ * // ... later
20769
+ * await service.unsubscribe();
20770
+ * ```
20771
+ */
20051
20772
  this.unsubscribe = async () => {
20052
20773
  this.loggerService.log(PARTIAL_REPORT_METHOD_NAME_UNSUBSCRIBE);
20053
20774
  if (this.subscribe.hasValue()) {
@@ -20061,9 +20782,45 @@ class PartialReportService {
20061
20782
  const BREAKEVEN_REPORT_METHOD_NAME_SUBSCRIBE = "BreakevenReportService.subscribe";
20062
20783
  const BREAKEVEN_REPORT_METHOD_NAME_UNSUBSCRIBE = "BreakevenReportService.unsubscribe";
20063
20784
  const BREAKEVEN_REPORT_METHOD_NAME_TICK = "BreakevenReportService.tickBreakeven";
20785
+ /**
20786
+ * Service for logging breakeven events to SQLite database.
20787
+ *
20788
+ * Captures all breakeven events (when signal reaches breakeven point)
20789
+ * and stores them in the Report database for analysis and tracking.
20790
+ *
20791
+ * Features:
20792
+ * - Listens to breakeven events via breakevenSubject
20793
+ * - Logs all breakeven achievements with full signal details
20794
+ * - Stores events in Report.writeData() for persistence
20795
+ * - Protected against multiple subscriptions using singleshot
20796
+ *
20797
+ * @example
20798
+ * ```typescript
20799
+ * import { BreakevenReportService } from "backtest-kit";
20800
+ *
20801
+ * const reportService = new BreakevenReportService();
20802
+ *
20803
+ * // Subscribe to breakeven events
20804
+ * const unsubscribe = reportService.subscribe();
20805
+ *
20806
+ * // Run strategy...
20807
+ * // Breakeven events are automatically logged
20808
+ *
20809
+ * // Later: unsubscribe
20810
+ * await reportService.unsubscribe();
20811
+ * ```
20812
+ */
20064
20813
  class BreakevenReportService {
20065
20814
  constructor() {
20815
+ /** Logger service for debug output */
20066
20816
  this.loggerService = inject(TYPES.loggerService);
20817
+ /**
20818
+ * Processes breakeven events and logs them to the database.
20819
+ *
20820
+ * @param data - Breakeven event data with signal and price information
20821
+ *
20822
+ * @internal
20823
+ */
20067
20824
  this.tickBreakeven = async (data) => {
20068
20825
  this.loggerService.log(BREAKEVEN_REPORT_METHOD_NAME_TICK, { data });
20069
20826
  await Report.writeData("breakeven", {
@@ -20079,6 +20836,9 @@ class BreakevenReportService {
20079
20836
  priceOpen: data.data.priceOpen,
20080
20837
  priceTakeProfit: data.data.priceTakeProfit,
20081
20838
  priceStopLoss: data.data.priceStopLoss,
20839
+ originalPriceTakeProfit: data.data.originalPriceTakeProfit,
20840
+ originalPriceStopLoss: data.data.originalPriceStopLoss,
20841
+ totalExecuted: data.data.totalExecuted,
20082
20842
  _partial: data.data._partial,
20083
20843
  note: data.data.note,
20084
20844
  pendingAt: data.data.pendingAt,
@@ -20093,6 +20853,21 @@ class BreakevenReportService {
20093
20853
  walkerName: "",
20094
20854
  });
20095
20855
  };
20856
+ /**
20857
+ * Subscribes to breakeven signal emitter to receive breakeven events.
20858
+ * Protected against multiple subscriptions.
20859
+ * Returns an unsubscribe function to stop receiving events.
20860
+ *
20861
+ * @returns Unsubscribe function to stop receiving breakeven events
20862
+ *
20863
+ * @example
20864
+ * ```typescript
20865
+ * const service = new BreakevenReportService();
20866
+ * const unsubscribe = service.subscribe();
20867
+ * // ... later
20868
+ * unsubscribe();
20869
+ * ```
20870
+ */
20096
20871
  this.subscribe = functoolsKit.singleshot(() => {
20097
20872
  this.loggerService.log(BREAKEVEN_REPORT_METHOD_NAME_SUBSCRIBE);
20098
20873
  const unsubscribe = breakevenSubject.subscribe(this.tickBreakeven);
@@ -20101,6 +20876,19 @@ class BreakevenReportService {
20101
20876
  unsubscribe();
20102
20877
  };
20103
20878
  });
20879
+ /**
20880
+ * Unsubscribes from breakeven signal emitter to stop receiving events.
20881
+ * Calls the unsubscribe function returned by subscribe().
20882
+ * If not subscribed, does nothing.
20883
+ *
20884
+ * @example
20885
+ * ```typescript
20886
+ * const service = new BreakevenReportService();
20887
+ * service.subscribe();
20888
+ * // ... later
20889
+ * await service.unsubscribe();
20890
+ * ```
20891
+ */
20104
20892
  this.unsubscribe = async () => {
20105
20893
  this.loggerService.log(BREAKEVEN_REPORT_METHOD_NAME_UNSUBSCRIBE);
20106
20894
  if (this.subscribe.hasValue()) {
@@ -20114,9 +20902,45 @@ class BreakevenReportService {
20114
20902
  const RISK_REPORT_METHOD_NAME_SUBSCRIBE = "RiskReportService.subscribe";
20115
20903
  const RISK_REPORT_METHOD_NAME_UNSUBSCRIBE = "RiskReportService.unsubscribe";
20116
20904
  const RISK_REPORT_METHOD_NAME_TICK = "RiskReportService.tickRejection";
20905
+ /**
20906
+ * Service for logging risk rejection events to SQLite database.
20907
+ *
20908
+ * Captures all signal rejection events from the risk management system
20909
+ * and stores them in the Report database for risk analysis and auditing.
20910
+ *
20911
+ * Features:
20912
+ * - Listens to risk rejection events via riskSubject
20913
+ * - Logs all rejected signals with reason and pending signal details
20914
+ * - Stores events in Report.writeData() for risk tracking
20915
+ * - Protected against multiple subscriptions using singleshot
20916
+ *
20917
+ * @example
20918
+ * ```typescript
20919
+ * import { RiskReportService } from "backtest-kit";
20920
+ *
20921
+ * const reportService = new RiskReportService();
20922
+ *
20923
+ * // Subscribe to risk rejection events
20924
+ * const unsubscribe = reportService.subscribe();
20925
+ *
20926
+ * // Run strategy with risk management...
20927
+ * // Rejection events are automatically logged
20928
+ *
20929
+ * // Later: unsubscribe
20930
+ * await reportService.unsubscribe();
20931
+ * ```
20932
+ */
20117
20933
  class RiskReportService {
20118
20934
  constructor() {
20935
+ /** Logger service for debug output */
20119
20936
  this.loggerService = inject(TYPES.loggerService);
20937
+ /**
20938
+ * Processes risk rejection events and logs them to the database.
20939
+ *
20940
+ * @param data - Risk event with rejection reason and pending signal information
20941
+ *
20942
+ * @internal
20943
+ */
20120
20944
  this.tickRejection = async (data) => {
20121
20945
  this.loggerService.log(RISK_REPORT_METHOD_NAME_TICK, { data });
20122
20946
  await Report.writeData("risk", {
@@ -20150,6 +20974,21 @@ class RiskReportService {
20150
20974
  walkerName: "",
20151
20975
  });
20152
20976
  };
20977
+ /**
20978
+ * Subscribes to risk rejection emitter to receive rejection events.
20979
+ * Protected against multiple subscriptions.
20980
+ * Returns an unsubscribe function to stop receiving events.
20981
+ *
20982
+ * @returns Unsubscribe function to stop receiving risk rejection events
20983
+ *
20984
+ * @example
20985
+ * ```typescript
20986
+ * const service = new RiskReportService();
20987
+ * const unsubscribe = service.subscribe();
20988
+ * // ... later
20989
+ * unsubscribe();
20990
+ * ```
20991
+ */
20153
20992
  this.subscribe = functoolsKit.singleshot(() => {
20154
20993
  this.loggerService.log(RISK_REPORT_METHOD_NAME_SUBSCRIBE);
20155
20994
  const unsubscribe = riskSubject.subscribe(this.tickRejection);
@@ -20158,6 +20997,19 @@ class RiskReportService {
20158
20997
  unsubscribe();
20159
20998
  };
20160
20999
  });
21000
+ /**
21001
+ * Unsubscribes from risk rejection emitter to stop receiving events.
21002
+ * Calls the unsubscribe function returned by subscribe().
21003
+ * If not subscribed, does nothing.
21004
+ *
21005
+ * @example
21006
+ * ```typescript
21007
+ * const service = new RiskReportService();
21008
+ * service.subscribe();
21009
+ * // ... later
21010
+ * await service.unsubscribe();
21011
+ * ```
21012
+ */
20161
21013
  this.unsubscribe = async () => {
20162
21014
  this.loggerService.log(RISK_REPORT_METHOD_NAME_UNSUBSCRIBE);
20163
21015
  if (this.subscribe.hasValue()) {