@tradejs/infra 1.0.9 → 1.0.10

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/dist/ai.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  mergeJsonlFiles,
3
3
  toFileToken
4
- } from "./chunk-KVEZORMS.mjs";
4
+ } from "./chunk-RQP5VSTH.mjs";
5
5
 
6
6
  // src/aiDatasetFile.ts
7
7
  import { once } from "events";
@@ -10,16 +10,81 @@ import fs from "fs/promises";
10
10
  import path from "path";
11
11
  import { createReadStream } from "fs";
12
12
  import readline from "readline";
13
+
14
+ // ../../node_modules/date-fns/toDate.mjs
15
+ function toDate(argument) {
16
+ const argStr = Object.prototype.toString.call(argument);
17
+ if (argument instanceof Date || typeof argument === "object" && argStr === "[object Date]") {
18
+ return new argument.constructor(+argument);
19
+ } else if (typeof argument === "number" || argStr === "[object Number]" || typeof argument === "string" || argStr === "[object String]") {
20
+ return new Date(argument);
21
+ } else {
22
+ return /* @__PURE__ */ new Date(NaN);
23
+ }
24
+ }
25
+
26
+ // ../../node_modules/date-fns/constructFrom.mjs
27
+ function constructFrom(date, value) {
28
+ if (date instanceof Date) {
29
+ return new date.constructor(value);
30
+ } else {
31
+ return new Date(value);
32
+ }
33
+ }
34
+
35
+ // ../../node_modules/date-fns/addMonths.mjs
36
+ function addMonths(date, amount) {
37
+ const _date = toDate(date);
38
+ if (isNaN(amount)) return constructFrom(date, NaN);
39
+ if (!amount) {
40
+ return _date;
41
+ }
42
+ const dayOfMonth = _date.getDate();
43
+ const endOfDesiredMonth = constructFrom(date, _date.getTime());
44
+ endOfDesiredMonth.setMonth(_date.getMonth() + amount + 1, 0);
45
+ const daysInMonth = endOfDesiredMonth.getDate();
46
+ if (dayOfMonth >= daysInMonth) {
47
+ return endOfDesiredMonth;
48
+ } else {
49
+ _date.setFullYear(
50
+ endOfDesiredMonth.getFullYear(),
51
+ endOfDesiredMonth.getMonth(),
52
+ dayOfMonth
53
+ );
54
+ return _date;
55
+ }
56
+ }
57
+
58
+ // ../../node_modules/date-fns/startOfMonth.mjs
59
+ function startOfMonth(date) {
60
+ const _date = toDate(date);
61
+ _date.setDate(1);
62
+ _date.setHours(0, 0, 0, 0);
63
+ return _date;
64
+ }
65
+
66
+ // src/aiDatasetFile.ts
13
67
  var DEFAULT_DIR = "data/ai/export";
14
68
  var AI_DATASET_WRITE_BATCH_SIZE = 100;
15
69
  var AI_MERGE_SORT_RUN_MAX_ROWS = 2e3;
16
70
  var AI_MERGE_SORT_RUN_MAX_BYTES = 16 * 1024 * 1024;
71
+ var AI_MERGE_SORT_MAX_OPEN_RUNS = 16;
17
72
  var AI_CHUNK_FILE_RE = /^ai-dataset-(.+)-chunk-[^.]+\.jsonl$/;
73
+ var BACKTEST_RUN_CHUNK_ID_RE = /^(\d{12}-[a-f0-9]{8})-/;
18
74
  var writerByPath = /* @__PURE__ */ new Map();
19
75
  var getAiChunkFilePath = (strategyName, chunkId, outDir = DEFAULT_DIR) => path.join(
20
76
  outDir,
21
77
  `ai-dataset-${toFileToken(strategyName)}-chunk-${toFileToken(chunkId)}.jsonl`
22
78
  );
79
+ var getAiChunkFilePrefix = (strategyName, runId) => `ai-dataset-${toFileToken(strategyName)}-chunk-${runId ? `${toFileToken(runId)}-` : ""}`;
80
+ var getRunIdFromAiChunkFileName = (strategyName, fileName) => {
81
+ const prefix = getAiChunkFilePrefix(strategyName);
82
+ if (!fileName.startsWith(prefix) || !fileName.endsWith(".jsonl")) {
83
+ return "";
84
+ }
85
+ const chunkToken = fileName.slice(prefix.length, -".jsonl".length);
86
+ return chunkToken.match(BACKTEST_RUN_CHUNK_ID_RE)?.[1] ?? "";
87
+ };
23
88
  var appendAiDatasetRow = async (params) => {
24
89
  const { strategyName, chunkId, row, outDir = DEFAULT_DIR } = params;
25
90
  const filePath = getAiChunkFilePath(strategyName, chunkId, outDir);
@@ -95,8 +160,8 @@ var closeAllAiDatasetWriters = async () => {
95
160
  }
96
161
  };
97
162
  var listAiChunkFiles = async (params) => {
98
- const { strategyName, outDir = DEFAULT_DIR } = params;
99
- const prefix = `ai-dataset-${toFileToken(strategyName)}-chunk-`;
163
+ const { strategyName, outDir = DEFAULT_DIR, runId } = params;
164
+ const prefix = getAiChunkFilePrefix(strategyName, runId);
100
165
  let entries = [];
101
166
  try {
102
167
  entries = await fs.readdir(outDir);
@@ -105,6 +170,20 @@ var listAiChunkFiles = async (params) => {
105
170
  }
106
171
  return entries.filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl")).map((name) => path.join(outDir, name)).sort();
107
172
  };
173
+ var listAiChunkRunIds = async (params) => {
174
+ const { strategyName, outDir = DEFAULT_DIR } = params;
175
+ let entries = [];
176
+ try {
177
+ entries = await fs.readdir(outDir);
178
+ } catch {
179
+ return [];
180
+ }
181
+ return [
182
+ ...new Set(
183
+ entries.map((name) => getRunIdFromAiChunkFileName(strategyName, name)).filter(Boolean)
184
+ )
185
+ ].sort();
186
+ };
108
187
  var listAiChunkStrategies = async (params) => {
109
188
  const outDir = params?.outDir ?? DEFAULT_DIR;
110
189
  let entries = [];
@@ -203,7 +282,7 @@ var readNextNonEmptyLine = async (iterator) => {
203
282
  }
204
283
  }
205
284
  };
206
- var mergeSortedRuns = async (params) => {
285
+ var mergeSortedRunBatch = async (params) => {
207
286
  const { runPaths, outPath } = params;
208
287
  await fs.mkdir(path.dirname(outPath), { recursive: true });
209
288
  const output = createWriteStream(outPath, { encoding: "utf8" });
@@ -264,12 +343,58 @@ var mergeSortedRuns = async (params) => {
264
343
  await outputDone;
265
344
  }
266
345
  };
346
+ var mergeSortedRuns = async (params) => {
347
+ const {
348
+ runPaths,
349
+ outPath,
350
+ tempDir,
351
+ maxOpenRuns = AI_MERGE_SORT_MAX_OPEN_RUNS
352
+ } = params;
353
+ const resolvedMaxOpenRuns = Math.max(2, Math.trunc(maxOpenRuns));
354
+ let currentRunPaths = [...runPaths];
355
+ let passIndex = 0;
356
+ while (currentRunPaths.length > resolvedMaxOpenRuns) {
357
+ const nextRunPaths = [];
358
+ for (let groupStart = 0, groupIndex = 0; groupStart < currentRunPaths.length; groupStart += resolvedMaxOpenRuns, groupIndex += 1) {
359
+ const groupRunPaths = currentRunPaths.slice(
360
+ groupStart,
361
+ groupStart + resolvedMaxOpenRuns
362
+ );
363
+ if (groupRunPaths.length === 1) {
364
+ nextRunPaths.push(groupRunPaths[0]);
365
+ continue;
366
+ }
367
+ const passPath = path.join(
368
+ tempDir,
369
+ `merge-pass-${String(passIndex).padStart(3, "0")}-${String(
370
+ groupIndex
371
+ ).padStart(6, "0")}.jsonl`
372
+ );
373
+ await mergeSortedRunBatch({
374
+ runPaths: groupRunPaths,
375
+ outPath: passPath
376
+ });
377
+ nextRunPaths.push(passPath);
378
+ await Promise.all(
379
+ groupRunPaths.map((runPath) => fs.rm(runPath, { force: true }))
380
+ );
381
+ }
382
+ currentRunPaths = nextRunPaths;
383
+ passIndex += 1;
384
+ }
385
+ await mergeSortedRunBatch({
386
+ runPaths: currentRunPaths,
387
+ outPath
388
+ });
389
+ };
267
390
  var mergeAiJsonlFiles = async (params) => {
268
391
  const {
269
392
  filePaths,
270
393
  outPath,
271
394
  maxRowsInMemory = AI_MERGE_SORT_RUN_MAX_ROWS,
272
- maxBytesInMemory = AI_MERGE_SORT_RUN_MAX_BYTES
395
+ maxBytesInMemory = AI_MERGE_SORT_RUN_MAX_BYTES,
396
+ maxOpenRuns = AI_MERGE_SORT_MAX_OPEN_RUNS,
397
+ shouldIncludeRow
273
398
  } = params;
274
399
  const tempDir = path.join(
275
400
  path.dirname(outPath),
@@ -308,9 +433,13 @@ var mergeAiJsonlFiles = async (params) => {
308
433
  if (!trimmed) {
309
434
  continue;
310
435
  }
436
+ const row = parseAiDatasetLine(trimmed, filePath);
437
+ if (shouldIncludeRow && !shouldIncludeRow(row)) {
438
+ continue;
439
+ }
311
440
  batch.push({
312
441
  line: trimmed,
313
- sortKey: getAiDatasetSortKey(parseAiDatasetLine(trimmed, filePath)),
442
+ sortKey: getAiDatasetSortKey(row),
314
443
  sourceIndex
315
444
  });
316
445
  sourceIndex += 1;
@@ -331,56 +460,275 @@ var mergeAiJsonlFiles = async (params) => {
331
460
  }
332
461
  await mergeSortedRuns({
333
462
  runPaths,
334
- outPath
463
+ outPath,
464
+ tempDir,
465
+ maxOpenRuns
335
466
  });
336
467
  } finally {
337
468
  await fs.rm(tempDir, { recursive: true, force: true });
338
469
  }
339
470
  };
471
+ var getAiDatasetPartPath = (filePath, partIndex) => {
472
+ const parsed = path.parse(filePath);
473
+ return path.join(parsed.dir, `${parsed.name}-part${partIndex}${parsed.ext}`);
474
+ };
475
+ var getPartWindowEndExclusive = (timestamp, monthsPerPart) => {
476
+ const partStart = startOfMonth(new Date(timestamp));
477
+ return addMonths(partStart, Math.max(1, monthsPerPart)).getTime();
478
+ };
479
+ var splitAiMergedDatasetFile = async (params) => {
480
+ const { filePath, monthsPerPart = 2 } = params;
481
+ const resolvedMonthsPerPart = Math.max(1, Math.trunc(monthsPerPart));
482
+ const reader = readline.createInterface({
483
+ input: createReadStream(filePath, { encoding: "utf8" }),
484
+ crlfDelay: Infinity
485
+ });
486
+ const partPaths = [];
487
+ let currentPartIndex = 0;
488
+ let currentPartPath = "";
489
+ let currentPartEndExclusive = Number.NaN;
490
+ let currentWriter = null;
491
+ let currentWriterDone = null;
492
+ let rowCount = 0;
493
+ const openPart = async (timestamp) => {
494
+ currentPartIndex += 1;
495
+ currentPartPath = getAiDatasetPartPath(filePath, currentPartIndex);
496
+ currentPartEndExclusive = getPartWindowEndExclusive(
497
+ timestamp,
498
+ resolvedMonthsPerPart
499
+ );
500
+ currentWriter = createWriteStream(currentPartPath, { encoding: "utf8" });
501
+ currentWriterDone = Promise.all([
502
+ once(currentWriter, "finish"),
503
+ once(currentWriter, "close")
504
+ ]);
505
+ partPaths.push(currentPartPath);
506
+ };
507
+ const closeCurrentWriter = async () => {
508
+ if (!currentWriter || !currentWriterDone) {
509
+ return;
510
+ }
511
+ currentWriter.end();
512
+ await currentWriterDone;
513
+ currentWriter = null;
514
+ currentWriterDone = null;
515
+ };
516
+ const getCurrentWriter = () => {
517
+ if (!currentWriter) {
518
+ throw new Error(
519
+ `AI dataset part writer was not initialized for ${filePath}`
520
+ );
521
+ }
522
+ return currentWriter;
523
+ };
524
+ try {
525
+ for await (const line of reader) {
526
+ const trimmed = line.trim();
527
+ if (!trimmed) {
528
+ continue;
529
+ }
530
+ const row = parseAiDatasetLine(trimmed, filePath);
531
+ const timestamp = Number(row.timestamp);
532
+ const safeTimestamp = Number.isFinite(timestamp) ? timestamp : Date.now();
533
+ if (!currentWriter || !Number.isFinite(currentPartEndExclusive) || safeTimestamp >= currentPartEndExclusive) {
534
+ await closeCurrentWriter();
535
+ await openPart(safeTimestamp);
536
+ }
537
+ const writer = getCurrentWriter();
538
+ if (!writer.write(`${trimmed}
539
+ `)) {
540
+ await once(writer, "drain");
541
+ }
542
+ rowCount += 1;
543
+ }
544
+ } finally {
545
+ reader.close();
546
+ await closeCurrentWriter();
547
+ }
548
+ if (partPaths.length <= 1) {
549
+ for (const partPath of partPaths) {
550
+ await fs.rm(partPath, { force: true });
551
+ }
552
+ return {
553
+ partPaths: [filePath],
554
+ partCount: partPaths.length || (rowCount > 0 ? 1 : 0),
555
+ rowCount,
556
+ splitApplied: false
557
+ };
558
+ }
559
+ await fs.rm(filePath, { force: true });
560
+ return {
561
+ partPaths,
562
+ partCount: partPaths.length,
563
+ rowCount,
564
+ splitApplied: true
565
+ };
566
+ };
340
567
  var readAiDatasetRows = async (params) => {
341
- const { filePath, limitFromEnd = 0, skipFromEnd = 0 } = params;
568
+ const { limitFromEnd = 0, skipFromEnd = 0 } = params;
569
+ const resolvedFilePaths = resolveAiDatasetFilePaths(params);
570
+ if (!resolvedFilePaths.length) {
571
+ return {
572
+ rows: [],
573
+ totalRows: 0
574
+ };
575
+ }
342
576
  const rows = [];
343
577
  const recentLines = [];
344
578
  let totalRows = 0;
345
579
  const recentWindowLimit = limitFromEnd > 0 ? limitFromEnd + Math.max(0, skipFromEnd) : 0;
580
+ for (const currentFilePath of resolvedFilePaths) {
581
+ const reader = readline.createInterface({
582
+ input: createReadStream(currentFilePath, { encoding: "utf8" }),
583
+ crlfDelay: Infinity
584
+ });
585
+ for await (const line of reader) {
586
+ const trimmed = line.trim();
587
+ if (!trimmed) {
588
+ continue;
589
+ }
590
+ totalRows += 1;
591
+ if (limitFromEnd > 0) {
592
+ if (recentLines.length === recentWindowLimit) {
593
+ recentLines.shift();
594
+ }
595
+ recentLines.push(trimmed);
596
+ } else {
597
+ const row = JSON.parse(trimmed);
598
+ rows.push(row);
599
+ }
600
+ }
601
+ reader.close();
602
+ }
603
+ const effectiveSkip = Math.max(0, skipFromEnd);
604
+ const selectedRecentLines = effectiveSkip > 0 ? recentLines.slice(0, Math.max(0, recentLines.length - effectiveSkip)) : recentLines;
605
+ const selectedRows = limitFromEnd > 0 ? selectedRecentLines.map((line) => JSON.parse(line)) : effectiveSkip > 0 ? rows.slice(0, Math.max(0, rows.length - effectiveSkip)) : rows;
606
+ return {
607
+ rows: selectedRows,
608
+ totalRows
609
+ };
610
+ };
611
+ var resolveAiDatasetFilePaths = (params) => (Array.isArray(params.filePaths) && params.filePaths.length ? params.filePaths : params.filePath ? [params.filePath] : []).map((item) => path.resolve(item));
612
+ var countNonEmptyAiDatasetRows = async (filePath) => {
613
+ let totalRows = 0;
346
614
  const reader = readline.createInterface({
347
615
  input: createReadStream(filePath, { encoding: "utf8" }),
348
616
  crlfDelay: Infinity
349
617
  });
350
618
  for await (const line of reader) {
351
- const trimmed = line.trim();
352
- if (!trimmed) {
353
- continue;
619
+ if (line.trim()) {
620
+ totalRows += 1;
621
+ }
622
+ }
623
+ reader.close();
624
+ return totalRows;
625
+ };
626
+ var countAiDatasetRows = async (params) => {
627
+ const { limitFromEnd = 0, skipFromEnd = 0 } = params;
628
+ const resolvedFilePaths = resolveAiDatasetFilePaths(params);
629
+ let totalRows = 0;
630
+ for (const filePath of resolvedFilePaths) {
631
+ totalRows += await countNonEmptyAiDatasetRows(filePath);
632
+ }
633
+ const effectiveSkip = Math.max(0, skipFromEnd);
634
+ const selectedRows = limitFromEnd > 0 ? Math.min(limitFromEnd, Math.max(0, totalRows - effectiveSkip)) : Math.max(0, totalRows - effectiveSkip);
635
+ return {
636
+ totalRows,
637
+ selectedRows
638
+ };
639
+ };
640
+ var streamAiDatasetRows = async (params) => {
641
+ const { limitFromEnd = 0, skipFromEnd = 0, onRow } = params;
642
+ const resolvedFilePaths = resolveAiDatasetFilePaths(params);
643
+ if (!resolvedFilePaths.length) {
644
+ return {
645
+ totalRows: 0,
646
+ selectedRows: 0
647
+ };
648
+ }
649
+ const effectiveSkip = Math.max(0, skipFromEnd);
650
+ let totalRows = 0;
651
+ let selectedRows = 0;
652
+ if (limitFromEnd > 0) {
653
+ const recentLines = [];
654
+ const recentWindowLimit = limitFromEnd + effectiveSkip;
655
+ for (const currentFilePath of resolvedFilePaths) {
656
+ const reader = readline.createInterface({
657
+ input: createReadStream(currentFilePath, { encoding: "utf8" }),
658
+ crlfDelay: Infinity
659
+ });
660
+ for await (const line of reader) {
661
+ const trimmed = line.trim();
662
+ if (!trimmed) {
663
+ continue;
664
+ }
665
+ totalRows += 1;
666
+ if (recentLines.length === recentWindowLimit) {
667
+ recentLines.shift();
668
+ }
669
+ recentLines.push(trimmed);
670
+ }
671
+ reader.close();
672
+ }
673
+ const selectedRecentLines = effectiveSkip > 0 ? recentLines.slice(0, Math.max(0, recentLines.length - effectiveSkip)) : recentLines;
674
+ for (const line of selectedRecentLines) {
675
+ await onRow(JSON.parse(line), selectedRows);
676
+ selectedRows += 1;
354
677
  }
355
- totalRows += 1;
356
- if (limitFromEnd > 0) {
357
- if (recentLines.length === recentWindowLimit) {
358
- recentLines.shift();
678
+ return {
679
+ totalRows,
680
+ selectedRows
681
+ };
682
+ }
683
+ const trailingSkipBuffer = [];
684
+ for (const currentFilePath of resolvedFilePaths) {
685
+ const reader = readline.createInterface({
686
+ input: createReadStream(currentFilePath, { encoding: "utf8" }),
687
+ crlfDelay: Infinity
688
+ });
689
+ for await (const line of reader) {
690
+ const trimmed = line.trim();
691
+ if (!trimmed) {
692
+ continue;
359
693
  }
360
- recentLines.push(trimmed);
361
- } else {
362
- const row = JSON.parse(trimmed);
363
- rows.push(row);
694
+ totalRows += 1;
695
+ if (effectiveSkip > 0) {
696
+ trailingSkipBuffer.push(trimmed);
697
+ if (trailingSkipBuffer.length <= effectiveSkip) {
698
+ continue;
699
+ }
700
+ const selectedLine = trailingSkipBuffer.shift();
701
+ if (!selectedLine) {
702
+ continue;
703
+ }
704
+ await onRow(JSON.parse(selectedLine), selectedRows);
705
+ selectedRows += 1;
706
+ continue;
707
+ }
708
+ await onRow(JSON.parse(trimmed), selectedRows);
709
+ selectedRows += 1;
364
710
  }
711
+ reader.close();
365
712
  }
366
- const effectiveSkip = Math.max(0, skipFromEnd);
367
- const selectedRecentLines = effectiveSkip > 0 ? recentLines.slice(0, Math.max(0, recentLines.length - effectiveSkip)) : recentLines;
368
- const selectedRows = limitFromEnd > 0 ? selectedRecentLines.map((line) => JSON.parse(line)) : effectiveSkip > 0 ? rows.slice(0, Math.max(0, rows.length - effectiveSkip)) : rows;
369
713
  return {
370
- rows: selectedRows,
371
- totalRows
714
+ totalRows,
715
+ selectedRows
372
716
  };
373
717
  };
374
718
  export {
375
719
  appendAiDatasetRow,
376
720
  closeAiDatasetWriter,
377
721
  closeAllAiDatasetWriters,
722
+ countAiDatasetRows,
378
723
  flushAiDatasetWriter,
379
724
  getAiChunkFilePath,
380
725
  listAiChunkFiles,
726
+ listAiChunkRunIds,
381
727
  listAiChunkStrategies,
382
728
  mergeAiJsonlFiles,
383
729
  mergeJsonlFiles,
384
730
  readAiDatasetRows,
731
+ splitAiMergedDatasetFile,
732
+ streamAiDatasetRows,
385
733
  toFileToken
386
734
  };
@@ -0,0 +1,57 @@
1
+ import { OrderLogData, PositionLogData } from '@tradejs/types';
2
+
3
+ interface BacktestArtifactRef {
4
+ kind: 'file';
5
+ version: 1;
6
+ path: string;
7
+ }
8
+ declare const writeCachedBacktestArtifacts: ({ orderLog, orderLogId, positionLog, projectRoot, userName, }: {
9
+ orderLog: OrderLogData;
10
+ orderLogId: string;
11
+ positionLog: PositionLogData;
12
+ projectRoot?: string;
13
+ userName: string;
14
+ }) => Promise<{
15
+ orderLog: BacktestArtifactRef;
16
+ positionLog: BacktestArtifactRef;
17
+ }>;
18
+ declare const readCachedBacktestArtifacts: ({ orderLogId, projectRoot, userName, }: {
19
+ orderLogId: string;
20
+ projectRoot?: string;
21
+ userName: string;
22
+ }) => Promise<{
23
+ orderLog: OrderLogData | null;
24
+ positionLog: PositionLogData | null;
25
+ }>;
26
+ declare const deleteCachedBacktestArtifacts: ({ orderLogId, projectRoot, userName, }: {
27
+ orderLogId: string;
28
+ projectRoot?: string;
29
+ userName: string;
30
+ }) => Promise<boolean>;
31
+ declare const writePersistedBacktestOrderLog: ({ orderLog, projectRoot, strategyName, testName, userName, }: {
32
+ orderLog: OrderLogData;
33
+ projectRoot?: string;
34
+ strategyName: string;
35
+ testName: string;
36
+ userName: string;
37
+ }) => Promise<BacktestArtifactRef>;
38
+ declare const readPersistedBacktestOrderLog: ({ projectRoot, ref, strategyName, testName, userName, }: {
39
+ projectRoot?: string;
40
+ ref?: BacktestArtifactRef | null;
41
+ strategyName: string;
42
+ testName: string;
43
+ userName: string;
44
+ }) => Promise<OrderLogData | null>;
45
+ declare const deletePersistedBacktestOrderLog: ({ projectRoot, ref, strategyName, testName, userName, }: {
46
+ projectRoot?: string;
47
+ ref?: BacktestArtifactRef | null;
48
+ strategyName: string;
49
+ testName: string;
50
+ userName: string;
51
+ }) => Promise<boolean>;
52
+ declare const parseBacktestArtifactRef: (value: unknown) => BacktestArtifactRef | null;
53
+ declare const getBacktestArtifactsRootDir: (projectRoot?: string) => string;
54
+ declare const getBacktestCacheArtifactsDirForUser: (userName: string, projectRoot?: string) => string;
55
+ declare const getPersistedBacktestArtifactsDirForUser: (userName: string, projectRoot?: string) => string;
56
+
57
+ export { type BacktestArtifactRef, deleteCachedBacktestArtifacts, deletePersistedBacktestOrderLog, getBacktestArtifactsRootDir, getBacktestCacheArtifactsDirForUser, getPersistedBacktestArtifactsDirForUser, parseBacktestArtifactRef, readCachedBacktestArtifacts, readPersistedBacktestOrderLog, writeCachedBacktestArtifacts, writePersistedBacktestOrderLog };
@@ -0,0 +1,57 @@
1
+ import { OrderLogData, PositionLogData } from '@tradejs/types';
2
+
3
+ interface BacktestArtifactRef {
4
+ kind: 'file';
5
+ version: 1;
6
+ path: string;
7
+ }
8
+ declare const writeCachedBacktestArtifacts: ({ orderLog, orderLogId, positionLog, projectRoot, userName, }: {
9
+ orderLog: OrderLogData;
10
+ orderLogId: string;
11
+ positionLog: PositionLogData;
12
+ projectRoot?: string;
13
+ userName: string;
14
+ }) => Promise<{
15
+ orderLog: BacktestArtifactRef;
16
+ positionLog: BacktestArtifactRef;
17
+ }>;
18
+ declare const readCachedBacktestArtifacts: ({ orderLogId, projectRoot, userName, }: {
19
+ orderLogId: string;
20
+ projectRoot?: string;
21
+ userName: string;
22
+ }) => Promise<{
23
+ orderLog: OrderLogData | null;
24
+ positionLog: PositionLogData | null;
25
+ }>;
26
+ declare const deleteCachedBacktestArtifacts: ({ orderLogId, projectRoot, userName, }: {
27
+ orderLogId: string;
28
+ projectRoot?: string;
29
+ userName: string;
30
+ }) => Promise<boolean>;
31
+ declare const writePersistedBacktestOrderLog: ({ orderLog, projectRoot, strategyName, testName, userName, }: {
32
+ orderLog: OrderLogData;
33
+ projectRoot?: string;
34
+ strategyName: string;
35
+ testName: string;
36
+ userName: string;
37
+ }) => Promise<BacktestArtifactRef>;
38
+ declare const readPersistedBacktestOrderLog: ({ projectRoot, ref, strategyName, testName, userName, }: {
39
+ projectRoot?: string;
40
+ ref?: BacktestArtifactRef | null;
41
+ strategyName: string;
42
+ testName: string;
43
+ userName: string;
44
+ }) => Promise<OrderLogData | null>;
45
+ declare const deletePersistedBacktestOrderLog: ({ projectRoot, ref, strategyName, testName, userName, }: {
46
+ projectRoot?: string;
47
+ ref?: BacktestArtifactRef | null;
48
+ strategyName: string;
49
+ testName: string;
50
+ userName: string;
51
+ }) => Promise<boolean>;
52
+ declare const parseBacktestArtifactRef: (value: unknown) => BacktestArtifactRef | null;
53
+ declare const getBacktestArtifactsRootDir: (projectRoot?: string) => string;
54
+ declare const getBacktestCacheArtifactsDirForUser: (userName: string, projectRoot?: string) => string;
55
+ declare const getPersistedBacktestArtifactsDirForUser: (userName: string, projectRoot?: string) => string;
56
+
57
+ export { type BacktestArtifactRef, deleteCachedBacktestArtifacts, deletePersistedBacktestOrderLog, getBacktestArtifactsRootDir, getBacktestCacheArtifactsDirForUser, getPersistedBacktestArtifactsDirForUser, parseBacktestArtifactRef, readCachedBacktestArtifacts, readPersistedBacktestOrderLog, writeCachedBacktestArtifacts, writePersistedBacktestOrderLog };