backtest-kit 3.4.2 → 3.5.1

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.mjs CHANGED
@@ -713,7 +713,7 @@ async function writeFileAtomic(file, data, options = {}) {
713
713
  }
714
714
  }
715
715
 
716
- var _a$3;
716
+ var _a$4;
717
717
  const BASE_WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
718
718
  // Calculate step in milliseconds for candle close time validation
719
719
  const INTERVAL_MINUTES$8 = {
@@ -836,7 +836,7 @@ class PersistBase {
836
836
  constructor(entityName, baseDir = join(process.cwd(), "logs/data")) {
837
837
  this.entityName = entityName;
838
838
  this.baseDir = baseDir;
839
- this[_a$3] = singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
839
+ this[_a$4] = singleshot(async () => await BASE_WAIT_FOR_INIT_FN(this));
840
840
  bt.loggerService.debug(PERSIST_BASE_METHOD_NAME_CTOR, {
841
841
  entityName: this.entityName,
842
842
  baseDir,
@@ -939,7 +939,7 @@ class PersistBase {
939
939
  }
940
940
  }
941
941
  }
942
- _a$3 = BASE_WAIT_FOR_INIT_SYMBOL;
942
+ _a$4 = BASE_WAIT_FOR_INIT_SYMBOL;
943
943
  // @ts-ignore
944
944
  PersistBase = makeExtendable(PersistBase);
945
945
  /**
@@ -2046,7 +2046,7 @@ class PersistLogUtils {
2046
2046
  */
2047
2047
  const PersistLogAdapter = new PersistLogUtils();
2048
2048
 
2049
- var _a$2, _b$2;
2049
+ var _a$3, _b$3;
2050
2050
  const BUSY_DELAY = 100;
2051
2051
  const SET_BUSY_SYMBOL = Symbol("setBusy");
2052
2052
  const GET_BUSY_SYMBOL = Symbol("getBusy");
@@ -2061,8 +2061,8 @@ const ACQUIRE_LOCK_FN = async (self) => {
2061
2061
  class Lock {
2062
2062
  constructor() {
2063
2063
  this._isBusy = 0;
2064
- this[_a$2] = queued(ACQUIRE_LOCK_FN);
2065
- this[_b$2] = () => this[SET_BUSY_SYMBOL](false);
2064
+ this[_a$3] = queued(ACQUIRE_LOCK_FN);
2065
+ this[_b$3] = () => this[SET_BUSY_SYMBOL](false);
2066
2066
  this.acquireLock = async () => {
2067
2067
  await this[ACQUIRE_LOCK_SYMBOL](this);
2068
2068
  };
@@ -2080,7 +2080,7 @@ class Lock {
2080
2080
  return !!this._isBusy;
2081
2081
  }
2082
2082
  }
2083
- _a$2 = ACQUIRE_LOCK_SYMBOL, _b$2 = RELEASE_LOCK_SYMBOL;
2083
+ _a$3 = ACQUIRE_LOCK_SYMBOL, _b$3 = RELEASE_LOCK_SYMBOL;
2084
2084
 
2085
2085
  const METHOD_NAME_ACQUIRE_LOCK = "CandleUtils.acquireLock";
2086
2086
  const METHOD_NAME_RELEASE_LOCK = "CandleUtils.releaseLock";
@@ -16076,7 +16076,7 @@ const COLUMN_CONFIG = {
16076
16076
  */
16077
16077
  const DEFAULT_COLUMNS = Object.freeze({ ...COLUMN_CONFIG });
16078
16078
 
16079
- var _a$1, _b$1;
16079
+ var _a$2, _b$2;
16080
16080
  const MARKDOWN_METHOD_NAME_ENABLE = "MarkdownUtils.enable";
16081
16081
  const MARKDOWN_METHOD_NAME_DISABLE = "MarkdownUtils.disable";
16082
16082
  const MARKDOWN_METHOD_NAME_USE_ADAPTER = "MarkdownAdapter.useMarkdownAdapter";
@@ -16086,8 +16086,8 @@ const MARKDOWN_METHOD_NAME_WRITE_DATA = "MarkdownAdapter.writeData";
16086
16086
  const MARKDOWN_METHOD_NAME_USE_MD = "MarkdownAdapter.useMd";
16087
16087
  const MARKDOWN_METHOD_NAME_USE_JSONL = "MarkdownAdapter.useJsonl";
16088
16088
  const MARKDOWN_METHOD_NAME_USE_DUMMY = "MarkdownAdapter.useDummy";
16089
- const WAIT_FOR_INIT_SYMBOL$1 = Symbol("wait-for-init");
16090
- const WRITE_SAFE_SYMBOL$1 = Symbol("write-safe");
16089
+ const WAIT_FOR_INIT_SYMBOL$2 = Symbol("wait-for-init");
16090
+ const WRITE_SAFE_SYMBOL$2 = Symbol("write-safe");
16091
16091
  /**
16092
16092
  * Default configuration that enables all markdown services.
16093
16093
  * Used when no specific configuration is provided to `enable()`.
@@ -16137,7 +16137,7 @@ class MarkdownFileBase {
16137
16137
  * Protected by singleshot to ensure one-time execution.
16138
16138
  * Sets up error handler that emits to exitEmitter.
16139
16139
  */
16140
- this[_a$1] = singleshot(async () => {
16140
+ this[_a$2] = singleshot(async () => {
16141
16141
  await fs.mkdir(this._baseDir, { recursive: true });
16142
16142
  this._stream = createWriteStream(this._filePath, { flags: "a" });
16143
16143
  this._stream.on("error", (err) => {
@@ -16149,7 +16149,7 @@ class MarkdownFileBase {
16149
16149
  * Waits for drain event if write buffer is full.
16150
16150
  * Times out after 15 seconds and returns TIMEOUT_SYMBOL.
16151
16151
  */
16152
- this[_b$1] = timeout(async (line) => {
16152
+ this[_b$2] = timeout(async (line) => {
16153
16153
  if (!this._stream.write(line)) {
16154
16154
  await new Promise((resolve) => {
16155
16155
  this._stream.once("drain", resolve);
@@ -16165,7 +16165,7 @@ class MarkdownFileBase {
16165
16165
  * @returns Promise that resolves when initialization is complete
16166
16166
  */
16167
16167
  async waitForInit() {
16168
- await this[WAIT_FOR_INIT_SYMBOL$1]();
16168
+ await this[WAIT_FOR_INIT_SYMBOL$2]();
16169
16169
  }
16170
16170
  /**
16171
16171
  * Writes markdown content to JSONL file with metadata.
@@ -16211,13 +16211,13 @@ class MarkdownFileBase {
16211
16211
  ...searchFlags,
16212
16212
  timestamp: Date.now(),
16213
16213
  }) + "\n";
16214
- const status = await this[WRITE_SAFE_SYMBOL$1](line);
16214
+ const status = await this[WRITE_SAFE_SYMBOL$2](line);
16215
16215
  if (status === TIMEOUT_SYMBOL$1) {
16216
16216
  throw new Error(`Timeout writing to markdown ${this.markdownName}`);
16217
16217
  }
16218
16218
  }
16219
16219
  }
16220
- _a$1 = WAIT_FOR_INIT_SYMBOL$1, _b$1 = WRITE_SAFE_SYMBOL$1;
16220
+ _a$2 = WAIT_FOR_INIT_SYMBOL$2, _b$2 = WRITE_SAFE_SYMBOL$2;
16221
16221
  //@ts-ignore
16222
16222
  MarkdownFileBase = makeExtendable(MarkdownFileBase);
16223
16223
  /**
@@ -23236,7 +23236,7 @@ class ColumnValidationService {
23236
23236
  }
23237
23237
  }
23238
23238
 
23239
- var _a, _b;
23239
+ var _a$1, _b$1;
23240
23240
  const REPORT_BASE_METHOD_NAME_CTOR = "ReportBase.CTOR";
23241
23241
  const REPORT_BASE_METHOD_NAME_WAIT_FOR_INIT = "ReportBase.waitForInit";
23242
23242
  const REPORT_BASE_METHOD_NAME_WRITE = "ReportBase.write";
@@ -23246,8 +23246,8 @@ const REPORT_UTILS_METHOD_NAME_ENABLE = "ReportUtils.enable";
23246
23246
  const REPORT_UTILS_METHOD_NAME_DISABLE = "ReportUtils.disable";
23247
23247
  const REPORT_UTILS_METHOD_NAME_USE_DUMMY = "ReportUtils.useDummy";
23248
23248
  const REPORT_UTILS_METHOD_NAME_USE_JSONL = "ReportUtils.useJsonl";
23249
- const WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
23250
- const WRITE_SAFE_SYMBOL = Symbol("write-safe");
23249
+ const WAIT_FOR_INIT_SYMBOL$1 = Symbol("wait-for-init");
23250
+ const WRITE_SAFE_SYMBOL$1 = Symbol("write-safe");
23251
23251
  /**
23252
23252
  * JSONL-based report adapter with append-only writes.
23253
23253
  *
@@ -23281,7 +23281,7 @@ class ReportBase {
23281
23281
  * Protected by singleshot to ensure one-time execution.
23282
23282
  * Sets up error handler that emits to exitEmitter.
23283
23283
  */
23284
- this[_a] = singleshot(async () => {
23284
+ this[_a$1] = singleshot(async () => {
23285
23285
  await fs.mkdir(this.baseDir, { recursive: true });
23286
23286
  this._stream = createWriteStream(this._filePath, { flags: "a" });
23287
23287
  this._stream.on("error", (err) => {
@@ -23293,7 +23293,7 @@ class ReportBase {
23293
23293
  * Waits for drain event if write buffer is full.
23294
23294
  * Times out after 15 seconds and returns TIMEOUT_SYMBOL.
23295
23295
  */
23296
- this[_b] = timeout(async (line) => {
23296
+ this[_b$1] = timeout(async (line) => {
23297
23297
  if (!this._stream.write(line)) {
23298
23298
  await new Promise((resolve) => {
23299
23299
  this._stream.once("drain", resolve);
@@ -23318,7 +23318,7 @@ class ReportBase {
23318
23318
  reportName: this.reportName,
23319
23319
  initial,
23320
23320
  });
23321
- await this[WAIT_FOR_INIT_SYMBOL]();
23321
+ await this[WAIT_FOR_INIT_SYMBOL$1]();
23322
23322
  }
23323
23323
  /**
23324
23324
  * Writes event data to JSONL file with metadata.
@@ -23365,13 +23365,13 @@ class ReportBase {
23365
23365
  ...searchFlags,
23366
23366
  timestamp: Date.now(),
23367
23367
  }) + "\n";
23368
- const status = await this[WRITE_SAFE_SYMBOL](line);
23368
+ const status = await this[WRITE_SAFE_SYMBOL$1](line);
23369
23369
  if (status === TIMEOUT_SYMBOL$1) {
23370
23370
  throw new Error(`Timeout writing to report ${this.reportName}`);
23371
23371
  }
23372
23372
  }
23373
23373
  }
23374
- _a = WAIT_FOR_INIT_SYMBOL, _b = WRITE_SAFE_SYMBOL;
23374
+ _a$1 = WAIT_FOR_INIT_SYMBOL$1, _b$1 = WRITE_SAFE_SYMBOL$1;
23375
23375
  // @ts-ignore
23376
23376
  ReportBase = makeExtendable(ReportBase);
23377
23377
  /**
@@ -31203,6 +31203,7 @@ async function dumpMessages(resultId, history, result, outputDir = "./dump/strat
31203
31203
  }
31204
31204
  }
31205
31205
 
31206
+ var _a, _b;
31206
31207
  const LOG_PERSIST_METHOD_NAME_WAIT_FOR_INIT = "LogPersistUtils.waitForInit";
31207
31208
  const LOG_PERSIST_METHOD_NAME_LOG = "LogPersistUtils.log";
31208
31209
  const LOG_PERSIST_METHOD_NAME_DEBUG = "LogPersistUtils.debug";
@@ -31218,17 +31219,47 @@ const LOG_ADAPTER_METHOD_NAME_USE_LOGGER = "LogAdapter.useLogger";
31218
31219
  const LOG_ADAPTER_METHOD_NAME_USE_PERSIST = "LogAdapter.usePersist";
31219
31220
  const LOG_ADAPTER_METHOD_NAME_USE_MEMORY = "LogAdapter.useMemory";
31220
31221
  const LOG_ADAPTER_METHOD_NAME_USE_DUMMY = "LogAdapter.useDummy";
31222
+ const LOG_ADAPTER_METHOD_NAME_USE_JSONL = "LogAdapter.useJsonl";
31223
+ const LOG_JSONL_METHOD_NAME_LOG = "LogJsonlUtils.log";
31224
+ const LOG_JSONL_METHOD_NAME_DEBUG = "LogJsonlUtils.debug";
31225
+ const LOG_JSONL_METHOD_NAME_INFO = "LogJsonlUtils.info";
31226
+ const LOG_JSONL_METHOD_NAME_WARN = "LogJsonlUtils.warn";
31227
+ const LOG_JSONL_METHOD_NAME_GET_LIST = "LogJsonlUtils.getList";
31228
+ const WAIT_FOR_INIT_SYMBOL = Symbol("wait-for-init");
31229
+ const WRITE_SAFE_SYMBOL = Symbol("write-safe");
31221
31230
  /**
31222
31231
  * Backtest execution time retrieval function.
31223
31232
  * Returns the 'when' timestamp from the execution context if available, otherwise returns the current time.
31224
31233
  * This allows log entries to be timestamped according to the backtest timeline rather than real-world time, improving log relevance and user experience during backtest analysis.
31225
31234
  */
31226
- const GET_DATE_FN = async () => {
31235
+ const GET_DATE_FN = () => {
31227
31236
  if (ExecutionContextService.hasContext()) {
31228
31237
  return new Date(bt.executionContextService.context.when);
31229
31238
  }
31230
31239
  return new Date();
31231
31240
  };
31241
+ /**
31242
+ * Method context retrieval function.
31243
+ * Returns the current method context from MethodContextService if available, otherwise returns null.
31244
+ * This allows log entries to include contextual information about the strategy, exchange, and frame associated with the log event, enhancing the ability to trace and analyze logs in relation to specific execution contexts within the backtest framework.
31245
+ */
31246
+ const GET_METHOD_CONTEXT_FN = () => {
31247
+ if (MethodContextService.hasContext()) {
31248
+ return bt.methodContextService.context;
31249
+ }
31250
+ return null;
31251
+ };
31252
+ /**
31253
+ * Execution context retrieval function.
31254
+ * Returns the current execution context from ExecutionContextService if available, otherwise returns null.
31255
+ * This allows log entries to include contextual information about the symbol, timestamp, and backtest mode associated with the log event, providing additional insights into the execution environment when analyzing logs.
31256
+ */
31257
+ const GET_EXECUTION_CONTEXT_FN = () => {
31258
+ if (ExecutionContextService.hasContext()) {
31259
+ return bt.executionContextService.context;
31260
+ }
31261
+ return null;
31262
+ };
31232
31263
  /**
31233
31264
  * Persistent log adapter.
31234
31265
  *
@@ -31263,12 +31294,14 @@ class LogPersistUtils {
31263
31294
  this.log = async (topic, ...args) => {
31264
31295
  bt.loggerService.info(LOG_PERSIST_METHOD_NAME_LOG, { topic });
31265
31296
  await this.waitForInit();
31266
- const date = await GET_DATE_FN();
31297
+ const date = GET_DATE_FN();
31267
31298
  this._entries.push({
31268
31299
  id: randomString(),
31269
31300
  type: "log",
31270
31301
  timestamp: Date.now(),
31271
31302
  createdAt: date.toISOString(),
31303
+ methodContext: GET_METHOD_CONTEXT_FN(),
31304
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31272
31305
  topic,
31273
31306
  args,
31274
31307
  });
@@ -31284,12 +31317,14 @@ class LogPersistUtils {
31284
31317
  this.debug = async (topic, ...args) => {
31285
31318
  bt.loggerService.info(LOG_PERSIST_METHOD_NAME_DEBUG, { topic });
31286
31319
  await this.waitForInit();
31287
- const date = await GET_DATE_FN();
31320
+ const date = GET_DATE_FN();
31288
31321
  this._entries.push({
31289
31322
  id: randomString(),
31290
31323
  type: "debug",
31291
31324
  timestamp: Date.now(),
31292
31325
  createdAt: date.toISOString(),
31326
+ methodContext: GET_METHOD_CONTEXT_FN(),
31327
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31293
31328
  topic,
31294
31329
  args,
31295
31330
  });
@@ -31305,12 +31340,14 @@ class LogPersistUtils {
31305
31340
  this.info = async (topic, ...args) => {
31306
31341
  bt.loggerService.info(LOG_PERSIST_METHOD_NAME_INFO, { topic });
31307
31342
  await this.waitForInit();
31308
- const date = await GET_DATE_FN();
31343
+ const date = GET_DATE_FN();
31309
31344
  this._entries.push({
31310
31345
  id: randomString(),
31311
31346
  type: "info",
31312
31347
  timestamp: Date.now(),
31313
31348
  createdAt: date.toISOString(),
31349
+ methodContext: GET_METHOD_CONTEXT_FN(),
31350
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31314
31351
  topic,
31315
31352
  args,
31316
31353
  });
@@ -31326,12 +31363,14 @@ class LogPersistUtils {
31326
31363
  this.warn = async (topic, ...args) => {
31327
31364
  bt.loggerService.info(LOG_PERSIST_METHOD_NAME_WARN, { topic });
31328
31365
  await this.waitForInit();
31329
- const date = await GET_DATE_FN();
31366
+ const date = GET_DATE_FN();
31330
31367
  this._entries.push({
31331
31368
  id: randomString(),
31332
31369
  type: "warn",
31333
31370
  timestamp: Date.now(),
31334
31371
  createdAt: date.toISOString(),
31372
+ methodContext: GET_METHOD_CONTEXT_FN(),
31373
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31335
31374
  topic,
31336
31375
  args,
31337
31376
  });
@@ -31380,12 +31419,14 @@ class LogMemoryUtils {
31380
31419
  */
31381
31420
  this.log = async (topic, ...args) => {
31382
31421
  bt.loggerService.info(LOG_MEMORY_METHOD_NAME_LOG, { topic });
31383
- const date = await GET_DATE_FN();
31422
+ const date = GET_DATE_FN();
31384
31423
  this._entries.push({
31385
31424
  id: randomString(),
31386
31425
  type: "log",
31387
31426
  timestamp: Date.now(),
31388
31427
  createdAt: date.toISOString(),
31428
+ methodContext: GET_METHOD_CONTEXT_FN(),
31429
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31389
31430
  topic,
31390
31431
  args,
31391
31432
  });
@@ -31399,12 +31440,14 @@ class LogMemoryUtils {
31399
31440
  */
31400
31441
  this.debug = async (topic, ...args) => {
31401
31442
  bt.loggerService.info(LOG_MEMORY_METHOD_NAME_DEBUG, { topic });
31402
- const date = await GET_DATE_FN();
31443
+ const date = GET_DATE_FN();
31403
31444
  this._entries.push({
31404
31445
  id: randomString(),
31405
31446
  type: "debug",
31406
31447
  timestamp: Date.now(),
31407
31448
  createdAt: date.toISOString(),
31449
+ methodContext: GET_METHOD_CONTEXT_FN(),
31450
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31408
31451
  topic,
31409
31452
  args,
31410
31453
  });
@@ -31418,12 +31461,14 @@ class LogMemoryUtils {
31418
31461
  */
31419
31462
  this.info = async (topic, ...args) => {
31420
31463
  bt.loggerService.info(LOG_MEMORY_METHOD_NAME_INFO, { topic });
31421
- const date = await GET_DATE_FN();
31464
+ const date = GET_DATE_FN();
31422
31465
  this._entries.push({
31423
31466
  id: randomString(),
31424
31467
  type: "info",
31425
31468
  timestamp: Date.now(),
31426
31469
  createdAt: date.toISOString(),
31470
+ methodContext: GET_METHOD_CONTEXT_FN(),
31471
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31427
31472
  topic,
31428
31473
  args,
31429
31474
  });
@@ -31437,12 +31482,14 @@ class LogMemoryUtils {
31437
31482
  */
31438
31483
  this.warn = async (topic, ...args) => {
31439
31484
  bt.loggerService.info(LOG_MEMORY_METHOD_NAME_WARN, { topic });
31440
- const date = await GET_DATE_FN();
31485
+ const date = GET_DATE_FN();
31441
31486
  this._entries.push({
31442
31487
  id: randomString(),
31443
31488
  type: "warn",
31444
31489
  timestamp: Date.now(),
31445
31490
  createdAt: date.toISOString(),
31491
+ methodContext: GET_METHOD_CONTEXT_FN(),
31492
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31446
31493
  topic,
31447
31494
  args,
31448
31495
  });
@@ -31466,6 +31513,165 @@ class LogMemoryUtils {
31466
31513
  }
31467
31514
  }
31468
31515
  }
31516
+ /**
31517
+ * JSONL-based log adapter with append-only writes and file-based reads.
31518
+ *
31519
+ * Features:
31520
+ * - Writes log entries as JSONL lines via WriteStream (append-only)
31521
+ * - Stream-based writes with backpressure handling
31522
+ * - 15-second timeout protection for write operations
31523
+ * - Automatic directory creation on first write
31524
+ * - Error handling via exitEmitter
31525
+ * - getList reads and parses all lines from the JSONL file
31526
+ *
31527
+ * File format: {dirName}/{fileName}.jsonl
31528
+ * Each line contains a full ILogEntry object.
31529
+ */
31530
+ class LogJsonlUtils {
31531
+ /**
31532
+ * Creates a new JSONL log adapter instance.
31533
+ *
31534
+ * @param fileName - Base file name (without extension)
31535
+ * @param dirName - Directory path for the JSONL file
31536
+ */
31537
+ constructor(fileName, dirName) {
31538
+ this.fileName = fileName;
31539
+ this.dirName = dirName;
31540
+ /** WriteStream instance for append-only writes, null until initialized */
31541
+ this._stream = null;
31542
+ /**
31543
+ * Singleshot initialization: creates directory and opens append stream.
31544
+ * Sets up error handler that emits to exitEmitter.
31545
+ */
31546
+ this[_a] = singleshot(async () => {
31547
+ await fs.mkdir(this.dirName, { recursive: true });
31548
+ this._stream = createWriteStream(this._filePath, { flags: "a" });
31549
+ this._stream.on("error", (err) => {
31550
+ exitEmitter.next(new Error(`LogJsonlUtils stream error for file=${this._filePath} message=${getErrorMessage(err)}`));
31551
+ });
31552
+ });
31553
+ /**
31554
+ * Timeout-protected write with backpressure handling.
31555
+ * Waits for drain event if write buffer is full.
31556
+ * Times out after 15 seconds and returns TIMEOUT_SYMBOL.
31557
+ */
31558
+ this[_b] = timeout(async (line) => {
31559
+ if (!this._stream.write(line)) {
31560
+ await new Promise((resolve) => {
31561
+ this._stream.once("drain", resolve);
31562
+ });
31563
+ }
31564
+ }, 15000);
31565
+ /**
31566
+ * Appends a log entry as a JSONL line.
31567
+ */
31568
+ this._append = async (entry) => {
31569
+ await this[WAIT_FOR_INIT_SYMBOL]();
31570
+ const line = JSON.stringify(entry) + "\n";
31571
+ const status = await this[WRITE_SAFE_SYMBOL](line);
31572
+ if (status === TIMEOUT_SYMBOL$1) {
31573
+ throw new Error(`LogJsonlUtils timeout writing to file=${this._filePath}`);
31574
+ }
31575
+ };
31576
+ /**
31577
+ * Logs a general-purpose message.
31578
+ * @param topic - The log topic / method name
31579
+ * @param args - Additional arguments
31580
+ */
31581
+ this.log = async (topic, ...args) => {
31582
+ bt.loggerService.info(LOG_JSONL_METHOD_NAME_LOG, { topic });
31583
+ const date = GET_DATE_FN();
31584
+ await this._append({
31585
+ id: randomString(),
31586
+ type: "log",
31587
+ timestamp: Date.now(),
31588
+ createdAt: date.toISOString(),
31589
+ methodContext: GET_METHOD_CONTEXT_FN(),
31590
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31591
+ topic,
31592
+ args,
31593
+ });
31594
+ };
31595
+ /**
31596
+ * Logs a debug-level message.
31597
+ * @param topic - The log topic / method name
31598
+ * @param args - Additional arguments
31599
+ */
31600
+ this.debug = async (topic, ...args) => {
31601
+ bt.loggerService.info(LOG_JSONL_METHOD_NAME_DEBUG, { topic });
31602
+ const date = GET_DATE_FN();
31603
+ await this._append({
31604
+ id: randomString(),
31605
+ type: "debug",
31606
+ timestamp: Date.now(),
31607
+ createdAt: date.toISOString(),
31608
+ methodContext: GET_METHOD_CONTEXT_FN(),
31609
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31610
+ topic,
31611
+ args,
31612
+ });
31613
+ };
31614
+ /**
31615
+ * Logs an info-level message.
31616
+ * @param topic - The log topic / method name
31617
+ * @param args - Additional arguments
31618
+ */
31619
+ this.info = async (topic, ...args) => {
31620
+ bt.loggerService.info(LOG_JSONL_METHOD_NAME_INFO, { topic });
31621
+ const date = GET_DATE_FN();
31622
+ await this._append({
31623
+ id: randomString(),
31624
+ type: "info",
31625
+ timestamp: Date.now(),
31626
+ createdAt: date.toISOString(),
31627
+ methodContext: GET_METHOD_CONTEXT_FN(),
31628
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31629
+ topic,
31630
+ args,
31631
+ });
31632
+ };
31633
+ /**
31634
+ * Logs a warning-level message.
31635
+ * @param topic - The log topic / method name
31636
+ * @param args - Additional arguments
31637
+ */
31638
+ this.warn = async (topic, ...args) => {
31639
+ bt.loggerService.info(LOG_JSONL_METHOD_NAME_WARN, { topic });
31640
+ const date = GET_DATE_FN();
31641
+ await this._append({
31642
+ id: randomString(),
31643
+ type: "warn",
31644
+ timestamp: Date.now(),
31645
+ createdAt: date.toISOString(),
31646
+ methodContext: GET_METHOD_CONTEXT_FN(),
31647
+ executionContext: GET_EXECUTION_CONTEXT_FN(),
31648
+ topic,
31649
+ args,
31650
+ });
31651
+ };
31652
+ /**
31653
+ * Reads all log entries from the JSONL file.
31654
+ * Returns empty array if file does not exist.
31655
+ * @returns Array of all log entries
31656
+ */
31657
+ this.getList = async () => {
31658
+ bt.loggerService.info(LOG_JSONL_METHOD_NAME_GET_LIST);
31659
+ let raw;
31660
+ try {
31661
+ raw = await fs.readFile(this._filePath, "utf-8");
31662
+ }
31663
+ catch {
31664
+ return [];
31665
+ }
31666
+ return raw
31667
+ .split("\n")
31668
+ .filter((line) => line.trim().length > 0)
31669
+ .map((line) => JSON.parse(line));
31670
+ };
31671
+ this._filePath = join(this.dirName, this.fileName);
31672
+ }
31673
+ }
31674
+ _a = WAIT_FOR_INIT_SYMBOL, _b = WRITE_SAFE_SYMBOL;
31469
31675
  /**
31470
31676
  * Dummy log adapter that discards all writes.
31471
31677
  *
@@ -31605,6 +31811,18 @@ class LogAdapter {
31605
31811
  bt.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_DUMMY);
31606
31812
  this._log = new LogDummyUtils();
31607
31813
  };
31814
+ /**
31815
+ * Switches to JSONL file log adapter.
31816
+ * Log entries will be appended to {dirName}/{fileName}.jsonl.
31817
+ * Reads are performed by parsing all lines from the file.
31818
+ *
31819
+ * @param fileName - Base file name without extension (default: "log")
31820
+ * @param dirName - Directory for the JSONL file (default: ./dump/log)
31821
+ */
31822
+ this.useJsonl = (fileName = "log.jsonl", dirName = join(process.cwd(), "./dump/log")) => {
31823
+ bt.loggerService.info(LOG_ADAPTER_METHOD_NAME_USE_JSONL);
31824
+ this._log = new LogJsonlUtils(fileName, dirName);
31825
+ };
31608
31826
  }
31609
31827
  }
31610
31828
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backtest-kit",
3
- "version": "3.4.2",
3
+ "version": "3.5.1",
4
4
  "description": "A TypeScript library for trading system backtest",
5
5
  "author": {
6
6
  "name": "Petr Tripolsky",