Configuration Files
Configuration files enable repeatable, complex backtesting setups in a JSON format.
Why use configuration files?
- Store complex multi-symbol setups for repeatable execution
- Run multiple strategies in a single batch
- Define per-symbol overrides without long command lines
- Generate portfolio reports automatically
- Share configurations with other users
Basic structure
{
"global": {
"strategy": "macrossover",
"bar-interval": "daily",
"date-from": "2015-01-01",
"date-to": "2024-12-31",
"output-mode": "summary"
},
"runs": [
{ "symbol": "@ES" },
{ "symbol": "@NQ" },
{ "symbol": "@CL" }
]
}The global section defines defaults; the runs array defines individual backtests that can override any global setting.
Running a configuration
algo run --config myconfig.json
# Validate without running
algo run --config myconfig.json --verifyConfig files without a path are loaded from ~/.algolang/configs/.
Comments
Although standard JSON does not support comments, Algolang config files allow line comments starting with // (outside of string literals). These are stripped before JSON parsing:
{
"global": {
// Mean reversion strategy on daily bars
"strategy": "meanrevert",
"bar-interval": "daily"
}
}Per-run overrides
Each run can override any global setting:
{
"global": {
"strategy": "kbt",
"bar-interval": "daily"
},
"runs": [
{ "symbol": "@ES" },
{
"symbol": "@NQ",
"bar-interval": "60m",
"session-hours": "9:30am-4:00pm"
}
]
}Symbol templates
The symbols section defines symbol lists for template expansion:
{
"global": { "strategy": "kbt" },
"symbols": {
"symbol": ["@ES", "@NQ", "@CL", "@GC"]
},
"runs": [
{
"series": [
{ "symbol": "{symbol}", "bar-interval": "daily" }
]
}
]
}This creates one run per symbol.
Loading symbols from files
Symbols can be loaded from external files in two ways:
Portfolio file reference (recommended): Use the < prefix to reference a portfolio file from ~/.algolang/portfolios/:
{
"symbols": {
"symbol": "<metals"
}
}This loads all symbols from the metals portfolio file (see Portfolio files in Chapter 4 for the full list of available portfolios and their aliases). Portfolio names are resolved case-insensitively, and aliases are supported (e.g., <metals and <metal both work).
Relative file path: You can also specify a path relative to ~/.algolang/:
{
"symbols": {
"symbol": "portfolios/bp24.txt"
}
}Both approaches support the same file format: one symbol per line, space-separated, or comma-separated. Lines starting with # are comments and empty lines are ignored.
Example portfolio file (~/.algolang/portfolios/metals):
@GC
@HG
@PA
@PL
@SIThe < prefix syntax works anywhere a symbol is accepted in config files, including in series arrays and in the global section:
{
"global": {
"symbol": "<div24",
"bar-interval": "daily"
}
}{
"series": [
{ "symbol": "<metals", "bar-interval": "60m" }
]
}Multiple symbol sources
For strategies that need multiple symbols per run (e.g., pairs trading), define multiple symbol sources using symbol1, symbol2, etc.:
{
"global": {
"strategy": "pairs"
},
"symbols": {
"symbol1": ["@ES", "@NQ", "@YM"],
"symbol2": ["@CL", "@GC", "@SI"]
},
"runs": [
{
"series": [
{ "symbol": "{symbol1}", "bar-interval": "daily" },
{ "symbol": "{symbol2}", "bar-interval": "daily" }
]
}
]
}This creates three runs: @ES paired with @CL, @NQ paired with @GC, and @YM paired with @SI.
The available template variables are:
| Variable | Alias | Source |
|---|---|---|
{symbol} | {symbol1} | Value of symbol or symbol1 key |
{symbol2} | Value of symbol2 key | |
{symbol3} | Value of symbol3 key |
Important: When using multiple sources, all sources must have the same number of symbols (paired iteration, not cartesian product). You can mix file paths and inline lists:
{
"symbols": {
"symbol1": "portfolios/primary.txt",
"symbol2": ["@SPY", "@QQQ", "@IWM"]
}
}Multi-symbol series
For strategies that need multiple data series per run:
{
"runs": [
{
"strategy": "pairs",
"series": [
{ "symbol": "@ES", "bar-interval": "60m" },
{ "symbol": "@NQ", "bar-interval": "60m" }
]
}
]
}Per-series settings
Each series entry can override the following settings independently. Settings not specified inherit from the run level, then global level, then system defaults:
bar-building-modebar-intervalsession-dayssession-hourstimezone
{
"series": [
{
"symbol": "@ES",
"session-hours": "9:30am-4:00pm",
"timezone": "America/New_York"
},
{
"symbol": "@NQ",
"session-hours": "9:30am-4:00pm",
"bar-interval": "30m"
}
],
"strategy": "pairs",
"bar-interval": "60m"
}In this example, both series default to 60m bars (from the run level), but @NQ overrides to use 30m bars. Each series has its session hours specified individually.
Output redirection (tty)
The tty setting redirects console output to a file instead of the terminal. This is useful for logging results or running batch jobs. The setting supports the same template variables as export.
By default, the file is overwritten each time:
{
"tty": "logs/{strat}-{sym}.log"
}Prefix the path with >> to append to an existing file:
{
"tty": ">>logs/{yyyy}{mm}{dd}.log"
}Each run can have its own output file, and per-run tty settings override the global value.
Template variables
The export, portfolio, and tty paths support template variables:
| Variable | Description |
|---|---|
{strat} | Strategy name |
{sym} | Symbol name |
{bar} | Bar interval |
{from}, {to} | Date range |
{yyyy}, {mm}, {dd} | Date components |
{hh}, {mi}, {ss} | Time components |
{datetime} | Full timestamp |
{date} | Full date (YYYY-MM-DD) |
{batchfile} | Config filename without extension |
{configfile} | Alias for {batchfile} |
{inputs} | Input values (e.g., Period=20,Mult=1.5) |
{$Name} | Value of strategy input Name |
Portfolio generation
The portfolio setting in the config generates a combined HTML report:
{
"global": {
"strategy": "kbt",
"export": "trades/{strat}-{sym}.json",
"portfolio": "portfolio-{datetime}.html"
},
"runs": [
{ "symbol": "@ES" },
{ "symbol": "@NQ" }
]
}If portfolio is set without export, trade files are created in a temporary directory and cleaned up after the report is generated.
Command-line overrides
When running with --config, any command-line flag that corresponds to a global config setting will override that setting when explicitly specified. This allows you to quickly test variations without modifying the config file.
Date Range and Capital:
| CLI Flag | Config Setting | Description |
|---|---|---|
--date-from | date-from | Start date for backtest |
--date-to | date-to | End date for backtest |
--initial-capital | initial-capital | Starting capital with optional currency |
--base-currency | base-currency | Base currency for reports |
Series Defaults (applied to all runs that don’t specify their own):
| CLI Flag | Config Setting | Description |
|---|---|---|
--symbols | symbol | Default symbol for runs without their own |
--bar-interval | bar-interval | Bar interval size |
--bar-building-mode | bar-building-mode | How bars are constructed |
--session-hours | session-hours | Trading session hours |
--session-days | session-days | Trading session days |
--timezone | timezone | Timezone for the session |
Engine Options:
| CLI Flag | Config Setting | Description |
|---|---|---|
--max-bars-back | max-bars-back | Maximum lookback period |
--risk-free-rate | risk-free-rate | Risk-free rate for Sharpe |
--position-size | position-size | Default position size |
--no-look-inside-bar | no-look-inside-bar | Disable intra-bar simulation |
--no-pyramiding | no-pyramiding | Disable position pyramiding |
--no-out-of-session-execution | no-out-of-session-execution | Disable out-of-session execution |
--dir-long-only | dir-long-only | Allow only long positions |
--dir-short-only | dir-short-only | Allow only short positions |
Cost Model:
| CLI Flag | Config Setting | Description |
|---|---|---|
--slippage-mode | slippage-mode | Slippage calculation mode |
--slippage-ticks | slippage-ticks | Slippage in ticks |
--commission-mode | commission-mode | Commission calculation mode |
--commission-amount | commission-amount | Commission amount |
--commission-percentage | commission-percentage | Commission percentage |
Output and Execution:
| CLI Flag | Config Setting | Description |
|---|---|---|
--portfolio | portfolio | Portfolio output path |
--export | export | Trade export path |
--audit-trail | audit-trail | Audit trail output path |
--execution-mode | execution-mode | Execution mode (auto/parallel/sequential) |
--workers | parallel-workers | Number of parallel workers |
Filtering:
| CLI Flag | Config Setting | Description |
|---|---|---|
--symbols-exclude | symbols-exclude | Symbols to exclude (additive with config value) |
--filter | filters | Filter name (replaces config filters) |
--market-suitability | Filter runs by market suitability |
Override behavior
- Global settings only: CLI overrides apply exclusively to the
globalsection. To change run-specific settings, edit the config file directly. - Explicit flags only: Only flags explicitly specified on the command line override config values. Default flag values do not override config settings.
- Series defaults propagation: CLI overrides to series-level settings (like
--bar-interval) are applied to the global defaults before they propagate to individual runs. Runs that already define their own series-level settings are not affected. - Symbols-exclude is additive: The
--symbols-excludeflag is combined with anysymbols-excludevalue in the config, rather than replacing it. - Verify effective config: Use
--verifyto display the final config after CLI overrides, without running the backtest.
# Override date range to test a shorter period
algo run --config portfolio.json --date-from 2023-01-01 --date-to 2024-01-01
# Override bar interval for all runs
algo run --config portfolio.json --bar-interval 60m
# Test with different capital and slippage
algo run --config portfolio.json --initial-capital USD50000 --slippage-ticks 5
# Inspect effective config after overrides
algo run --config portfolio.json --bar-interval 60m --verifyMulti-strategy configuration
For portfolios with multiple strategies, use the strategies array instead of runs:
{
"global": {
"date-from": "2015-01-01",
"initial-capital": "USD1000000",
"portfolio": "multi-{datetime}.html"
},
"symbols": {
"symbol": ["@ES", "@NQ", "@CL", "@GC"]
},
"strategies": [
{
"strategy": "kbt",
"runs": [
{ "series": [{ "symbol": "{symbol}", "bar-interval": "daily" }] }
]
},
{
"strategy": "meanrevert",
"symbols": { "symbol": ["@ES", "@NQ"] },
"runs": [
{ "series": [{ "symbol": "{symbol}", "bar-interval": "daily" }] }
]
}
]
}In multi-strategy mode, each strategy can optionally override the global symbol list.
Strategy entry structure
Each entry in the strategies array contains:
| Field | Required | Description |
|---|---|---|
strategy | Yes | Strategy name |
runs | Yes | Array of run configurations (same as single-strategy) |
inputs | No | Strategy-specific input parameters |
symbols | No | Override global symbols for this strategy |
| Other settings | No | Any global setting can be overridden at strategy level |
Key differences from single-strategy mode
| Aspect | Single-Strategy | Multi-Strategy |
|---|---|---|
| Top-level array | runs | strategies |
| Strategy location | global.strategy | Each strategies[].strategy |
| Inputs location | global.inputs | Each strategies[].inputs |
| Symbols | Global only | Global with per-strategy override |
Multi-strategy validation rules
- You cannot have both
strategiesandrunsat the top level - The
strategyfield must not appear inglobal(it belongs in each strategy entry) - The
inputsfield must not appear inglobal(it belongs in each strategy entry) - Each strategy entry must have a
strategyfield and arunsarray with at least one run - Each strategy’s runs are validated against its effective symbols (strategy-level or global)
Run entry format
Each entry in the runs array supports three formats for specifying symbols:
seriesarray (preferred): Full control over each data series:{ "series": [{ "symbol": "@ES", "bar-interval": "60m" }] }symbolfield: Shorthand that creates a series automatically:{ "symbol": "@ES" }symbolsfield: An alias forsymbol(both are accepted):{ "symbols": "@ES/@NQ" }
When using symbol or symbols with slash-separated symbols (e.g., "@ES/@NQ"), each symbol is automatically split into its own series entry.
Global settings reference
The global section supports the following settings (all are optional):
| Setting | Type | Default | Description |
|---|---|---|---|
strategy | string | Strategy name | |
symbol | string | Default symbol (e.g., "@ES", "<div24") | |
series | array | Default series array | |
bar-interval | string | "daily" | Bar interval size |
bar-building-mode | string | "natural" | "natural" or "session" |
date-from | string | "2010-01-01" | Start date (YYYY-MM-DD) |
date-to | string | Today | End date (YYYY-MM-DD) |
initial-capital | string | "1000000" | Initial capital with optional currency prefix |
session-hours | string | Trading session hours | |
session-days | string | Trading session days | |
timezone | string | IANA timezone | |
slippage-mode | string | "per-unit" | "per-unit", "per-trade", or "percentage" |
slippage-ticks | number | 0 | Slippage in ticks |
commission-mode | string | "per-unit" | "per-unit", "per-trade", or "percentage" |
commission-amount | string | "0" | Commission amount |
commission-percentage | number | 0 | Commission as percentage (0-100) |
max-bars-back | number | 263 | Maximum lookback period |
bouncing-ticks | number | 0 | Bouncing ticks percentage (0-100) |
no-look-inside-bar | bool | false | Disable intra-bar order evaluation |
no-pyramiding | bool | false | Disable pyramiding |
no-out-of-session-execution | bool | false | Disable shadow bar evaluation |
dir-long-only | bool | false | Allow only long positions |
dir-short-only | bool | false | Allow only short positions |
risk-free-rate | number | 0.05 | Risk-free rate for Sharpe calculations |
output-mode | string | "silent" | Output verbosity |
inputs | object | Strategy input overrides | |
export | string | Trade export file path (supports template variables) | |
portfolio | string | Portfolio HTML report path (supports template variables) | |
tty | string | Redirect output to file (prefix with >> to append) | |
description | string | Description for portfolio sub-title (supports {$Name} input variables) | |
notes | string | Free-form notes or comments | |
use-first | string | Use first N% of data (e.g., "70" or "70%") | |
use-last | string | Use last N% of data (e.g., "30" or "30%") | |
base-currency | string | Base currency for reports | |
execution-mode | string | "auto" | Execution mode: "auto", "parallel", "sequential" |
parallel-workers | number | 64 | Number of parallel workers (parallel mode only) |
All global settings can be overridden at the run level.
Comprehensive example
The following example demonstrates many config features – global defaults, per-run overrides, different strategies, and multi-symbol runs:
{
"global": {
"strategy": "meanrevert",
"bar-interval": "daily",
"bar-building-mode": "natural",
"date-from": "2015-01-01",
"date-to": "2024-12-31",
"initial-capital": "USD100000",
"session-hours": "8:30am-3:15pm",
"session-days": "Mon-Fri",
"timezone": "America/New_York",
"slippage-mode": "per-unit",
"slippage-ticks": 2,
"commission-mode": "per-unit",
"commission-amount": "2.50USD",
"max-bars-back": 263,
"no-pyramiding": true,
"risk-free-rate": 0.05,
"output-mode": "summary",
"inputs": {
"Period": 20,
"Mult": 1.5
}
},
"runs": [
{
// Uses all global defaults
"symbol": "@ES"
},
{
// Override bar interval and session, plus strategy inputs
"symbol": "@NQ",
"bar-interval": "60m",
"session-hours": "9:30am-4:00pm",
"inputs": {
"Period": 15,
"Mult": 2.0
}
},
{
// Different capital and timezone
"symbol": "@CL",
"initial-capital": "USD50000",
"slippage-ticks": 1,
"timezone": "America/Chicago",
"session-hours": "6:00pm-5:00pm"
},
{
// Different strategy entirely
"symbol": "@GC",
"strategy": "trendfollow",
"dir-long-only": true,
"inputs": {
"FastMA": 10,
"SlowMA": 50
}
},
{
// Different date range and commission model
"symbol": "@ZB",
"date-from": "2018-01-01",
"commission-mode": "per-trade",
"commission-amount": "5.00"
},
{
// Multi-symbol pairs strategy using series array
"strategy": "pairs",
"series": [
{
"symbol": "@ES",
"bar-interval": "60m",
"session-hours": "9:30am-4:00pm",
"timezone": "America/New_York"
},
{
"symbol": "@NQ",
"bar-interval": "60m",
"session-hours": "9:30am-4:00pm"
}
]
}
]
}Validation
Use --verify to validate a config file without running any backtests:
algo run --config myconfig.json --verifyValidation checks include:
- Type checking: Ensures values are the correct type
- Range checking: Validates numeric ranges (e.g.,
bouncing-ticksmust be 0-100) - Format checking: Validates date formats, time formats, and timezone names
- Logical checking: Prevents conflicting options (e.g., both
dir-long-onlyanddir-short-only) - Series validation: Ensures each run has at least one series with a valid symbol
The standalone algo config -f <file> command can also be used to validate and display the parsed config as formatted JSON.
Example validation errors:
Configuration error: batch.run:15:3: JSON syntax error: invalid character '}' after object key
Configuration error: batch.run: global: invalid bar-building-mode "invalid" (must be one of: natural, session)
Configuration error: batch.run: global: date-from (2020-01-01) must be before date-to (2019-01-01)
Configuration error: batch.run: global: cannot specify both dir-long-only and dir-short-only as true
Configuration error: batch.run: runs[0]: at least one series with a symbol is required
Configuration error: batch.run: runs list cannot be empty
Configuration error: batch.run: symbol template {symbol2} references source 2, but only 1 source(s) defined
Configuration error: batch.run: runs[0] ({symbo}) series[0]: unrecognized template {symbo}Tips
- Start simple: Begin with minimal global settings and add per-run overrides as needed.
- Validate before running: Always use
algo run --config myconfig.json --verifyto check for errors before running full backtests. - Organise by strategy: Group related runs that use the same strategy together for easier maintenance.
- Use portfolio files: Reference portfolio files with
<prefix rather than listing symbols inline for commonly used groups. - Use template variables: Take advantage of
{strat},{sym}, and{datetime}in export and portfolio paths to generate unique filenames automatically.