This page documents the reporting and data retrieval functionality for Walker mode, which provides multi-strategy comparison results and performance rankings. Walker reports aggregate backtest statistics from multiple strategies and present them in a unified format for analysis.
For information about Walker execution flow and strategy iteration, see Walker Execution Flow. For details on how strategies are compared and ranked, see Strategy Comparison.
Walker reports provide structured access to multi-strategy comparison results through three primary APIs:
Walker.getData() - Returns raw comparison data as structured objectsWalker.getReport() - Generates formatted markdown reports with tablesWalker.dump() - Persists reports to diskThese APIs are thin wrappers around WalkerMarkdownService, which accumulates strategy results during walker execution and formats them for consumption.
The following diagram shows how walker reports are generated from strategy execution through to final output:
The Walker.getData() method returns raw comparison data as a structured object without formatting. This is useful for programmatic access to walker results.
Walker.getData(
symbol: string,
walkerName: WalkerName
): Promise<IWalkerResults>
| Parameter | Type | Description |
|---|---|---|
symbol |
string |
Trading pair symbol (e.g., "BTCUSDT") |
walkerName |
WalkerName |
Walker schema name registered via addWalker() |
The method returns an IWalkerResults object containing:
bestStrategy - Name of the strategy with the highest metric valuebestMetric - The highest metric value achievedstrategies - Array of strategy comparison results, each containing:
strategyName - Strategy identifierstats - Full BacktestStatistics object (see Backtest Reports)metric - The specific metric value used for comparisonThe method performs the following steps:
loggerService.info()walkerSchemaService.get(walkerName)metric field from schema (defaults to "sharpeRatio" if not specified)walkerMarkdownService.getData() with symbol, walker name, metric, and contextFrom the README, the typical usage pattern:
// Get raw comparison data
const results = await Walker.getData("BTCUSDT", "btc-walker");
console.log(results);
// Returns:
// {
// bestStrategy: "strategy-b",
// bestMetric: 1.85,
// strategies: [
// { strategyName: "strategy-a", stats: { sharpeRatio: 1.23, ... }, metric: 1.23 },
// { strategyName: "strategy-b", stats: { sharpeRatio: 1.85, ... }, metric: 1.85 },
// { strategyName: "strategy-c", stats: { sharpeRatio: 0.98, ... }, metric: 0.98 }
// ]
// }
The Walker.getReport() method generates a formatted markdown report with comparison tables and performance rankings.
Walker.getReport(
symbol: string,
walkerName: WalkerName
): Promise<string>
The generated markdown report includes:
The method follows this delegation chain:
Walker.getReport() validates inputs and logs invocationexchangeName, frameName, and metricwalkerMarkdownService.getReport() with full contextThe Walker.dump() method saves the generated markdown report to disk with automatic directory creation.
Walker.dump(
symbol: string,
walkerName: WalkerName,
path?: string
): Promise<void>
| Parameter | Type | Default | Description |
|---|---|---|---|
symbol |
string |
Required | Trading pair symbol |
walkerName |
WalkerName |
Required | Walker schema name |
path |
string |
"./logs/walker" |
Directory path for report output |
Reports are saved with the following pattern:
{path}/{walkerName}.md
For example:
./logs/walker/btc-walker.md./custom/path/btc-walker.mdThe method performs atomic file writes to prevent corruption:
mkdir(dir, { recursive: true })getReport()writeFile() in UTF-8 encoding// Save to default path: ./logs/walker/my-walker.md
await Walker.dump("BTCUSDT", "my-walker");
// Save to custom path: ./custom/path/my-walker.md
await Walker.dump("BTCUSDT", "my-walker", "./custom/path");
Walker reports support multiple metrics for strategy ranking. The metric is specified in the walker schema via the metric field.
| Metric Name | Type | Description | Calculation | Direction |
|---|---|---|---|---|
sharpeRatio |
number |
Risk-adjusted return | avgPnl / stdDev |
Higher is better |
annualizedSharpeRatio |
number |
Annualized Sharpe | sharpeRatio × √365 |
Higher is better |
winRate |
number |
Win percentage | (winCount / totalSignals) × 100 |
Higher is better |
avgPnl |
number |
Average PNL percentage | sum(pnl) / totalSignals |
Higher is better |
totalPnl |
number |
Cumulative PNL percentage | sum(pnl) |
Higher is better |
certaintyRatio |
number |
Win/loss ratio | `avgWin / | avgLoss |
expectedYearlyReturns |
number |
Projected annual returns | avgPnl × (365 / avgDurationDays) |
Higher is better |
If no metric is specified in the walker schema, "sharpeRatio" is used as the default:
const metric = walkerSchema.metric || "sharpeRatio";
Walker schema with custom metric:
addWalker({
walkerName: "btc-walker",
exchangeName: "binance",
frameName: "1d-backtest",
strategies: ["strategy-a", "strategy-b", "strategy-c"],
metric: "sharpeRatio", // Metric for strategy comparison
callbacks: {
onComplete: (results) => {
console.log("Best strategy:", results.bestStrategy);
console.log("Best metric:", results.bestMetric);
},
},
});
Walker reports use markdown tables to present comparison data in a structured format.
The comparison table ranks strategies by the selected metric and displays key performance indicators:
From the README documentation:
# Walker Report: btc-walker (BTCUSDT)
**Best Strategy:** strategy-b
**Best Metric (sharpeRatio):** 1.85
| Rank | Strategy | Sharpe Ratio | Win Rate | Avg PNL | Total PNL | Trades |
|------|----------|--------------|----------|---------|-----------|--------|
| 1 | strategy-b | 1.85 | 68.5% | +1.45% | +12.30% | 38 |
| 2 | strategy-a | 1.23 | 72.3% | +0.34% | +15.50% | 45 |
| 3 | strategy-c | 0.98 | 65.2% | +1.20% | +10.20% | 25 |
**Total Strategies:** 3
**Exchange:** binance
**Frame:** 1d-backtest
Walker reports integrate with the event system to provide real-time updates and completion notifications.
| Event | Emitter | Purpose | Payload |
|---|---|---|---|
| Walker Progress | walkerEmitter |
Emitted after each strategy completes | WalkerContract with progress |
| Walker Complete | walkerCompleteSubject |
Emitted when all strategies finish | IWalkerResults with rankings |
| Background Done | doneWalkerSubject |
Emitted when Walker.background() finishes |
DoneContract with context |
import { listenWalkerComplete, Walker } from "backtest-kit";
// Listen to walker completion
listenWalkerComplete((results) => {
console.log("Walker completed:", results.bestStrategy);
Walker.dump("BTCUSDT", results.walkerName); // Save report
});
// Run walker in background
Walker.background("BTCUSDT", {
walkerName: "btc-walker"
});
The following diagram illustrates the complete lifecycle of walker report data from execution through persistence:
| Method | Return Type | Description | Default Path |
|---|---|---|---|
Walker.getData(symbol, walkerName) |
Promise<IWalkerResults> |
Returns structured comparison data | N/A |
Walker.getReport(symbol, walkerName) |
Promise<string> |
Generates markdown report string | N/A |
Walker.dump(symbol, walkerName, path?) |
Promise<void> |
Saves report to disk | ./logs/walker |
Walker.run(symbol, context) |
AsyncGenerator |
Runs walker with progress updates | N/A |
Walker.background(symbol, context) |
Function |
Runs walker in background, returns cancel function | N/A |
All walker report methods follow this delegation pattern:
Walker.method()Walker logs invocationWalker retrieves schemaWalker delegates to WalkerMarkdownServiceWalkerMarkdownService queries BacktestMarkdownService for each strategyWalker markdown service supports clearing accumulated data, similar to backtest and live services:
// Clear data for specific walker
backtest.walkerMarkdownService.clear("my-walker");
// This is done automatically in Walker.run() before execution
The Walker.run() method automatically clears walker markdown data before execution to ensure fresh results:
backtest.walkerMarkdownService.clear(context.walkerName);