Custom Series

[[custom_series]] lets you create a custom numeric series from a formula.

In this block, the formula is limited to symbols available at indicator stage. Runtime backtest, portfolio, order, and trade variables are not available.

Use this block to isolate an intermediate calculation and reuse it across conditions or as input to other indicators.

How the formula interprets series

Inside a custom_series, a series is not interpreted on the native timeframe of the block that produced it, but on the timeframe of the block that reads it.

In other words, the formula always evaluates in the frame of reference of the custom_series itself. If it uses a series coming from another timeframe, that series is first realigned onto the block axis before it is used. Both the current value and its history are therefore read in that same frame.

Take a simple case. If your main strategy runs on 240, an indicator daily_signal is calculated on D, and a custom_series reads that indicator without defining its own timeframe, then the formula runs on the 240 axis. In that context, daily_signal[1] means the value seen one 240 bar earlier on the projected series. It does not mean the previous daily bar.

This rule matters as soon as you combine multiple timeframes in the same formula. It ensures that a series and its history remain consistent from the point of view of the block consuming them.

Block declaration

A strategy can contain multiple [[custom_series]] blocks. Each block outputs one numeric series identified by its id.

formula follows the general expression rules (operators, functions, reserved constants, historical indexing). See Expressions and functions. In [[custom_series]], the formula can use standard price series, outputs from indicators already defined in the strategy, and the variables they expose.

Examples

Minimal setup

This block reproduces Williams Variable Accumulation/Distribution. The formula measures the gap between close and open, normalizes it by the candle range, then weights it by volume.

[[custom_series]]
id      = "wvad"
formula = "high != low ? (close - open) / (high - low) * volume : 0"

True Range

This block computes the True Range of a candle. The formula takes the maximum between the current range (high - low) and the absolute gaps between the current candle extremes and the previous close.

[[custom_series]]
id      = "true_range"
formula = "max(high - low, abs(high - close[1]), abs(low - close[1]))"

Dedicated timeframe

This block forces the computation onto a daily timeframe. If timeframe is omitted, the block runs on the grid main timeframe defined in [backtest].

[[custom_series]]
id        = "daily_body"
formula   = "close - open"
timeframe = "D"

See the Exchanges, Symbols and Timeframes page for alignment rules between this timeframe and the main timeframe.

Using custom_series as the source of another indicator

A custom series can be reused as source in other indicator blocks.

[[custom_series]]
id      = "price_delta"
formula = "close - close[1]"

[[moving_average]]
id     = "delta_ma"
type   = "ema"
source = "price_delta"
length = 20

Variables exposed by indicators

A custom_series formula can also use the variables exposed by indicators already defined in the strategy, for example fast.length, fast.type, fast.symbol, or fast.timeframe.

This example adapts the formula according to the moving-average types currently being evaluated during grid search.

[[moving_average]]
id           = "fast"
type         = ["sma", "ema"]
length.start = 10
length.stop  = 30

[[moving_average]]
id     = "slow"
type   = ["sma", "ema"]
length = 50

[[custom_series]]
id      = "ma_signal"
formula = "fast.type == 'ema' and slow.type == 'ema' ? fast / slow : (fast - slow) / slow * 100"

Parameters

ParameterDescription
id
 String
 Required
Unique name of the produced series. This identifier becomes the variable name you use in expressions.
formula
 Expression
 Required
Expression that defines the computed series.
Supported inputs: standard prices, ids of indicators already defined, variables exposed by those indicators (fast.length, fast.type, fast.symbol, fast.timeframe, etc.), numeric constants, and expression functions.
Accepted TOML types: string, integer, floating-point number.
Runtime backtest, portfolio, order, and trade variables are not available in this block.
Reserved constants pi, euler, phi, and rphi should not be reused as business identifiers.
timeframe
 String
 or Array
 Optional
Timeframe used to compute the series.
If omitted, computation uses the grid main timeframe defined in [backtest].
For accepted formats and alignment rules, see Exchanges, Symbols and Timeframes.
symbol
 String
 or Array
 Forbidden
symbol is not allowed on [[custom_series]].
For multi-market logic, define upstream indicator sources with their own symbols, then combine those indicators in formula.

Available variables

The custom_series block exposes one numeric series plus context metadata (symbol, timeframe). These variables are exposed after the series has been computed and can be used downstream. They are not available inside the block formula itself.

Assume this configuration:

[[custom_series]]
id      = "candle_body"
formula = "close - open"

Then:

VariableDescription
candle_body or candle_body[0]
Decimal
Current value of the computed series.
candle_body[n]
Decimal
Value of the series n bars ago.
candle_body.symbol
String
Market symbol effectively used by this block.
candle_body.timeframe
String
Timeframe effectively used by this block.

Notes

  • Numeric variables support arithmetic, comparisons, and logical operators.
  • Text variables are intended for equality/inequality checks only.
  • A formula cannot reference its own id (self-reference is forbidden).

Common errors

Message (summary)Typical causeFix
Invalid formulaInvalid expression syntax, missing parenthesis, or malformed expression token.Simplify the formula, verify variable names, then rebuild it progressively.
The expression cannot reference its own idSelf-reference (for example id = "x" with formula = "x + 1").Use another input series; do not reference the current block id in its own formula.
Key 'symbol' is not allowed on custom_series blockssymbol is present in [[custom_series]].Remove symbol from the block and handle multi-market logic through upstream indicators.
Unknown source idA referenced indicator id does not exist (typo, case mismatch, missing block), or the formula uses a variable that is not exposed by an indicator already defined in the strategy.Check spelling/case, ensure the source indicator block exists, and only use standard price series, outputs from indicators already defined, or the variables they expose.
Cyclic dependencyCircular indicator dependency graph.Refactor block dependencies to remove the cycle.