Walker schemas define multi-strategy comparison configurations for A/B testing and optimization workflows. A walker executes backtests for multiple strategies on the same historical data and compares their performance using a specified metric.
For information about individual strategy configuration, see Strategy Schemas. For information about frame (timeframe) configuration used by walkers, see Frame Schemas. For information about executing walkers, see Walker API.
Walker schemas are defined by the IWalkerSchema interface and registered via the addWalker() function.
Schema Definition
| Property | Type | Description |
|---|---|---|
walkerName |
WalkerName (string) |
Unique identifier for the walker configuration |
exchangeName |
ExchangeName (string) |
Exchange schema to use for all strategy backtests |
frameName |
FrameName (string) |
Frame schema defining the backtest timeframe |
strategies |
StrategyName[] |
Array of strategy names to compare |
| Property | Type | Default | Description |
|---|---|---|---|
metric |
WalkerMetric |
"sharpeRatio" |
Optimization metric for comparison |
note |
string |
undefined |
Developer documentation note |
callbacks |
Partial<IWalkerCallbacks> |
undefined |
Lifecycle event callbacks |
The WalkerMetric type defines which statistical measure is used to rank and select the best strategy. Higher values are always better (metrics are maximized).
type WalkerMetric =
| "sharpeRatio" // Risk-adjusted return (avgPnl / stdDev)
| "annualizedSharpeRatio" // Annualized Sharpe (sharpeRatio × √365)
| "winRate" // Percentage of winning trades (0-100)
| "totalPnl" // Cumulative PNL across all signals
| "certaintyRatio" // avgWin / |avgLoss|
| "avgPnl" // Average PNL per signal
| "expectedYearlyReturns" // Projected yearly returns
Risk-Adjusted Metrics
sharpeRatio / annualizedSharpeRatio: Best for strategies with consistent returns and controlled drawdownscertaintyRatio: Best for strategies with asymmetric risk/reward profilesReturn Metrics
totalPnl: Best for maximizing absolute profit without regard to riskavgPnl: Best for strategies with varying trade frequenciesexpectedYearlyReturns: Best for long-term performance projectionReliability Metrics
winRate: Best for strategies requiring high win consistencyWalker schemas are registered through the addWalker() function, which performs validation and stores the configuration.
Registration Flow
addWalker({
walkerName: "llm-prompt-optimizer",
note: "Compare GPT-4 prompts for trading signal generation",
exchangeName: "binance",
frameName: "1month-backtest",
strategies: [
"gpt4-prompt-v1",
"gpt4-prompt-v2",
"gpt4-prompt-v3"
],
metric: "sharpeRatio",
callbacks: {
onStrategyComplete: (strategyName, symbol, stats, metricValue) => {
console.log(`${strategyName}: Sharpe=${metricValue}`);
},
onComplete: (results) => {
console.log(`Best: ${results.bestStrategy} (${results.bestMetric})`);
}
}
});
Walker schemas support lifecycle callbacks for monitoring comparison progress.
onStrategyComplete
Called after each strategy backtest completes with its results.
onStrategyComplete: (
strategyName: StrategyName,
symbol: string,
stats: BacktestStatistics,
metricValue: number | null
) => void
Parameters:
strategyName: Name of the completed strategysymbol: Trading pair symbolstats: Full backtest statistics for the strategymetricValue: Computed value of the walker's metric (null if calculation unsafe)onComplete
Called after all strategies complete with final comparison results.
onComplete: (
results: IWalkerResults
) => void
Parameters:
results: Complete walker results including best strategy selectionWalker schemas orchestrate multiple components to perform strategy comparison.
Component Dependencies
When Walker.run() is called, validation occurs for all referenced components:
The Walker.run() method executes backtests sequentially for all strategies and emits progress events.
Execution Architecture
Walker execution clears accumulated data for all strategies before starting:
backtestMarkdownService.clear() and scheduleMarkdownService.clear() for each strategystrategyGlobalService.clear() to reset internal stateriskGlobalService.clear() if strategies use risk profilesThis ensures clean state for each walker run and prevents data contamination between executions.
Walker results are accumulated in WalkerMarkdownService and exposed through Walker.getData(), Walker.getReport(), and Walker.dump().
Results Structure
interface IWalkerResults {
walkerName: WalkerName;
symbol: string;
metric: WalkerMetric;
bestStrategy: StrategyName;
bestMetric: number;
totalStrategies: number;
results: IWalkerStrategyResult[];
}
interface IWalkerStrategyResult {
strategyName: StrategyName;
metricValue: number | null;
stats: BacktestStatistics;
}
// Execute walker comparison
for await (const progress of Walker.run("BTCUSDT", {
walkerName: "prompt-optimizer"
})) {
console.log(`${progress.strategiesTested}/${progress.totalStrategies}`);
console.log(`Best: ${progress.bestStrategy} (${progress.bestMetric})`);
}
// Retrieve results
const results = await Walker.getData("BTCUSDT", "prompt-optimizer");
console.log(`Winner: ${results.bestStrategy}`);
console.log(`Sharpe Ratio: ${results.bestMetric}`);
// Generate markdown report
const markdown = await Walker.getReport("BTCUSDT", "prompt-optimizer");
console.log(markdown);
// Save report to disk
await Walker.dump("BTCUSDT", "prompt-optimizer");
// Writes to: ./logs/walker/prompt-optimizer.md
Walker execution emits progress and completion events through the global event system.
Event Flow
Progress events (WalkerContract) are emitted after each strategy completes:
interface WalkerContract {
walkerName: WalkerName;
strategyName: StrategyName; // Current strategy
symbol: string;
metric: WalkerMetric;
metricValue: number | null; // Current strategy's metric
bestStrategy: StrategyName; // Best so far
bestMetric: number; // Best metric so far
strategiesTested: number;
totalStrategies: number;
}
Listen to progress:
listenWalker((event) => {
console.log(`Progress: ${event.strategiesTested}/${event.totalStrategies}`);
console.log(`Current: ${event.strategyName} = ${event.metricValue}`);
console.log(`Leader: ${event.bestStrategy} = ${event.bestMetric}`);
});
Completion events (IWalkerResults) are emitted when all strategies finish:
listenWalkerComplete((results) => {
console.log(`Winner: ${results.bestStrategy}`);
console.log(`Metric: ${results.bestMetric}`);
console.log(`Tested: ${results.totalStrategies} strategies`);
// Access all results
results.results.forEach(r => {
console.log(`${r.strategyName}: ${r.metricValue}`);
});
});
Walker schemas can be retrieved and listed for inspection or dynamic UI generation.
const walkerSchema = backtest.walkerSchemaService.get("prompt-optimizer");
console.log(walkerSchema.strategies); // ["v1", "v2", "v3"]
console.log(walkerSchema.metric); // "sharpeRatio"
const allWalkers = await listWalkers();
allWalkers.forEach(walker => {
console.log(`${walker.walkerName}: ${walker.strategies.length} strategies`);
});
Walker schemas are ideal for comparing different LLM prompts for signal generation:
// Register strategy variants with different prompts
addStrategy({
strategyName: "gpt4-aggressive",
interval: "5m",
getSignal: async (symbol) => {
const prompt = "Generate aggressive trading signals...";
return await callGPT4(symbol, prompt);
}
});
addStrategy({
strategyName: "gpt4-conservative",
interval: "5m",
getSignal: async (symbol) => {
const prompt = "Generate conservative trading signals...";
return await callGPT4(symbol, prompt);
}
});
// Compare with walker
addWalker({
walkerName: "prompt-optimizer",
exchangeName: "binance",
frameName: "1month-backtest",
strategies: ["gpt4-aggressive", "gpt4-conservative"],
metric: "sharpeRatio"
});
Walker can perform grid search over strategy parameters:
// Register strategies with different parameter combinations
const periods = [10, 20, 50];
const thresholds = [0.01, 0.02, 0.03];
periods.forEach(period => {
thresholds.forEach(threshold => {
addStrategy({
strategyName: `sma-${period}-${threshold}`,
interval: "5m",
getSignal: async (symbol) => {
return await smaStrategy(symbol, period, threshold);
}
});
});
});
// Walker tests all combinations
addWalker({
walkerName: "sma-grid-search",
exchangeName: "binance",
frameName: "1year-backtest",
strategies: [
"sma-10-0.01", "sma-10-0.02", "sma-10-0.03",
"sma-20-0.01", "sma-20-0.02", "sma-20-0.03",
"sma-50-0.01", "sma-50-0.02", "sma-50-0.03"
],
metric: "annualizedSharpeRatio"
});
Walker enables safe A/B testing of strategy modifications:
addWalker({
walkerName: "production-ab-test",
exchangeName: "binance",
frameName: "3month-backtest",
strategies: [
"production-v1", // Current production
"production-v2-beta" // New candidate
],
metric: "sharpeRatio",
callbacks: {
onComplete: (results) => {
if (results.bestStrategy === "production-v2-beta") {
console.log("✓ v2-beta outperforms production");
console.log(`Improvement: ${results.bestMetric}`);
} else {
console.log("✗ Keep current production version");
}
}
}
});