backtest-kit 1.4.11 → 1.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.cjs +328 -84
- package/build/index.mjs +328 -85
- package/package.json +1 -1
- package/types.d.ts +182 -53
package/build/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import fs, { mkdir, writeFile } from 'fs/promises';
|
|
|
5
5
|
import path, { join } from 'path';
|
|
6
6
|
import crypto from 'crypto';
|
|
7
7
|
import os from 'os';
|
|
8
|
+
import { promises } from 'fs';
|
|
8
9
|
|
|
9
10
|
const GLOBAL_CONFIG = {
|
|
10
11
|
/**
|
|
@@ -160,6 +161,7 @@ const markdownServices$1 = {
|
|
|
160
161
|
walkerMarkdownService: Symbol('walkerMarkdownService'),
|
|
161
162
|
heatMarkdownService: Symbol('heatMarkdownService'),
|
|
162
163
|
partialMarkdownService: Symbol('partialMarkdownService'),
|
|
164
|
+
outlineMarkdownService: Symbol('outlineMarkdownService'),
|
|
163
165
|
};
|
|
164
166
|
const validationServices$1 = {
|
|
165
167
|
exchangeValidationService: Symbol('exchangeValidationService'),
|
|
@@ -10460,6 +10462,11 @@ const columns = [
|
|
|
10460
10462
|
label: "Symbol",
|
|
10461
10463
|
format: (data) => data.symbol,
|
|
10462
10464
|
},
|
|
10465
|
+
{
|
|
10466
|
+
key: "strategyName",
|
|
10467
|
+
label: "Strategy",
|
|
10468
|
+
format: (data) => data.strategyName,
|
|
10469
|
+
},
|
|
10463
10470
|
{
|
|
10464
10471
|
key: "signalId",
|
|
10465
10472
|
label: "Signal ID",
|
|
@@ -10494,7 +10501,7 @@ const columns = [
|
|
|
10494
10501
|
/** Maximum number of events to store in partial reports */
|
|
10495
10502
|
const MAX_EVENTS = 250;
|
|
10496
10503
|
/**
|
|
10497
|
-
* Storage class for accumulating partial profit/loss events per symbol.
|
|
10504
|
+
* Storage class for accumulating partial profit/loss events per symbol-strategy pair.
|
|
10498
10505
|
* Maintains a chronological list of profit and loss level events.
|
|
10499
10506
|
*/
|
|
10500
10507
|
class ReportStorage {
|
|
@@ -10505,17 +10512,17 @@ class ReportStorage {
|
|
|
10505
10512
|
/**
|
|
10506
10513
|
* Adds a profit event to the storage.
|
|
10507
10514
|
*
|
|
10508
|
-
* @param symbol - Trading pair symbol
|
|
10509
10515
|
* @param data - Signal row data
|
|
10510
10516
|
* @param currentPrice - Current market price
|
|
10511
10517
|
* @param level - Profit level reached
|
|
10512
10518
|
* @param backtest - True if backtest mode
|
|
10513
10519
|
*/
|
|
10514
|
-
addProfitEvent(
|
|
10520
|
+
addProfitEvent(data, currentPrice, level, backtest, timestamp) {
|
|
10515
10521
|
this._eventList.push({
|
|
10516
10522
|
timestamp,
|
|
10517
10523
|
action: "profit",
|
|
10518
|
-
symbol,
|
|
10524
|
+
symbol: data.symbol,
|
|
10525
|
+
strategyName: data.strategyName,
|
|
10519
10526
|
signalId: data.id,
|
|
10520
10527
|
position: data.position,
|
|
10521
10528
|
currentPrice,
|
|
@@ -10530,17 +10537,17 @@ class ReportStorage {
|
|
|
10530
10537
|
/**
|
|
10531
10538
|
* Adds a loss event to the storage.
|
|
10532
10539
|
*
|
|
10533
|
-
* @param symbol - Trading pair symbol
|
|
10534
10540
|
* @param data - Signal row data
|
|
10535
10541
|
* @param currentPrice - Current market price
|
|
10536
10542
|
* @param level - Loss level reached
|
|
10537
10543
|
* @param backtest - True if backtest mode
|
|
10538
10544
|
*/
|
|
10539
|
-
addLossEvent(
|
|
10545
|
+
addLossEvent(data, currentPrice, level, backtest, timestamp) {
|
|
10540
10546
|
this._eventList.push({
|
|
10541
10547
|
timestamp,
|
|
10542
10548
|
action: "loss",
|
|
10543
|
-
symbol,
|
|
10549
|
+
symbol: data.symbol,
|
|
10550
|
+
strategyName: data.strategyName,
|
|
10544
10551
|
signalId: data.id,
|
|
10545
10552
|
position: data.position,
|
|
10546
10553
|
currentPrice,
|
|
@@ -10576,35 +10583,37 @@ class ReportStorage {
|
|
|
10576
10583
|
};
|
|
10577
10584
|
}
|
|
10578
10585
|
/**
|
|
10579
|
-
* Generates markdown report with all partial events for a symbol (View).
|
|
10586
|
+
* Generates markdown report with all partial events for a symbol-strategy pair (View).
|
|
10580
10587
|
*
|
|
10581
10588
|
* @param symbol - Trading pair symbol
|
|
10589
|
+
* @param strategyName - Strategy name
|
|
10582
10590
|
* @returns Markdown formatted report with all events
|
|
10583
10591
|
*/
|
|
10584
|
-
async getReport(symbol) {
|
|
10592
|
+
async getReport(symbol, strategyName) {
|
|
10585
10593
|
const stats = await this.getData();
|
|
10586
10594
|
if (stats.totalEvents === 0) {
|
|
10587
|
-
return str.newline(`# Partial Profit/Loss Report: ${symbol}`, "", "No partial profit/loss events recorded yet.");
|
|
10595
|
+
return str.newline(`# Partial Profit/Loss Report: ${symbol}:${strategyName}`, "", "No partial profit/loss events recorded yet.");
|
|
10588
10596
|
}
|
|
10589
10597
|
const header = columns.map((col) => col.label);
|
|
10590
10598
|
const separator = columns.map(() => "---");
|
|
10591
10599
|
const rows = this._eventList.map((event) => columns.map((col) => col.format(event)));
|
|
10592
10600
|
const tableData = [header, separator, ...rows];
|
|
10593
10601
|
const table = str.newline(tableData.map((row) => `| ${row.join(" | ")} |`));
|
|
10594
|
-
return str.newline(`# Partial Profit/Loss Report: ${symbol}`, "", table, "", `**Total events:** ${stats.totalEvents}`, `**Profit events:** ${stats.totalProfit}`, `**Loss events:** ${stats.totalLoss}`);
|
|
10602
|
+
return str.newline(`# Partial Profit/Loss Report: ${symbol}:${strategyName}`, "", table, "", `**Total events:** ${stats.totalEvents}`, `**Profit events:** ${stats.totalProfit}`, `**Loss events:** ${stats.totalLoss}`);
|
|
10595
10603
|
}
|
|
10596
10604
|
/**
|
|
10597
|
-
* Saves symbol report to disk.
|
|
10605
|
+
* Saves symbol-strategy report to disk.
|
|
10598
10606
|
*
|
|
10599
10607
|
* @param symbol - Trading pair symbol
|
|
10608
|
+
* @param strategyName - Strategy name
|
|
10600
10609
|
* @param path - Directory path to save report (default: "./dump/partial")
|
|
10601
10610
|
*/
|
|
10602
|
-
async dump(symbol, path = "./dump/partial") {
|
|
10603
|
-
const markdown = await this.getReport(symbol);
|
|
10611
|
+
async dump(symbol, strategyName, path = "./dump/partial") {
|
|
10612
|
+
const markdown = await this.getReport(symbol, strategyName);
|
|
10604
10613
|
try {
|
|
10605
10614
|
const dir = join(process.cwd(), path);
|
|
10606
10615
|
await mkdir(dir, { recursive: true });
|
|
10607
|
-
const filename = `${symbol}.md`;
|
|
10616
|
+
const filename = `${symbol}_${strategyName}.md`;
|
|
10608
10617
|
const filepath = join(dir, filename);
|
|
10609
10618
|
await writeFile(filepath, markdown, "utf-8");
|
|
10610
10619
|
console.log(`Partial profit/loss report saved: ${filepath}`);
|
|
@@ -10619,10 +10628,10 @@ class ReportStorage {
|
|
|
10619
10628
|
*
|
|
10620
10629
|
* Features:
|
|
10621
10630
|
* - Listens to partial profit and loss events via partialProfitSubject/partialLossSubject
|
|
10622
|
-
* - Accumulates all events (profit, loss) per symbol
|
|
10631
|
+
* - Accumulates all events (profit, loss) per symbol-strategy pair
|
|
10623
10632
|
* - Generates markdown tables with detailed event information
|
|
10624
10633
|
* - Provides statistics (total profit/loss events)
|
|
10625
|
-
* - Saves reports to disk in dump/partial/{symbol}.md
|
|
10634
|
+
* - Saves reports to disk in dump/partial/{symbol}_{strategyName}.md
|
|
10626
10635
|
*
|
|
10627
10636
|
* @example
|
|
10628
10637
|
* ```typescript
|
|
@@ -10632,7 +10641,7 @@ class ReportStorage {
|
|
|
10632
10641
|
* // No manual callback setup needed
|
|
10633
10642
|
*
|
|
10634
10643
|
* // Later: generate and save report
|
|
10635
|
-
* await service.dump("BTCUSDT");
|
|
10644
|
+
* await service.dump("BTCUSDT", "my-strategy");
|
|
10636
10645
|
* ```
|
|
10637
10646
|
*/
|
|
10638
10647
|
class PartialMarkdownService {
|
|
@@ -10640,10 +10649,10 @@ class PartialMarkdownService {
|
|
|
10640
10649
|
/** Logger service for debug output */
|
|
10641
10650
|
this.loggerService = inject(TYPES.loggerService);
|
|
10642
10651
|
/**
|
|
10643
|
-
* Memoized function to get or create ReportStorage for a symbol.
|
|
10644
|
-
* Each symbol gets its own isolated storage instance.
|
|
10652
|
+
* Memoized function to get or create ReportStorage for a symbol-strategy pair.
|
|
10653
|
+
* Each symbol-strategy combination gets its own isolated storage instance.
|
|
10645
10654
|
*/
|
|
10646
|
-
this.getStorage = memoize(([symbol]) =>
|
|
10655
|
+
this.getStorage = memoize(([symbol, strategyName]) => JSON.stringify([symbol, strategyName]), () => new ReportStorage());
|
|
10647
10656
|
/**
|
|
10648
10657
|
* Processes profit events and accumulates them.
|
|
10649
10658
|
* Should be called from partialProfitSubject subscription.
|
|
@@ -10660,8 +10669,8 @@ class PartialMarkdownService {
|
|
|
10660
10669
|
this.loggerService.log("partialMarkdownService tickProfit", {
|
|
10661
10670
|
data,
|
|
10662
10671
|
});
|
|
10663
|
-
const storage = this.getStorage(data.symbol);
|
|
10664
|
-
storage.addProfitEvent(data.
|
|
10672
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
10673
|
+
storage.addProfitEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
10665
10674
|
};
|
|
10666
10675
|
/**
|
|
10667
10676
|
* Processes loss events and accumulates them.
|
|
@@ -10679,101 +10688,113 @@ class PartialMarkdownService {
|
|
|
10679
10688
|
this.loggerService.log("partialMarkdownService tickLoss", {
|
|
10680
10689
|
data,
|
|
10681
10690
|
});
|
|
10682
|
-
const storage = this.getStorage(data.symbol);
|
|
10683
|
-
storage.addLossEvent(data.
|
|
10691
|
+
const storage = this.getStorage(data.symbol, data.data.strategyName);
|
|
10692
|
+
storage.addLossEvent(data.data, data.currentPrice, data.level, data.backtest, data.timestamp);
|
|
10684
10693
|
};
|
|
10685
10694
|
/**
|
|
10686
|
-
* Gets statistical data from all partial profit/loss events for a symbol.
|
|
10695
|
+
* Gets statistical data from all partial profit/loss events for a symbol-strategy pair.
|
|
10687
10696
|
* Delegates to ReportStorage.getData().
|
|
10688
10697
|
*
|
|
10689
10698
|
* @param symbol - Trading pair symbol to get data for
|
|
10699
|
+
* @param strategyName - Strategy name to get data for
|
|
10690
10700
|
* @returns Statistical data object with all metrics
|
|
10691
10701
|
*
|
|
10692
10702
|
* @example
|
|
10693
10703
|
* ```typescript
|
|
10694
10704
|
* const service = new PartialMarkdownService();
|
|
10695
|
-
* const stats = await service.getData("BTCUSDT");
|
|
10705
|
+
* const stats = await service.getData("BTCUSDT", "my-strategy");
|
|
10696
10706
|
* console.log(stats.totalProfit, stats.totalLoss);
|
|
10697
10707
|
* ```
|
|
10698
10708
|
*/
|
|
10699
|
-
this.getData = async (symbol) => {
|
|
10709
|
+
this.getData = async (symbol, strategyName) => {
|
|
10700
10710
|
this.loggerService.log("partialMarkdownService getData", {
|
|
10701
10711
|
symbol,
|
|
10712
|
+
strategyName,
|
|
10702
10713
|
});
|
|
10703
|
-
const storage = this.getStorage(symbol);
|
|
10714
|
+
const storage = this.getStorage(symbol, strategyName);
|
|
10704
10715
|
return storage.getData();
|
|
10705
10716
|
};
|
|
10706
10717
|
/**
|
|
10707
|
-
* Generates markdown report with all partial events for a symbol.
|
|
10718
|
+
* Generates markdown report with all partial events for a symbol-strategy pair.
|
|
10708
10719
|
* Delegates to ReportStorage.getReport().
|
|
10709
10720
|
*
|
|
10710
10721
|
* @param symbol - Trading pair symbol to generate report for
|
|
10722
|
+
* @param strategyName - Strategy name to generate report for
|
|
10711
10723
|
* @returns Markdown formatted report string with table of all events
|
|
10712
10724
|
*
|
|
10713
10725
|
* @example
|
|
10714
10726
|
* ```typescript
|
|
10715
10727
|
* const service = new PartialMarkdownService();
|
|
10716
|
-
* const markdown = await service.getReport("BTCUSDT");
|
|
10728
|
+
* const markdown = await service.getReport("BTCUSDT", "my-strategy");
|
|
10717
10729
|
* console.log(markdown);
|
|
10718
10730
|
* ```
|
|
10719
10731
|
*/
|
|
10720
|
-
this.getReport = async (symbol) => {
|
|
10732
|
+
this.getReport = async (symbol, strategyName) => {
|
|
10721
10733
|
this.loggerService.log("partialMarkdownService getReport", {
|
|
10722
10734
|
symbol,
|
|
10735
|
+
strategyName,
|
|
10723
10736
|
});
|
|
10724
|
-
const storage = this.getStorage(symbol);
|
|
10725
|
-
return storage.getReport(symbol);
|
|
10737
|
+
const storage = this.getStorage(symbol, strategyName);
|
|
10738
|
+
return storage.getReport(symbol, strategyName);
|
|
10726
10739
|
};
|
|
10727
10740
|
/**
|
|
10728
|
-
* Saves symbol report to disk.
|
|
10741
|
+
* Saves symbol-strategy report to disk.
|
|
10729
10742
|
* Creates directory if it doesn't exist.
|
|
10730
10743
|
* Delegates to ReportStorage.dump().
|
|
10731
10744
|
*
|
|
10732
10745
|
* @param symbol - Trading pair symbol to save report for
|
|
10746
|
+
* @param strategyName - Strategy name to save report for
|
|
10733
10747
|
* @param path - Directory path to save report (default: "./dump/partial")
|
|
10734
10748
|
*
|
|
10735
10749
|
* @example
|
|
10736
10750
|
* ```typescript
|
|
10737
10751
|
* const service = new PartialMarkdownService();
|
|
10738
10752
|
*
|
|
10739
|
-
* // Save to default path: ./dump/partial/
|
|
10740
|
-
* await service.dump("BTCUSDT");
|
|
10753
|
+
* // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
|
|
10754
|
+
* await service.dump("BTCUSDT", "my-strategy");
|
|
10741
10755
|
*
|
|
10742
|
-
* // Save to custom path: ./custom/path/
|
|
10743
|
-
* await service.dump("BTCUSDT", "./custom/path");
|
|
10756
|
+
* // Save to custom path: ./custom/path/BTCUSDT_my-strategy.md
|
|
10757
|
+
* await service.dump("BTCUSDT", "my-strategy", "./custom/path");
|
|
10744
10758
|
* ```
|
|
10745
10759
|
*/
|
|
10746
|
-
this.dump = async (symbol, path = "./dump/partial") => {
|
|
10760
|
+
this.dump = async (symbol, strategyName, path = "./dump/partial") => {
|
|
10747
10761
|
this.loggerService.log("partialMarkdownService dump", {
|
|
10748
10762
|
symbol,
|
|
10763
|
+
strategyName,
|
|
10749
10764
|
path,
|
|
10750
10765
|
});
|
|
10751
|
-
const storage = this.getStorage(symbol);
|
|
10752
|
-
await storage.dump(symbol, path);
|
|
10766
|
+
const storage = this.getStorage(symbol, strategyName);
|
|
10767
|
+
await storage.dump(symbol, strategyName, path);
|
|
10753
10768
|
};
|
|
10754
10769
|
/**
|
|
10755
10770
|
* Clears accumulated event data from storage.
|
|
10756
|
-
* If
|
|
10757
|
-
* If
|
|
10771
|
+
* If ctx is provided, clears only that specific symbol-strategy pair's data.
|
|
10772
|
+
* If nothing is provided, clears all data.
|
|
10758
10773
|
*
|
|
10759
|
-
* @param
|
|
10774
|
+
* @param ctx - Optional context with symbol and strategyName
|
|
10760
10775
|
*
|
|
10761
10776
|
* @example
|
|
10762
10777
|
* ```typescript
|
|
10763
10778
|
* const service = new PartialMarkdownService();
|
|
10764
10779
|
*
|
|
10765
|
-
* // Clear specific symbol
|
|
10766
|
-
* await service.clear("BTCUSDT");
|
|
10780
|
+
* // Clear specific symbol-strategy pair
|
|
10781
|
+
* await service.clear({ symbol: "BTCUSDT", strategyName: "my-strategy" });
|
|
10767
10782
|
*
|
|
10768
|
-
* // Clear all
|
|
10783
|
+
* // Clear all data
|
|
10769
10784
|
* await service.clear();
|
|
10770
10785
|
* ```
|
|
10771
10786
|
*/
|
|
10772
|
-
this.clear = async (
|
|
10787
|
+
this.clear = async (ctx) => {
|
|
10773
10788
|
this.loggerService.log("partialMarkdownService clear", {
|
|
10774
|
-
|
|
10789
|
+
ctx,
|
|
10775
10790
|
});
|
|
10776
|
-
|
|
10791
|
+
if (ctx) {
|
|
10792
|
+
const key = JSON.stringify([ctx.symbol, ctx.strategyName]);
|
|
10793
|
+
this.getStorage.clear(key);
|
|
10794
|
+
}
|
|
10795
|
+
else {
|
|
10796
|
+
this.getStorage.clear();
|
|
10797
|
+
}
|
|
10777
10798
|
};
|
|
10778
10799
|
/**
|
|
10779
10800
|
* Initializes the service by subscribing to partial profit/loss events.
|
|
@@ -10904,6 +10925,145 @@ class PartialGlobalService {
|
|
|
10904
10925
|
}
|
|
10905
10926
|
}
|
|
10906
10927
|
|
|
10928
|
+
/**
|
|
10929
|
+
* Warning threshold for message size in kilobytes.
|
|
10930
|
+
* Messages exceeding this size trigger console warnings.
|
|
10931
|
+
*/
|
|
10932
|
+
const WARN_KB = 100;
|
|
10933
|
+
/**
|
|
10934
|
+
* Internal function for dumping signal data to markdown files.
|
|
10935
|
+
* Creates a directory structure with system prompts, user messages, and LLM output.
|
|
10936
|
+
*
|
|
10937
|
+
* @param signalId - Unique identifier for the result
|
|
10938
|
+
* @param history - Array of message models from LLM conversation
|
|
10939
|
+
* @param signal - Signal DTO with trade parameters
|
|
10940
|
+
* @param outputDir - Output directory path (default: "./dump/strategy")
|
|
10941
|
+
* @returns Promise that resolves when all files are written
|
|
10942
|
+
*/
|
|
10943
|
+
const DUMP_SIGNAL_FN = async (signalId, history, signal, outputDir = "./dump/strategy") => {
|
|
10944
|
+
// Extract system messages and system reminders from existing data
|
|
10945
|
+
const systemMessages = history.filter((m) => m.role === "system");
|
|
10946
|
+
const userMessages = history.filter((m) => m.role === "user");
|
|
10947
|
+
const subfolderPath = path.join(outputDir, String(signalId));
|
|
10948
|
+
try {
|
|
10949
|
+
await promises.access(subfolderPath);
|
|
10950
|
+
return;
|
|
10951
|
+
}
|
|
10952
|
+
catch {
|
|
10953
|
+
await promises.mkdir(subfolderPath, { recursive: true });
|
|
10954
|
+
}
|
|
10955
|
+
{
|
|
10956
|
+
let summary = "# Outline Result Summary\n";
|
|
10957
|
+
{
|
|
10958
|
+
summary += "\n";
|
|
10959
|
+
summary += `**ResultId**: ${String(signalId)}\n`;
|
|
10960
|
+
summary += "\n";
|
|
10961
|
+
}
|
|
10962
|
+
if (signal) {
|
|
10963
|
+
summary += "## Output Data\n\n";
|
|
10964
|
+
summary += "```json\n";
|
|
10965
|
+
summary += JSON.stringify(signal, null, 2);
|
|
10966
|
+
summary += "\n```\n\n";
|
|
10967
|
+
}
|
|
10968
|
+
// Add system messages to summary
|
|
10969
|
+
if (systemMessages.length > 0) {
|
|
10970
|
+
summary += "## System Messages\n\n";
|
|
10971
|
+
systemMessages.forEach((msg, idx) => {
|
|
10972
|
+
summary += `### System Message ${idx + 1}\n\n`;
|
|
10973
|
+
summary += msg.content;
|
|
10974
|
+
summary += "\n";
|
|
10975
|
+
});
|
|
10976
|
+
}
|
|
10977
|
+
const summaryFile = path.join(subfolderPath, "00_system_prompt.md");
|
|
10978
|
+
await promises.writeFile(summaryFile, summary, "utf8");
|
|
10979
|
+
}
|
|
10980
|
+
{
|
|
10981
|
+
await Promise.all(Array.from(userMessages.entries()).map(async ([idx, message]) => {
|
|
10982
|
+
const messageNum = String(idx + 1).padStart(2, "0");
|
|
10983
|
+
const contentFileName = `${messageNum}_user_message.md`;
|
|
10984
|
+
const contentFilePath = path.join(subfolderPath, contentFileName);
|
|
10985
|
+
{
|
|
10986
|
+
const messageSizeBytes = Buffer.byteLength(message.content, "utf8");
|
|
10987
|
+
const messageSizeKb = Math.floor(messageSizeBytes / 1024);
|
|
10988
|
+
if (messageSizeKb > WARN_KB) {
|
|
10989
|
+
console.warn(`User message ${idx + 1} is ${messageSizeBytes} bytes (${messageSizeKb}kb), which exceeds warning limit`);
|
|
10990
|
+
}
|
|
10991
|
+
}
|
|
10992
|
+
let content = `# User Input ${idx + 1}\n\n`;
|
|
10993
|
+
content += `**ResultId**: ${String(signalId)}\n\n`;
|
|
10994
|
+
content += message.content;
|
|
10995
|
+
content += "\n";
|
|
10996
|
+
await promises.writeFile(contentFilePath, content, "utf8");
|
|
10997
|
+
}));
|
|
10998
|
+
}
|
|
10999
|
+
{
|
|
11000
|
+
const messageNum = String(userMessages.length + 1).padStart(2, "0");
|
|
11001
|
+
const contentFileName = `${messageNum}_llm_output.md`;
|
|
11002
|
+
const contentFilePath = path.join(subfolderPath, contentFileName);
|
|
11003
|
+
let content = "# Full Outline Result\n\n";
|
|
11004
|
+
content += `**ResultId**: ${String(signalId)}\n\n`;
|
|
11005
|
+
if (signal) {
|
|
11006
|
+
content += "## Output Data\n\n";
|
|
11007
|
+
content += "```json\n";
|
|
11008
|
+
content += JSON.stringify(signal, null, 2);
|
|
11009
|
+
content += "\n```\n";
|
|
11010
|
+
}
|
|
11011
|
+
await promises.writeFile(contentFilePath, content, "utf8");
|
|
11012
|
+
}
|
|
11013
|
+
};
|
|
11014
|
+
/**
|
|
11015
|
+
* Service for generating markdown documentation from LLM outline results.
|
|
11016
|
+
* Used by AI Strategy Optimizer to save debug logs and conversation history.
|
|
11017
|
+
*
|
|
11018
|
+
* Creates directory structure:
|
|
11019
|
+
* - ./dump/strategy/{signalId}/00_system_prompt.md - System messages and output data
|
|
11020
|
+
* - ./dump/strategy/{signalId}/01_user_message.md - First user input
|
|
11021
|
+
* - ./dump/strategy/{signalId}/02_user_message.md - Second user input
|
|
11022
|
+
* - ./dump/strategy/{signalId}/XX_llm_output.md - Final LLM output
|
|
11023
|
+
*/
|
|
11024
|
+
class OutlineMarkdownService {
|
|
11025
|
+
constructor() {
|
|
11026
|
+
/** Logger service injected via DI */
|
|
11027
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
11028
|
+
/**
|
|
11029
|
+
* Dumps signal data and conversation history to markdown files.
|
|
11030
|
+
* Skips if directory already exists to avoid overwriting previous results.
|
|
11031
|
+
*
|
|
11032
|
+
* Generated files:
|
|
11033
|
+
* - 00_system_prompt.md - System messages and output summary
|
|
11034
|
+
* - XX_user_message.md - Each user message in separate file (numbered)
|
|
11035
|
+
* - XX_llm_output.md - Final LLM output with signal data
|
|
11036
|
+
*
|
|
11037
|
+
* @param signalId - Unique identifier for the result (used as directory name)
|
|
11038
|
+
* @param history - Array of message models from LLM conversation
|
|
11039
|
+
* @param signal - Signal DTO with trade parameters (priceOpen, TP, SL, etc.)
|
|
11040
|
+
* @param outputDir - Output directory path (default: "./dump/strategy")
|
|
11041
|
+
* @returns Promise that resolves when all files are written
|
|
11042
|
+
*
|
|
11043
|
+
* @example
|
|
11044
|
+
* ```typescript
|
|
11045
|
+
* await outlineService.dumpSignal(
|
|
11046
|
+
* "strategy-1",
|
|
11047
|
+
* conversationHistory,
|
|
11048
|
+
* { position: "long", priceTakeProfit: 51000, priceStopLoss: 49000, minuteEstimatedTime: 60 }
|
|
11049
|
+
* );
|
|
11050
|
+
* // Creates: ./dump/strategy/strategy-1/00_system_prompt.md
|
|
11051
|
+
* // ./dump/strategy/strategy-1/01_user_message.md
|
|
11052
|
+
* // ./dump/strategy/strategy-1/02_llm_output.md
|
|
11053
|
+
* ```
|
|
11054
|
+
*/
|
|
11055
|
+
this.dumpSignal = async (signalId, history, signal, outputDir = "./dump/strategy") => {
|
|
11056
|
+
this.loggerService.log("outlineMarkdownService dumpSignal", {
|
|
11057
|
+
signalId,
|
|
11058
|
+
history,
|
|
11059
|
+
signal,
|
|
11060
|
+
outputDir,
|
|
11061
|
+
});
|
|
11062
|
+
return await DUMP_SIGNAL_FN(signalId, history, signal, outputDir);
|
|
11063
|
+
};
|
|
11064
|
+
}
|
|
11065
|
+
}
|
|
11066
|
+
|
|
10907
11067
|
{
|
|
10908
11068
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
10909
11069
|
}
|
|
@@ -10961,6 +11121,7 @@ class PartialGlobalService {
|
|
|
10961
11121
|
provide(TYPES.walkerMarkdownService, () => new WalkerMarkdownService());
|
|
10962
11122
|
provide(TYPES.heatMarkdownService, () => new HeatMarkdownService());
|
|
10963
11123
|
provide(TYPES.partialMarkdownService, () => new PartialMarkdownService());
|
|
11124
|
+
provide(TYPES.outlineMarkdownService, () => new OutlineMarkdownService());
|
|
10964
11125
|
}
|
|
10965
11126
|
{
|
|
10966
11127
|
provide(TYPES.exchangeValidationService, () => new ExchangeValidationService());
|
|
@@ -11032,6 +11193,7 @@ const markdownServices = {
|
|
|
11032
11193
|
walkerMarkdownService: inject(TYPES.walkerMarkdownService),
|
|
11033
11194
|
heatMarkdownService: inject(TYPES.heatMarkdownService),
|
|
11034
11195
|
partialMarkdownService: inject(TYPES.partialMarkdownService),
|
|
11196
|
+
outlineMarkdownService: inject(TYPES.outlineMarkdownService),
|
|
11035
11197
|
};
|
|
11036
11198
|
const validationServices = {
|
|
11037
11199
|
exchangeValidationService: inject(TYPES.exchangeValidationService),
|
|
@@ -12698,6 +12860,83 @@ async function getMode() {
|
|
|
12698
12860
|
return bt ? "backtest" : "live";
|
|
12699
12861
|
}
|
|
12700
12862
|
|
|
12863
|
+
const DUMP_SIGNAL_METHOD_NAME = "dump.dumpSignal";
|
|
12864
|
+
/**
|
|
12865
|
+
* Dumps signal data and LLM conversation history to markdown files.
|
|
12866
|
+
* Used by AI-powered strategies to save debug logs for analysis.
|
|
12867
|
+
*
|
|
12868
|
+
* Creates a directory structure with:
|
|
12869
|
+
* - 00_system_prompt.md - System messages and output summary
|
|
12870
|
+
* - XX_user_message.md - Each user message in separate file (numbered)
|
|
12871
|
+
* - XX_llm_output.md - Final LLM output with signal data
|
|
12872
|
+
*
|
|
12873
|
+
* Skips if directory already exists to avoid overwriting previous results.
|
|
12874
|
+
*
|
|
12875
|
+
* @param signalId - Unique identifier for the result (used as directory name, e.g., UUID)
|
|
12876
|
+
* @param history - Array of message models from LLM conversation
|
|
12877
|
+
* @param signal - Signal DTO returned by LLM (position, priceOpen, TP, SL, etc.)
|
|
12878
|
+
* @param outputDir - Output directory path (default: "./dump/strategy")
|
|
12879
|
+
* @returns Promise that resolves when all files are written
|
|
12880
|
+
*
|
|
12881
|
+
* @example
|
|
12882
|
+
* ```typescript
|
|
12883
|
+
* import { dumpSignal, getCandles } from "backtest-kit";
|
|
12884
|
+
* import { v4 as uuid } from "uuid";
|
|
12885
|
+
*
|
|
12886
|
+
* addStrategy({
|
|
12887
|
+
* strategyName: "llm-strategy",
|
|
12888
|
+
* interval: "5m",
|
|
12889
|
+
* getSignal: async (symbol) => {
|
|
12890
|
+
* const messages = [];
|
|
12891
|
+
*
|
|
12892
|
+
* // Build multi-timeframe analysis conversation
|
|
12893
|
+
* const candles1h = await getCandles(symbol, "1h", 24);
|
|
12894
|
+
* messages.push(
|
|
12895
|
+
* { role: "user", content: `Analyze 1h trend:\n${formatCandles(candles1h)}` },
|
|
12896
|
+
* { role: "assistant", content: "Trend analyzed" }
|
|
12897
|
+
* );
|
|
12898
|
+
*
|
|
12899
|
+
* const candles5m = await getCandles(symbol, "5m", 24);
|
|
12900
|
+
* messages.push(
|
|
12901
|
+
* { role: "user", content: `Analyze 5m structure:\n${formatCandles(candles5m)}` },
|
|
12902
|
+
* { role: "assistant", content: "Structure analyzed" }
|
|
12903
|
+
* );
|
|
12904
|
+
*
|
|
12905
|
+
* // Request signal
|
|
12906
|
+
* messages.push({
|
|
12907
|
+
* role: "user",
|
|
12908
|
+
* content: "Generate trading signal. Use position: 'wait' if uncertain."
|
|
12909
|
+
* });
|
|
12910
|
+
*
|
|
12911
|
+
* const resultId = uuid();
|
|
12912
|
+
* const signal = await llmRequest(messages);
|
|
12913
|
+
*
|
|
12914
|
+
* // Save conversation and result for debugging
|
|
12915
|
+
* await dumpSignal(resultId, messages, signal);
|
|
12916
|
+
*
|
|
12917
|
+
* return signal;
|
|
12918
|
+
* }
|
|
12919
|
+
* });
|
|
12920
|
+
*
|
|
12921
|
+
* // Creates: ./dump/strategy/{uuid}/00_system_prompt.md
|
|
12922
|
+
* // ./dump/strategy/{uuid}/01_user_message.md (1h analysis)
|
|
12923
|
+
* // ./dump/strategy/{uuid}/02_assistant_message.md
|
|
12924
|
+
* // ./dump/strategy/{uuid}/03_user_message.md (5m analysis)
|
|
12925
|
+
* // ./dump/strategy/{uuid}/04_assistant_message.md
|
|
12926
|
+
* // ./dump/strategy/{uuid}/05_user_message.md (signal request)
|
|
12927
|
+
* // ./dump/strategy/{uuid}/06_llm_output.md (final signal)
|
|
12928
|
+
* ```
|
|
12929
|
+
*/
|
|
12930
|
+
async function dumpSignal(signalId, history, signal, outputDir = "./dump/strategy") {
|
|
12931
|
+
backtest$1.loggerService.info(DUMP_SIGNAL_METHOD_NAME, {
|
|
12932
|
+
signalId,
|
|
12933
|
+
history,
|
|
12934
|
+
signal,
|
|
12935
|
+
outputDir,
|
|
12936
|
+
});
|
|
12937
|
+
return await backtest$1.outlineMarkdownService.dumpSignal(signalId, history, signal, outputDir);
|
|
12938
|
+
}
|
|
12939
|
+
|
|
12701
12940
|
const BACKTEST_METHOD_NAME_RUN = "BacktestUtils.run";
|
|
12702
12941
|
const BACKTEST_METHOD_NAME_BACKGROUND = "BacktestUtils.background";
|
|
12703
12942
|
const BACKTEST_METHOD_NAME_GET_REPORT = "BacktestUtils.getReport";
|
|
@@ -13918,26 +14157,26 @@ const PARTIAL_METHOD_NAME_DUMP = "PartialUtils.dump";
|
|
|
13918
14157
|
*
|
|
13919
14158
|
* Data source:
|
|
13920
14159
|
* - PartialMarkdownService listens to partialProfitSubject/partialLossSubject
|
|
13921
|
-
* - Accumulates events in ReportStorage (max 250 events per symbol)
|
|
13922
|
-
* - Events include: timestamp, action, symbol, signalId, position, level, price, mode
|
|
14160
|
+
* - Accumulates events in ReportStorage (max 250 events per symbol-strategy pair)
|
|
14161
|
+
* - Events include: timestamp, action, symbol, strategyName, signalId, position, level, price, mode
|
|
13923
14162
|
*
|
|
13924
14163
|
* @example
|
|
13925
14164
|
* ```typescript
|
|
13926
14165
|
* import { Partial } from "./classes/Partial";
|
|
13927
14166
|
*
|
|
13928
|
-
* // Get statistical data for BTCUSDT
|
|
13929
|
-
* const stats = await Partial.getData("BTCUSDT");
|
|
14167
|
+
* // Get statistical data for BTCUSDT:my-strategy
|
|
14168
|
+
* const stats = await Partial.getData("BTCUSDT", "my-strategy");
|
|
13930
14169
|
* console.log(`Total events: ${stats.totalEvents}`);
|
|
13931
14170
|
* console.log(`Profit events: ${stats.totalProfit}`);
|
|
13932
14171
|
* console.log(`Loss events: ${stats.totalLoss}`);
|
|
13933
14172
|
*
|
|
13934
14173
|
* // Generate markdown report
|
|
13935
|
-
* const markdown = await Partial.getReport("BTCUSDT");
|
|
14174
|
+
* const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
|
|
13936
14175
|
* console.log(markdown); // Formatted table with all events
|
|
13937
14176
|
*
|
|
13938
14177
|
* // Export report to file
|
|
13939
|
-
* await Partial.dump("BTCUSDT"); // Saves to ./dump/partial/
|
|
13940
|
-
* await Partial.dump("BTCUSDT", "./custom/path"); // Custom directory
|
|
14178
|
+
* await Partial.dump("BTCUSDT", "my-strategy"); // Saves to ./dump/partial/BTCUSDT_my-strategy.md
|
|
14179
|
+
* await Partial.dump("BTCUSDT", "my-strategy", "./custom/path"); // Custom directory
|
|
13941
14180
|
* ```
|
|
13942
14181
|
*/
|
|
13943
14182
|
class PartialUtils {
|
|
@@ -13949,11 +14188,12 @@ class PartialUtils {
|
|
|
13949
14188
|
* Returns aggregated metrics calculated from all profit and loss events.
|
|
13950
14189
|
*
|
|
13951
14190
|
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
14191
|
+
* @param strategyName - Strategy name (e.g., "my-strategy")
|
|
13952
14192
|
* @returns Promise resolving to PartialStatistics object with counts and event list
|
|
13953
14193
|
*
|
|
13954
14194
|
* @example
|
|
13955
14195
|
* ```typescript
|
|
13956
|
-
* const stats = await Partial.getData("BTCUSDT");
|
|
14196
|
+
* const stats = await Partial.getData("BTCUSDT", "my-strategy");
|
|
13957
14197
|
*
|
|
13958
14198
|
* console.log(`Total events: ${stats.totalEvents}`);
|
|
13959
14199
|
* console.log(`Profit events: ${stats.totalProfit} (${(stats.totalProfit / stats.totalEvents * 100).toFixed(1)}%)`);
|
|
@@ -13965,16 +14205,17 @@ class PartialUtils {
|
|
|
13965
14205
|
* }
|
|
13966
14206
|
* ```
|
|
13967
14207
|
*/
|
|
13968
|
-
this.getData = async (symbol) => {
|
|
13969
|
-
backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol });
|
|
13970
|
-
return await backtest$1.partialMarkdownService.getData(symbol);
|
|
14208
|
+
this.getData = async (symbol, strategyName) => {
|
|
14209
|
+
backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_DATA, { symbol, strategyName });
|
|
14210
|
+
return await backtest$1.partialMarkdownService.getData(symbol, strategyName);
|
|
13971
14211
|
};
|
|
13972
14212
|
/**
|
|
13973
|
-
* Generates markdown report with all partial profit/loss events for a symbol.
|
|
14213
|
+
* Generates markdown report with all partial profit/loss events for a symbol-strategy pair.
|
|
13974
14214
|
*
|
|
13975
14215
|
* Creates formatted table containing:
|
|
13976
14216
|
* - Action (PROFIT/LOSS)
|
|
13977
14217
|
* - Symbol
|
|
14218
|
+
* - Strategy
|
|
13978
14219
|
* - Signal ID
|
|
13979
14220
|
* - Position (LONG/SHORT)
|
|
13980
14221
|
* - Level % (+10%, -20%, etc)
|
|
@@ -13985,35 +14226,36 @@ class PartialUtils {
|
|
|
13985
14226
|
* Also includes summary statistics at the end.
|
|
13986
14227
|
*
|
|
13987
14228
|
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
14229
|
+
* @param strategyName - Strategy name (e.g., "my-strategy")
|
|
13988
14230
|
* @returns Promise resolving to markdown formatted report string
|
|
13989
14231
|
*
|
|
13990
14232
|
* @example
|
|
13991
14233
|
* ```typescript
|
|
13992
|
-
* const markdown = await Partial.getReport("BTCUSDT");
|
|
14234
|
+
* const markdown = await Partial.getReport("BTCUSDT", "my-strategy");
|
|
13993
14235
|
* console.log(markdown);
|
|
13994
14236
|
*
|
|
13995
14237
|
* // Output:
|
|
13996
|
-
* // # Partial Profit/Loss Report: BTCUSDT
|
|
14238
|
+
* // # Partial Profit/Loss Report: BTCUSDT:my-strategy
|
|
13997
14239
|
* //
|
|
13998
|
-
* // | Action | Symbol | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
|
|
13999
|
-
* // | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
14000
|
-
* // | PROFIT | BTCUSDT | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
|
|
14001
|
-
* // | LOSS | BTCUSDT | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
|
|
14240
|
+
* // | Action | Symbol | Strategy | Signal ID | Position | Level % | Current Price | Timestamp | Mode |
|
|
14241
|
+
* // | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
14242
|
+
* // | PROFIT | BTCUSDT | my-strategy | abc123 | LONG | +10% | 51500.00000000 USD | 2024-01-15T10:30:00.000Z | Backtest |
|
|
14243
|
+
* // | LOSS | BTCUSDT | my-strategy | abc123 | LONG | -10% | 49000.00000000 USD | 2024-01-15T11:00:00.000Z | Backtest |
|
|
14002
14244
|
* //
|
|
14003
14245
|
* // **Total events:** 2
|
|
14004
14246
|
* // **Profit events:** 1
|
|
14005
14247
|
* // **Loss events:** 1
|
|
14006
14248
|
* ```
|
|
14007
14249
|
*/
|
|
14008
|
-
this.getReport = async (symbol) => {
|
|
14009
|
-
backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol });
|
|
14010
|
-
return await backtest$1.partialMarkdownService.getReport(symbol);
|
|
14250
|
+
this.getReport = async (symbol, strategyName) => {
|
|
14251
|
+
backtest$1.loggerService.info(PARTIAL_METHOD_NAME_GET_REPORT, { symbol, strategyName });
|
|
14252
|
+
return await backtest$1.partialMarkdownService.getReport(symbol, strategyName);
|
|
14011
14253
|
};
|
|
14012
14254
|
/**
|
|
14013
14255
|
* Generates and saves markdown report to file.
|
|
14014
14256
|
*
|
|
14015
14257
|
* Creates directory if it doesn't exist.
|
|
14016
|
-
* Filename format: {symbol}.md (e.g., "
|
|
14258
|
+
* Filename format: {symbol}_{strategyName}.md (e.g., "BTCUSDT_my-strategy.md")
|
|
14017
14259
|
*
|
|
14018
14260
|
* Delegates to PartialMarkdownService.dump() which:
|
|
14019
14261
|
* 1. Generates markdown report via getReport()
|
|
@@ -14022,26 +14264,27 @@ class PartialUtils {
|
|
|
14022
14264
|
* 4. Logs success/failure to console
|
|
14023
14265
|
*
|
|
14024
14266
|
* @param symbol - Trading pair symbol (e.g., "BTCUSDT")
|
|
14267
|
+
* @param strategyName - Strategy name (e.g., "my-strategy")
|
|
14025
14268
|
* @param path - Output directory path (default: "./dump/partial")
|
|
14026
14269
|
* @returns Promise that resolves when file is written
|
|
14027
14270
|
*
|
|
14028
14271
|
* @example
|
|
14029
14272
|
* ```typescript
|
|
14030
|
-
* // Save to default path: ./dump/partial/
|
|
14031
|
-
* await Partial.dump("BTCUSDT");
|
|
14273
|
+
* // Save to default path: ./dump/partial/BTCUSDT_my-strategy.md
|
|
14274
|
+
* await Partial.dump("BTCUSDT", "my-strategy");
|
|
14032
14275
|
*
|
|
14033
|
-
* // Save to custom path: ./reports/partial/
|
|
14034
|
-
* await Partial.dump("BTCUSDT", "./reports/partial");
|
|
14276
|
+
* // Save to custom path: ./reports/partial/BTCUSDT_my-strategy.md
|
|
14277
|
+
* await Partial.dump("BTCUSDT", "my-strategy", "./reports/partial");
|
|
14035
14278
|
*
|
|
14036
14279
|
* // After multiple symbols backtested, export all reports
|
|
14037
14280
|
* for (const symbol of ["BTCUSDT", "ETHUSDT", "BNBUSDT"]) {
|
|
14038
|
-
* await Partial.dump(symbol, "./backtest-results");
|
|
14281
|
+
* await Partial.dump(symbol, "my-strategy", "./backtest-results");
|
|
14039
14282
|
* }
|
|
14040
14283
|
* ```
|
|
14041
14284
|
*/
|
|
14042
|
-
this.dump = async (symbol, path) => {
|
|
14043
|
-
backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, path });
|
|
14044
|
-
await backtest$1.partialMarkdownService.dump(symbol, path);
|
|
14285
|
+
this.dump = async (symbol, strategyName, path) => {
|
|
14286
|
+
backtest$1.loggerService.info(PARTIAL_METHOD_NAME_DUMP, { symbol, strategyName, path });
|
|
14287
|
+
await backtest$1.partialMarkdownService.dump(symbol, strategyName, path);
|
|
14045
14288
|
};
|
|
14046
14289
|
}
|
|
14047
14290
|
}
|
|
@@ -14054,9 +14297,9 @@ class PartialUtils {
|
|
|
14054
14297
|
* import { Partial } from "backtest-kit";
|
|
14055
14298
|
*
|
|
14056
14299
|
* // Usage same as PartialUtils methods
|
|
14057
|
-
* const stats = await Partial.getData("BTCUSDT");
|
|
14058
|
-
* const report = await Partial.getReport("BTCUSDT");
|
|
14059
|
-
* await Partial.dump("BTCUSDT");
|
|
14300
|
+
* const stats = await Partial.getData("BTCUSDT", "my-strategy");
|
|
14301
|
+
* const report = await Partial.getReport("BTCUSDT", "my-strategy");
|
|
14302
|
+
* await Partial.dump("BTCUSDT", "my-strategy");
|
|
14060
14303
|
* ```
|
|
14061
14304
|
*/
|
|
14062
14305
|
const Partial = new PartialUtils();
|
|
@@ -14142,4 +14385,4 @@ class ConstantUtils {
|
|
|
14142
14385
|
*/
|
|
14143
14386
|
const Constant = new ConstantUtils();
|
|
14144
14387
|
|
|
14145
|
-
export { Backtest, Constant, ExecutionContextService, Heat, Live, MethodContextService, Optimizer, Partial, Performance, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Schedule, Walker, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setConfig, setLogger };
|
|
14388
|
+
export { Backtest, Constant, ExecutionContextService, Heat, Live, MethodContextService, Optimizer, Partial, Performance, PersistBase, PersistPartialAdapter, PersistRiskAdapter, PersistScheduleAdapter, PersistSignalAdapter, PositionSize, Schedule, Walker, addExchange, addFrame, addOptimizer, addRisk, addSizing, addStrategy, addWalker, dumpSignal, emitters, formatPrice, formatQuantity, getAveragePrice, getCandles, getDate, getMode, backtest as lib, listExchanges, listFrames, listOptimizers, listRisks, listSizings, listStrategies, listWalkers, listenBacktestProgress, listenDoneBacktest, listenDoneBacktestOnce, listenDoneLive, listenDoneLiveOnce, listenDoneWalker, listenDoneWalkerOnce, listenError, listenExit, listenOptimizerProgress, listenPartialLoss, listenPartialLossOnce, listenPartialProfit, listenPartialProfitOnce, listenPerformance, listenSignal, listenSignalBacktest, listenSignalBacktestOnce, listenSignalLive, listenSignalLiveOnce, listenSignalOnce, listenValidation, listenWalker, listenWalkerComplete, listenWalkerOnce, listenWalkerProgress, setConfig, setLogger };
|