Backtest
[backtest] defines the global environment in which your strategy runs.
It sets the test period, the symbols and timeframes to load, the initial capital, fees and slippage, the entry sizing rules, and the parameters related to margin, leverage, and pyramiding.
A strategy file can contain only one [backtest] block.
See the Exchanges, Symbols and Timeframes page for symbol and timeframe interpretation.
The logic for margin, leverage, account equity, sizing price, execution price, and liquidation is described in the Using Margin and Leverage in Whale‑E page. The [backtest] block only exposes the configuration options needed by that logic.
How numeric ranges with .start, .stop and .step are combined with indicator ranges is explained in the Hyperparameter Combinations page.
Block declaration
A strategy can contain only one [backtest] block.
Examples
The following examples show complete configurations you can adapt to your own strategies. The detailed behaviour of default_qty_type, default_qty_value, margin_*, and the size multipliers is described in Using Margin and Leverage in Whale‑E.
Minimal setup
This minimal configuration defines a single symbol, a single timeframe and a test period. All other settings use their default values.
[backtest]
symbol = "BINANCE:BTCUSDT"
timeframe = "240"
start_date = 2024-01-01
end_date = 2025-01-01
initial_capital = 1000Backtest without explicit leverage in terms of exposure
This block configures a backtest where orders are sized as a percentage of account equity. Margin parameters remain at their defaults, and allocation stays below 100% to keep a safety buffer for fees and sizing-to-fill price gaps in the default 1x frame.
[backtest]
symbol = "BINANCE:BTCUSDT"
timeframe = "240"
start_date = 2024-01-01
end_date = 2025-01-01
initial_capital = 1000
default_qty_type = "percent_of_equity"
default_qty_value = 95Backtest with margin and asymmetric multipliers
This block shows a configuration where positions are opened with a limited share of equity, margin is below 100%, and size multipliers differ on the long and short side.
[backtest]
symbol = "BINANCE:BTCUSDT"
timeframe = "240"
start_date = 2024-01-01
end_date = 2025-01-01
initial_capital = 1000
default_qty_type = "percent_of_equity"
default_qty_value = 30
margin_long = 50 # 50 % margin on long positions
margin_short = 50 # 50 % margin on short positions
long_size_multiplier = 5 # ×5 size multiplier for longs
short_size_multiplier = 2 # ×2 size multiplier for shortsExploring capital allocation
The default_qty_value range defines a series of equity allocations from 10 % to 95 % in steps of 5. With default_qty_type = "percent_of_equity", this key is the global exposure base before any side multiplier is applied.
[backtest]
symbol = "BINANCE:BTCUSDT"
timeframe = "240"
start_date = 2024-01-01
end_date = 2025-01-01
initial_capital = 1000
default_qty_type = "percent_of_equity"
long_size_multiplier = 4
default_qty_value.start = 10
default_qty_value.stop = 95
default_qty_value.step = 5Exploring the long multiplier with fixed allocation
Capital allocation is fixed at 40 % of equity with default_qty_value = 40. The long_size_multiplier range then defines a set of size multipliers for long positions. This pattern is useful in grid search because it keeps a shared base and varies only long-side exposure.
[backtest]
symbol = "BINANCE:BTCUSDT"
timeframe = "240"
start_date = 2024-01-01
end_date = 2025-01-01
initial_capital = 1000
default_qty_type = "percent_of_equity"
default_qty_value = 40
long_size_multiplier.start = 1
long_size_multiplier.stop = 10
long_size_multiplier.step = 0.5Exploring allocation and size multipliers together
Equity allocation and both the long and short size multipliers are explored at the same time. Each combination of these parameters produces a separate backtest run.
This example is mainly relevant for strategies that can open both long and short positions. In that case, default_qty_value defines a shared base, while long_size_multiplier and short_size_multiplier adjust each side separately. On a one-sided strategy, these parameters largely collapse into the same thing on the active side, so the value of this joint optimisation becomes much more limited.
[backtest]
symbol = "BINANCE:BTCUSDT"
timeframe = "240"
start_date = 2024-01-01
end_date = 2025-01-01
initial_capital = 1000
default_qty_type = "percent_of_equity"
# Equity allocation range
default_qty_value.start = 10
default_qty_value.stop = 50
default_qty_value.step = 5
# Long‑side size multipliers
long_size_multiplier.start = 1
long_size_multiplier.stop = 10
long_size_multiplier.step = 0.5
# Short‑side size multipliers
short_size_multiplier.start = 1
short_size_multiplier.stop = 10
short_size_multiplier.step = 0.5Parameters of the [backtest] block
The table below lists all parameters available in the [backtest] block. When the description mentions other documentation pages, those pages contain the detailed explanations. For everything related to sizing, margins, and multipliers, the reference page remains Using Margin and Leverage in Whale‑E.
| Parameter | Description |
|---|---|
start_dateDate‑Time Required | Start date of the backtest. Dates may include a numeric offset. The engine always runs internally in UTC, but it first interprets both start_date and end_date using a fixed inferred offset, then converts them to UTC.Offset inference and validation rules:
Accepted formats:
|
end_dateDate‑Time Required | End date of the backtest. It uses the same formats and offset rules as start_date. |
price_history_start_dateDate‑Time Optional | Explicit start date for the price history fetch window. This key only controls how much upstream data is loaded and does not change the business backtest window (start_date/end_date). It follows the same date formats and offset rules as start_date and end_date.If omitted, Whale‑E keeps the current automatic lookback-based behaviour. If provided too late to satisfy the minimum required lookback, Whale‑E automatically clamps it backward to the required minimum and emits a warning. Default: automatic calculation. |
symbolString or Array Required | Main symbol of the simulation. Can be a single string (for example "BINANCE:BTCUSDT") or an array of symbols. The exchange prefix is required in the form EXCHANGE:SYMBOL. When several symbols are provided, Whale‑E builds a grid for each symbol/timeframe combination. The Exchanges, Symbols and Timeframes page describes the supported formats in detail. |
timeframeString or Array Required | Main timeframe of the backtest. Can be a single string (for example "60", "240", "D", "W") or an array of timeframes. When several timeframes or symbols are given, Whale‑E creates a separate grid for each symbol/timeframe combination. The way indicators override their own timeframe is described in the Exchanges, Symbols and Timeframes page. |
auto_slippage_enabledBoolean Optional | Enables automatic slippage based on one‑minute candles. If false, slippage is defined only by slippage.Default: false. |
auto_slippage_ratioDecimal Optional | Ratio applied to the one‑minute high‑low range when computing automatic slippage. Ignored when auto_slippage_enabled is false.Default: 0.25. |
slippageInteger Optional | Number of price ticks added manually as slippage to the execution price. Used only when auto_slippage_enabled is false.Default: 0. |
backtest_fill_limits_assumptionInteger Optional | Minimum overrun, in ticks, required to consider a LIMIT order as filled. A value of 0 means a simple touch. This parameter applies to LIMIT entries and to the LIMIT leg of STOP_LIMIT entries.Default: 0. |
use_bar_magnifierBoolean Optional | Enables intrabar inspection using a lower timeframe to determine the actual order of events inside an aggregated candle (for example “entry then stop” on the same bar). When disabled, the intrabar order is inferred only from OHLC data at the main timeframe. Default: false. |
process_orders_on_closeBoolean Optional | Controls when orders submitted on a bar close become eligible for execution. When false, an order created on a bar close can only be executed starting from the next bar open (the first available tick in historical backtests). When true, orders can be processed on the current bar close tick.Default: false. |
max_blocks_on_same_candleInteger Optional | Maximum number of blocks executed on the same candle without advancing to the next candle. Used to detect and stop infinite loops. Set to 0 to disable.Default: 1024. |
commission_valueDecimal Optional | Commission value, interpreted according to commission_type. In percent mode it is a percentage and must remain strictly below 100. In cash_per_contract or cash_per_order mode it is a fixed amount in quote currency.Default: 0.1. |
commission_typeString Optional | Commission mode. Possible values are percent, cash_per_contract and cash_per_order.Default: "percent". |
initial_capitalDecimal Optional | Initial capital of the backtest, in the quote currency of the main symbol. Default: 1000000. |
default_qty_typeString Optional | Global mode used to compute entry size: fixed, cash, or percent_of_equity.Default: "percent_of_equity". |
default_qty_valueDecimal or Range Optional | Public global sizing value used by entry blocks when the block does not define qty or qty_percent. In fixed mode, this value is an absolute quantity. In cash mode, it is a monetary budget. In percent_of_equity, it is the global percentage base before any long_size_multiplier or short_size_multiplier is applied. A single value is accepted in every mode. .start, .stop and .step variants are accepted only in percent_of_equity for grid search.Default: 100 in percent_of_equity. In fixed and cash, if default_qty_value is absent and no local qty or qty_percent is provided, the order is rejected. |
margin_longDecimal Optional | Margin percentage applied to long positions. Required margin for a long is the notional value multiplied by margin_long / 100. A value of 0 disables the margin system for long positions. This option also supports .start, .stop and .step suffixes for grid search. The full margin and liquidation behaviour is described in Using Margin and Leverage in Whale‑E.Default: 100. |
margin_shortDecimal Optional | Margin percentage applied to short positions. Required margin for a short is the notional value multiplied by margin_short / 100. A value of 0 disables the margin system for short positions. As for margin_long, .start, .stop and .step variants can be used for grid search.Default: 100. |
long_size_multiplierDecimal Optional | Multiplier applied to the global base defined by default_qty_value for long orders in percentage-based sizing modes. A value of 1 leaves the size unchanged. This option can be set as a single value or as a range (.start, .stop, .step) for grid search. It is ignored for entry sizing in fixed and cash modes.Default: 1. |
short_size_multiplierDecimal Optional | Multiplier applied to the global base defined by default_qty_value for short orders in percentage-based sizing modes. A value of 1 leaves the size unchanged. As with the long side, .start, .stop, .step variants are available for grid search. It is ignored for entry sizing in fixed and cash modes.Default: 1. |
pyramidingInteger Optional | Maximum number of entries allowed in the same direction for a position. A value of 1 disables pyramiding and limits the position to a single entry. A value N allows up to N cumulative entries before additional entry signals are ignored.Default: 1. |
close_entries_ruleString Optional | Rule used when a [[close]] block consumes entries that are already open. In this context, order_id always references the order_id value of a [[entry]] block. With fifo, the engine closes the oldest open entries first, even when the [[close]] block targets a specific entry through order_id. With any, it closes the entry targeted by order_id first, then falls back to the oldest open entries if some quantity still needs to be closed.Default: "fifo". |
close_open_position_at_endBoolean Optional | Controls how a position that is still open at end_date is handled. When true, Whale‑E automatically closes the position at the end of the backtest so the result stays bounded to the selected window. When false, the position remains open in the engine and Whale‑E values it at end_date for the final calculation. No explicit closing trade is added at the end of the window. Default: true. |
Additional notes
Automatic slippage and 1‑minute data
When auto_slippage_enabled is true, the engine applies slippage to each order based on the one‑minute candle in which the execution occurs. It takes that minute’s high‑low range, multiplies it by auto_slippage_ratio, then shifts the execution price by that amount in an unfavourable direction.
The one‑minute candles required for this calculation are loaded automatically, whatever the main timeframe of the backtest is. When auto_slippage_enabled is false, slippage is defined only by slippage, and the engine does not simulate intrabar slippage.
Order size modes (default_qty_type)
The pair default_qty_type / default_qty_value defines the global method used to compute entry size for [[entry]] and [[order]] blocks, as long as no local qty or qty_percent override is present.
In fixed mode, entry size is an absolute quantity. If no local qty or qty_percent is provided, Whale‑E uses [backtest].default_qty_value. If that value is absent, the order is rejected.
In cash mode, entry size is a monetary budget. If no local qty or qty_percent is provided, Whale‑E uses [backtest].default_qty_value as the global fallback value.
In percent_of_equity mode, entry size is determined from a percentage of equity. default_qty_value defines that global base, then side multipliers can adjust it. In this mode, default_qty_value can be provided as a single value or as a range.
For the exact semantics of each mode, the reference page remains Using Margin and Leverage in Whale‑E.
Pyramiding
The pyramiding parameter sets the maximum number of entries that can be accumulated in the same direction for a single position.
A value of 1 disables pyramiding. Once an initial entry has been executed, no additional entry can increase the position until it has been fully closed or reversed.
A value N > 1 allows up to N successive entries in the same direction. The counter is reset when the position is fully closed or when it changes sign (from long to short or the opposite).
Timestamps and storage
Internally, the engine runs strictly in UTC. Interpretation of start_date and end_date, as well as formatting of timestamps in logs and database records, uses the fixed offset inferred from the dates you provide. This offset is constant for the full backtest.
Timestamps stored in the database include this offset in a dedicated context field (for example UTC+02:00).
End-of-backtest handling for open positions (close_open_position_at_end)
The close_open_position_at_end setting decides whether a position that is still open at end_date is closed or only valued.
With close_open_position_at_end = true, Whale‑E automatically closes the position at the end of the backtest. The result is then strictly bounded by the selected window, which is the most straightforward way to analyze a finished run.
With close_open_position_at_end = false, Whale‑E keeps the position open in the engine and values it at end_date for the final result. This keeps the terminal exposure visible, but some final values change because no explicit close is added at end_date.