Getting Started
Backtest Labs is a visual backtesting platform where you design trading strategies by connecting nodes on a canvas. Each node represents a distinct piece of your strategy, whether that's an indicator calculating values from market data, an operator comparing signals, or an action node executing trades when your conditions are met. Once your strategy is wired up, you can run it against historical market data to see exactly how it would have performed, complete with performance analytics, interactive charts, and detailed trade logs.
Nodes
Overview
This section documents every node available in the strategy builder. Nodes are organized into categories based on their function, and each node's entry covers what it does, the math behind it, its parameters, and its inputs and outputs.
Nodes are organized into categories:
- IndicatorsCalculate technical values from price, volume, and other market data
- ActionsExecute trades (Buy, Sell) or hold position (Wait)
- OperatorsCombine and compare signals using logic and math
- UtilitiesHelpers like crossover detection, stop losses, and scheduling
- PortfolioAccess live portfolio metrics like drawdown, exposure, and cash balance
Some indicator nodes have optional input handles that allow you to override one of their default parameter values by connecting the output of another node. Each node's documentation specifies which inputs are available and whether they're required or optional.
Wire types
Every connection between nodes carries one of three kinds of data. The strategy builder enforces type compatibility when you drag a wire from an output to an input.
- Signal — a per-bar on/off state (active or inactive). Action nodes (Buy, Sell, Wait) and signal combiners (And, Or, Sequence) consume signals on their inputs.
- Series — a per-bar numeric value (a line). Indicator value outputs like the RSI line, an MA line, or ATR×multiplier are series. Math, Relation, Crossover, Direction Filter, and the optional data_in handles on indicators accept series. A Constant is automatically treated as a broadcast-constant series, so a Numeric Value source plugs into any Series input.
- Constant — a single numeric value broadcast to every bar. The Numeric Value node is the canonical constant source. Any Series-typed input also accepts a Constant.
Multi-line outputs and the line selector
Some indicators emit more than one line at once. Bollinger Bands emits upper, middle, and lower bands; DMI emits ADX, +DI, and -DI; Ichimoku emits four lines. Every wire coming out of a multi-line indicator has a small label near the source end showing which line is flowing through.
The label is always visible. Three states:
- Auto-route (default) — the label shows the indicator's primary line name (middle band for Bollinger Bands, conversion line for Ichimoku) with a dim border. The wire carries the primary line.
- Explicit selection — after you click the label and pick a different line, the border turns brand-colored and the wire carries the chosen line. Picking the primary line again returns to auto-route.
- Stale selection — if a node config change removes the previously-picked line (for example, switching DMI from dmi_adx to adx_only after wiring +DI), the label renders with a warning-colored fill and border so you can re-pick rather than silently delivering a no-longer-available series.
Clicking the label opens a menu of the lines the source indicator currently emits. The menu adapts to the indicator's config: pivot styles, MA periods, DMI mode, support/resistance levels — each governs which lines are selectable.
EMA
The EMA node computes one or more exponential moving averages of price or any connected numeric series. It weights recent bars more heavily than an SMA of the same length and supports three signal modes (trend, crossover, ribbon).
Parameters
- Type
- Direction
- Period
Lookback in bars for each EMA. Count limits depend on Type: Trend uses 1, Crossover requires exactly 2 (labeled Fast and Slow), Ribbon accepts 3 to 8 (labeled P1 through P8). The Trend mode compares the source to the slowest (last) period.
- data_in
If connected, each EMA is computed on the connected series. If unconnected, computed on the close price of the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where the configured condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The EMA line, or the configured set of lines (one per period in Crossover or Ribbon mode), drawn as price overlays. Any input that accepts a Series receives ema_1 (the primary line) by default; the line selector on the output handle lets you pick any of the other configured periods (ema_1 through ema_N).
Formulas
First EMA = SMA over the first N closes Then: EMA at bar t = alpha * close[t] + (1 - alpha) * EMA[t-1] where alpha = 2 / (N + 1)
Bullish: signal[t] = 1 while source[t] > EMA_slowest[t] Bearish: signal[t] = 1 while source[t] < EMA_slowest[t]
signal[t] = 1 when fast[t] > slow[t] AND fast[t-1] <= slow[t-1], else 0
signal[t] = 1 when fast[t] < slow[t] AND fast[t-1] >= slow[t-1], else 0
Bullish: signal[t] = 1 while EMA_1[t] > EMA_2[t] > ... > EMA_N[t] Bearish: signal[t] = 1 while EMA_1[t] < EMA_2[t] < ... < EMA_N[t]
MA
The MA node computes a moving average of price or any connected numeric series. It supports two calculation methods (SMA and SMMA) and three signal modes (trend, crossover, ribbon).
Parameters
- Type
- Method
- Direction
- Period
Lookback in bars for each moving average. Count limits depend on Type: Trend uses 1, Crossover requires exactly 2 (labeled Fast and Slow), Ribbon accepts 3 to 8 (labeled P1 through P8).
- data_in
If connected, the moving average is computed on the connected series. If unconnected, computed on the close price of the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where the configured condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The moving average line, or the configured set of lines (one per period in Crossover or Ribbon mode). The chart draws these as overlays. Any input that accepts a Series receives ma_1 (the primary line) by default; the line selector on the output handle lets you pick any of the other configured periods (ma_1 through ma_N).
Formulas
SMA at bar t = (close[t-N+1] + close[t-N+2] + ... + close[t]) / N
First SMMA = SMA over the first N closes Then: SMMA at bar t = alpha * close[t] + (1 - alpha) * SMMA[t-1] where alpha = 1 / N
signal[t] = 1 when fast[t] > slow[t] AND fast[t-1] <= slow[t-1], else 0
signal[t] = 1 when fast[t] < slow[t] AND fast[t-1] >= slow[t-1], else 0
DMI / ADX
The DMI node computes the Directional Movement Index — the +DI and -DI directional lines and the ADX trend-strength line. It emits a signal from directional dominance gated by a minimum ADX threshold.
Parameters
- Period
Wilder smoothing length for the directional movement, true range, and ADX. +DI and -DI become defined after the period; ADX after roughly twice the period.
- Threshold
The minimum ADX value required for the signal to activate. Bars where ADX sits at or below the threshold produce no signal regardless of directional dominance.
- Output Lines
This selection controls the chart and Series outputs only. The signal condition always uses directional dominance gated by the configured ADX threshold.
- Direction
- data_in
If connected, the high, low, and close all collapse to the connected series (a single-value bar), so the directional movement is measured on the series' own bar-to-bar change. If unconnected, the high, low, and close of the strategy's ticker are used.
Outputs
- signal — Signal. Activates on bars where the configured Direction holds with ADX above the threshold, independent of Output Lines. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The line or lines selected by Output Lines, drawn as a sub-panel and offered by the output line selector. Any input that accepts a Series receives ADX by default for ADX only or DMI + ADX, and +DI by default for DMI only.
Formulas
+DM = up move when up move > down move and up move > 0, else 0 -DM = down move when down move > up move and down move > 0, else 0 where up move = high[t] - high[t-1], down move = low[t-1] - low[t]
+DI = 100 * Wilder-smoothed(+DM) / Wilder-smoothed(true range) -DI = 100 * Wilder-smoothed(-DM) / Wilder-smoothed(true range)
DX = 100 * |+DI - -DI| / (+DI + -DI) ADX = Wilder-smoothed(DX)
Bullish: signal[t] = 1 while +DI[t] > -DI[t] AND ADX[t] > threshold Bearish: signal[t] = 1 while -DI[t] > +DI[t] AND ADX[t] > threshold
Ichimoku Cloud
The Ichimoku node computes the Ichimoku Kinko Hyo lines — the Conversion Line, Base Line, and the two leading spans that form the cloud. It emits a signal from the close's position relative to the cloud.
Parameters
- Conversion Line Period
Lookback for the Conversion Line (Tenkan-sen), the midpoint of the highest high and lowest low over the window.
- Base Line Period
Lookback for the Base Line (Kijun-sen), the midpoint of the highest high and lowest low over the window.
- Leading Span B Period
Lookback for Leading Span B (Senkou Span B), the midpoint of the highest high and lowest low over the window.
- Displacement
Number of bars the two leading spans are shifted forward. The cloud compared against the close at a given bar is the span value from this many bars earlier.
- Direction
Ichimoku has no data_in handle: the lines are built from the high, low, and close of the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where the close is above (bullish) or below (bearish) both leading spans. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The Conversion Line, Base Line, Leading Span A, and Leading Span B, drawn as price overlays with the span pair shaded as the cloud. Any input that accepts a Series receives the Conversion Line; conversion_line, base_line, span_a, and span_b are each available by name on the output handle.
Formulas
Conversion Line = (highest high + lowest low) / 2 over the Conversion period Base Line = (highest high + lowest low) / 2 over the Base period Leading Span A = ((Conversion Line + Base Line) / 2) shifted forward by Displacement Leading Span B = ((highest high + lowest low) / 2 over the Span B period) shifted forward by Displacement
Bullish: signal[t] = 1 while close[t] > Span A[t] AND close[t] > Span B[t] Bearish: signal[t] = 1 while close[t] < Span A[t] AND close[t] < Span B[t]
Supertrend
The Supertrend node builds an ATR-banded trend line that locks under price in an uptrend and over price in a downtrend, flipping sides when the close breaks through. It emits a signal from the current trend side.
Parameters
- ATR Period
Wilder smoothing length for the Average True Range that sets the band width. Shorter periods make the bands react faster and flip more often.
- Multiplier
The number of ATRs the bands sit away from the midpoint of the high and low. Larger values widen the bands, so the trend flips less often.
- Direction
- data_in
If connected, the high, low, and close all collapse to the connected series (a single-value bar), so the bands track the series itself. If unconnected, the high, low, and close of the strategy's ticker are used.
Outputs
- signal — Signal. Active on every bar in the matching trend state, not only on the flip bar. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The lower and upper bands, drawn as price overlays. The Supertrend line itself (supertrend), and the lower_band and upper_band, are each available by name on the output handle.
Formulas
basic upper = (high + low) / 2 + multiplier * ATR basic lower = (high + low) / 2 - multiplier * ATR where ATR is Wilder's average true range over the ATR period
The final upper band only ratchets down unless the prior close breaks above it; the final lower band only ratchets up unless the prior close breaks below it. The Supertrend line is whichever final band the close is currently on.
Bullish: signal[t] = 1 while close[t] is above the Supertrend line (uptrend) Bearish: signal[t] = 1 while close[t] is below the Supertrend line (downtrend)
Parabolic SAR
The Parabolic SAR node plots a stop-and-reverse dot that trails price, accelerating toward it as the trend extends and flipping to the other side when price crosses it. It emits a signal on each flip.
Parameters
- Acceleration Factor
The starting acceleration and the step added each time price makes a new extreme in the current trend. Larger values pull the dot toward price faster, producing earlier flips.
- Max Acceleration
The ceiling on the acceleration factor. Once reached, the dot stops accelerating for the remainder of the trend.
- Direction
Parabolic SAR has no data_in handle: it is computed from the high and low of the strategy's ticker.
Outputs
- signal — Signal. Activates on the bar where the close crosses the SAR in the configured Direction. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The SAR dot value, drawn as a price overlay. Any input that accepts a Series receives this line.
Formulas
SAR[t] = SAR[t-1] + AF * (EP - SAR[t-1]) where EP is the extreme point (highest high in an uptrend, lowest low in a downtrend) and AF rises by the Acceleration Factor on each new extreme, capped at Max Acceleration
When price crosses the SAR, the trend flips: SAR resets to the prior EP, EP resets to the current extreme, and AF resets to the Acceleration Factor.
Bullish: signal[t] = 1 when close[t] > SAR[t] AND close[t-1] <= SAR[t-1] Bearish: signal[t] = 1 when close[t] < SAR[t] AND close[t-1] >= SAR[t-1]
Trendline
The Trendline node draws trendlines from swing pivots by default: a resistance line through the two most recent confirmed swing highs (measured on the high) and a support line through the two most recent confirmed swing lows (on the low), with breakout signals against the close. Wiring both anchor inputs switches it to a single custom line between two captured anchor points. Wiring exactly one anchor blocks the run.
Parameters
- Pivot Strength
Bars required on each side of a swing high or low, with every neighbor strictly lower (high) or higher (low). A pivot confirms this many bars after it forms, so lines and signals arrive with that delay.
- Basis
Automatic mode always measures swing highs on the high and swing lows on the low, and compares breakouts against the close.
- Update Mode
- Extend
- Cross Signal
- A
A boolean mask marking the bar to capture as the first custom anchor. The anchor's value is the basis price on that bar. Wire A and B together or not at all — a single wired anchor blocks the run.
- B
A boolean mask marking the bar to capture as the second custom anchor. A line is drawn only once both anchors exist and B is on a later bar than A.
Outputs
- signal — Signal. Activates on bars where the configured Cross Signal condition fires. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. Automatic mode draws both lines (Resistance and Support) as price overlays; an input that accepts a Series receives the resistance line. Wired mode carries the single custom line.
Formulas
Resistance: line through the two most recent confirmed pivot highs, extended forward Support: line through the two most recent confirmed pivot lows, extended forward A pivot high at bar p requires high[p] to exceed every high within (Pivot Strength) bars on both sides; it confirms at bar p + Pivot Strength
slope = (B value - A value) / (B bar - A bar) line[t] = A value + slope * (t - A bar)
Automatic Cross Up: signal[t] = 1 when close[t] > resistance[t] AND close[t-1] <= resistance[t-1] Automatic Cross Down: signal[t] = 1 when close[t] < support[t] AND close[t-1] >= support[t-1] Wired: the same cross test against the custom line using the basis price
Aroon
The Aroon node measures how recently price made a new high or low within a lookback window. It produces an Aroon Up line, an Aroon Down line, and their difference (the oscillator), and emits a signal from the relationship between the two lines.
Parameters
- Period
Lookback in bars. Aroon Up reads 100 when the highest high is the current bar and decays toward 0 as that high recedes over the period; Aroon Down does the same for the lowest low.
- Direction
- Trigger
Aroon has no data_in handle: it is defined directly on the bars since the highest high and lowest low of the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where the configured Direction and Trigger condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The Aroon Up, Aroon Down, and oscillator lines on a 0 to 100 (oscillator -100 to 100) scale, drawn as a sub-panel. Any input that accepts a Series receives the Aroon Up line; aroon_up, aroon_down, and oscillator are each available by name on the output handle.
Formulas
Aroon Up = 100 * (period - bars since highest high) / period Aroon Down = 100 * (period - bars since lowest low) / period Oscillator = Aroon Up - Aroon Down
Bullish: signal[t] = 1 when Up[t] > Down[t] AND Up[t-1] <= Down[t-1] Bearish: signal[t] = 1 when Down[t] > Up[t] AND Down[t-1] <= Up[t-1]
Bullish: signal[t] = 1 while Up[t] > Down[t] Bearish: signal[t] = 1 while Down[t] > Up[t]
RSI
The RSI node computes the Relative Strength Index, a momentum oscillator bounded between 0 and 100 that weighs the size of recent gains against recent losses. It emits a signal from overbought and oversold threshold conditions, with a choice of edge-triggered or sustained activation.
Parameters
- Period
Lookback in bars for the average gain and average loss that feed the index. Shorter periods produce a faster, noisier oscillator; longer periods produce a smoother one.
- Oversold
The lower threshold. Must stay below Overbought; the editor keeps the two values ordered. Drives the bullish condition.
- Overbought
The upper threshold. Must stay above Oversold; the editor keeps the two values ordered. Drives the bearish condition.
- Direction
- Trigger
- data_in
If connected, RSI is computed on the connected series. If unconnected, it is computed on the close price of the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where the configured Direction and Trigger condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The RSI line on a 0 to 100 scale, drawn as a sub-panel oscillator. Any input that accepts a Series receives this line.
Formulas
RS = average gain / average loss over the period RSI = 100 - (100 / (1 + RS))
First average = simple mean of the first N gains (or losses) Then: average[t] = (average[t-1] * (N - 1) + current[t]) / N
signal[t] = 1 when RSI[t] >= oversold AND RSI[t-1] < oversold, else 0
signal[t] = 1 when RSI[t] <= overbought AND RSI[t-1] > overbought, else 0
Bullish: signal[t] = 1 while RSI[t] < oversold Bearish: signal[t] = 1 while RSI[t] > overbought
MACD
The MACD node computes Moving Average Convergence Divergence, a momentum indicator built from the gap between a fast and a slow EMA of price. It emits a signal from the MACD line crossing its signal line, with a choice of edge-triggered or sustained activation.
Parameters
- Fast Period
Lookback in bars for the faster EMA. Must be shorter than Slow Period.
- Slow Period
Lookback in bars for the slower EMA. The MACD line is the fast EMA minus this slow EMA.
- Signal Period
Lookback for the EMA of the MACD line that forms the signal line.
- Direction
- Trigger
- data_in
If connected, MACD is computed on the connected series. If unconnected, it is computed on the close price of the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where the configured Direction and Trigger condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The MACD line, signal line, and histogram are drawn as a sub-panel. Any input that accepts a Series receives the MACD line.
Formulas
MACD line = EMA(close, fast) - EMA(close, slow) Signal line = EMA(MACD line, signal period) Histogram = MACD line - Signal line
signal[t] = 1 when MACD[t] > Signal[t] AND MACD[t-1] <= Signal[t-1], else 0
signal[t] = 1 when MACD[t] < Signal[t] AND MACD[t-1] >= Signal[t-1], else 0
Bullish: signal[t] = 1 while MACD[t] > Signal[t] Bearish: signal[t] = 1 while MACD[t] < Signal[t]
Stochastic
The Stochastic node computes the Stochastic Oscillator, a momentum measure bounded between 0 and 100 that locates the close within its recent high-low range. It produces a smoothed %K line and a %D signal line, and emits a signal from %K/%D crossovers that occur inside the overbought or oversold zone.
Parameters
- %K Period
Lookback in bars for the highest high and lowest low that define the range. Shorter periods produce a faster, noisier oscillator.
- Slowing
Smoothing applied to the raw %K to form the slow %K line. A value of 1 leaves the raw %K unsmoothed.
- %D Period
Smoothing applied to the slow %K to form the %D signal line. A value of 1 makes %D equal to %K.
- Oversold
The lower threshold. Must stay below Overbought. Drives the bullish condition.
- Overbought
The upper threshold. Must stay above Oversold. Drives the bearish condition.
- Direction
- data_in
If connected, the connected series replaces the close used in the calculation; the high and low still come from the strategy's ticker. If unconnected, the ticker's high, low, and close are used.
Outputs
- signal — Signal. Activates on bars where the configured Direction crossover occurs inside the matching zone. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The %K and %D lines on a 0 to 100 scale, drawn as a sub-panel oscillator. Any input that accepts a Series receives the %K line.
Formulas
fast %K = 100 * (close - lowest low) / (highest high - lowest low) over the %K period
%K = simple moving average of fast %K over Slowing %D = simple moving average of %K over the %D period
signal[t] = 1 when %K[t] > %D[t] AND %K[t-1] <= %D[t-1] AND %D[t] < oversold, else 0
signal[t] = 1 when %K[t] < %D[t] AND %K[t-1] >= %D[t-1] AND %D[t] > overbought, else 0
CCI
The CCI node computes the Commodity Channel Index, an unbounded momentum oscillator that measures the typical price's distance from its moving average in units of mean deviation. It emits a signal from overbought and oversold threshold conditions, with a choice of edge-triggered or sustained activation.
Parameters
- Period
Lookback in bars for the moving average of typical price and the mean deviation. Shorter periods produce a faster, noisier oscillator.
- Constant
The scaling factor in the denominator. The conventional 0.015 places roughly 70 to 80 percent of values within the plus or minus 100 band; a smaller constant widens the range of values, a larger one compresses it.
- Oversold
The lower threshold. Must stay below Overbought. Drives the bullish condition.
- Overbought
The upper threshold. Must stay above Oversold. Drives the bearish condition.
- Direction
- Trigger
- data_in
If connected, CCI is computed on the connected series in place of typical price. If unconnected, typical price (the average of high, low, and close) of the strategy's ticker is used.
Outputs
- signal — Signal. Activates on bars where the configured Direction and Trigger condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The CCI line, drawn as a sub-panel oscillator. Any input that accepts a Series receives this line.
Formulas
typical price = (high + low + close) / 3 CCI = (typical price - SMA of typical price) / (constant * mean deviation)
mean of |typical price - SMA of typical price| over the period
signal[t] = 1 when CCI[t] > oversold AND CCI[t-1] <= oversold, else 0
signal[t] = 1 when CCI[t] < overbought AND CCI[t-1] >= overbought, else 0
Bullish: signal[t] = 1 while CCI[t] <= oversold Bearish: signal[t] = 1 while CCI[t] >= overbought
Williams %R
The Williams %R node computes Williams Percent Range, a momentum oscillator on an inverted 0 to -100 scale that locates the close within its recent high-low range. A value near 0 sits at the top of the range and a value near -100 at the bottom. It emits a signal from overbought and oversold threshold conditions, with a choice of edge-triggered or sustained activation.
Parameters
- Period
Lookback in bars for the highest high and lowest low that define the range. Shorter periods produce a faster, noisier oscillator.
- Oversold
The lower threshold on the inverted scale. Must stay below Overbought. Drives the bullish condition.
- Overbought
The upper threshold on the inverted scale. Must stay above Oversold. Drives the bearish condition.
- Direction
- Trigger
Outputs
- signal — Signal. Activates on bars where the configured Direction and Trigger condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The %R line on a 0 to -100 scale, drawn as a sub-panel oscillator. Any input that accepts a Series receives this line.
Formulas
%R = (highest high - close) / (highest high - lowest low) * -100 over the period
signal[t] = 1 when %R[t] > oversold AND %R[t-1] <= oversold, else 0
signal[t] = 1 when %R[t] < overbought AND %R[t-1] >= overbought, else 0
Bullish: signal[t] = 1 while %R[t] < oversold Bearish: signal[t] = 1 while %R[t] > overbought
Stochastic RSI
The Stochastic RSI node applies the Stochastic Oscillator formula to RSI values rather than price, producing a faster, more sensitive momentum measure bounded between 0 and 100. It produces a smoothed %K line and a %D signal line, and emits a signal from %K/%D crossovers inside the overbought or oversold zone, or from sustained zone occupancy.
Parameters
- RSI Length
Lookback in bars for the underlying RSI that the Stochastic formula is applied to.
- Stochastic Length
Lookback in bars for the highest and lowest RSI used to normalize RSI into the 0 to 100 range.
- %K Smoothing
Smoothing applied to the raw Stochastic RSI to form the %K line. A value of 1 leaves the raw line unsmoothed.
- %D Smoothing
Smoothing applied to %K to form the %D signal line. A value of 1 makes %D equal to %K.
- Oversold
The lower threshold. Must stay below Overbought. Drives the bullish condition.
- Overbought
The upper threshold. Must stay above Oversold. Drives the bearish condition.
- Direction
- Trigger
- data_in
If connected, the underlying RSI is computed on the connected series. If unconnected, it is computed on the close price of the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where the configured Direction and Trigger condition holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The %K and %D lines on a 0 to 100 scale, drawn as a sub-panel oscillator. Any input that accepts a Series receives the %K line.
Formulas
RSI = Relative Strength Index over RSI Length (Wilder's smoothing) raw = 100 * (RSI - lowest RSI) / (highest RSI - lowest RSI) over Stochastic Length
%K = simple moving average of raw over %K Smoothing %D = simple moving average of %K over %D Smoothing
signal[t] = 1 when %K[t] > %D[t] AND %K[t-1] <= %D[t-1] AND %K[t] < oversold, else 0
signal[t] = 1 when %K[t] < %D[t] AND %K[t-1] >= %D[t-1] AND %K[t] > overbought, else 0
Bullish: signal[t] = 1 while %K[t] < oversold Bearish: signal[t] = 1 while %K[t] > overbought
Bollinger Bands
The Bollinger Bands node computes a simple moving average and two bands set a number of standard deviations above and below it. It emits a signal from price breaking through the selected band.
Parameters
- Period
Lookback in bars for both the moving average and the standard deviation.
- StdDev Up
Standard-deviation multiplier for the upper band. Larger values push the upper band further from the average.
- StdDev Down
Standard-deviation multiplier for the lower band. Larger values push the lower band further from the average.
- Band Side
- Trigger
- Direction
- data_in
If connected, the bands are computed on the connected series. If unconnected, computed on the close price of the strategy's ticker.
Outputs
- signal — Signal. Activates per the Trigger and Band Side selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The three bands drawn as price overlays. The upper, middle, and lower lines are each available by name on the output handle.
Formulas
middle = SMA(source, period) upper = middle + StdDev Up * stdev(source, period) lower = middle - StdDev Down * stdev(source, period) where stdev is the population standard deviation (divides by N)
Upper side: signal[t] = 1 when source[t] > upper[t] AND source[t-1] <= upper[t-1] Lower side: signal[t] = 1 when source[t] < lower[t] AND source[t-1] >= lower[t-1]
Upper side: signal[t] = 1 while source[t] > upper[t] Lower side: signal[t] = 1 while source[t] < lower[t]
Donchian Channels
The Donchian Channels node plots the highest high and lowest low over a lookback window with a midline between them. It emits a signal from price breaking the prior bar's channel.
Parameters
- Period
Lookback in bars for the highest high and lowest low.
- Band Side
- Trigger
- Direction
- data_in
If connected, the channels are the rolling max and min of the connected series and signals compare that series to its own channels. If unconnected, the upper channel is the highest High, the lower channel the lowest Low, and the close is compared against them.
Outputs
- signal — Signal. Activates per the Trigger and Band Side selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The three channel lines drawn as price overlays. The upper, middle, and lower lines are each available by name on the output handle.
Formulas
upper = highest High over the period lower = lowest Low over the period middle = (upper + lower) / 2
signal[t] = 1 when close[t] > upper[t-1] AND close[t-1] <= upper[t-2] The channel is compared one bar back because the current bar's high/low are inside the current channel.
Keltner Channels
The Keltner Channels node plots an EMA centerline with bands set a multiple of the Average True Range above and below it. It emits a signal from price breaking through the selected band.
Parameters
- EMA Period
Lookback in bars for the EMA centerline.
- ATR Period
Wilder smoothing length for the Average True Range that sets the band width. Kept separate from the EMA period.
- Multiplier
The number of ATRs each band sits away from the centerline. Larger values widen the channel.
- Band Side
- Trigger
- Direction
- data_in
If connected, the connected series replaces the close for the EMA centerline. The ATR always uses the ticker's High, Low, and Close. If unconnected, the centerline uses the close price.
Outputs
- signal — Signal. Activates per the Trigger and Band Side selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The three channel lines drawn as price overlays. The upper, middle, and lower lines are each available by name on the output handle.
Formulas
middle = EMA(source, EMA period) upper = middle + Multiplier * ATR(ATR period) lower = middle - Multiplier * ATR(ATR period) where ATR is Wilder's average true range
signal[t] = 1 when close[t] > upper[t] AND close[t-1] <= upper[t-1]
ATR (Average True Range)
The ATR node measures the average size of each bar's range. Its output line is the ATR scaled by a multiplier, and it emits a signal from that value relative to a threshold.
Parameters
- Period
Lookback in bars for the smoothing applied to True Range.
- Multiplier
Scale factor applied to the smoothed ATR. The output line and the threshold comparison both use this scaled value.
- Smoothing
- Threshold
The level the scaled ATR is compared against to produce the signal.
- Trigger
- Direction
- data_in
If connected, the connected series replaces the close in the True Range calculation. The High and Low always come from the ticker. If unconnected, the ticker's High, Low, and Close are used.
Outputs
- signal — Signal. Activates per the Direction and Trigger against the threshold. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The scaled ATR (ATR times Multiplier), drawn on its own subchart. Downstream Series inputs (such as Stop Loss or Risk Per Trade) consume this value directly.
Formulas
TR[t] = max(high[t] - low[t], |high[t] - close[t-1]|, |low[t] - close[t-1]|)
values[t] = Multiplier * smoothing(TR, period)
Bullish: signal[t] = 1 when values[t] > threshold AND values[t-1] <= threshold Bearish: signal[t] = 1 when values[t] < threshold AND values[t-1] >= threshold
Volatility Regime
The Volatility Regime node classifies volatility into a regime score and emits a signal when the score falls in the selected regime. By default it measures volatility itself as ATR as a percent of price (ATR divided by close, times 100). Wiring a series into its input overrides the internal measure — the node then classifies that series instead.
Parameters
- ATR Period
Period of the internal ATR used when nothing is wired into the input. Ignored when a series is connected.
- Lookback Period
Rolling window used to rank or average the volatility measure when scoring the current bar.
- Threshold Method
- High Threshold
Upper regime cutoff, interpreted per the Threshold Method.
- Low Threshold
Lower regime cutoff, interpreted per the Threshold Method.
- Vol Mode
- data_in
Optional override. Wire in a volatility measure such as a Bollinger band width, standard deviation, or any numeric series to classify it in place of the internal ATR percent of price.
Outputs
- signal — Signal. Activates on bars matching the selected Vol Mode. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The regime score, drawn on its own subchart.
Formulas
Default (nothing wired): measure[t] = ATR(ATR Period)[t] / close[t] * 100 Wired: measure[t] = input[t]
Percentile: score[t] = percentile rank of measure[t] within the last (lookback) values, times 100 Mean: score[t] = measure[t] / rolling mean of measure over (lookback) Fixed: score[t] = measure[t]
High Vol: signal[t] = 1 while score[t] >= High Threshold Low Vol: signal[t] = 1 while score[t] <= Low Threshold Expansion: signal[t] = 1 while score[t] > score[t-1] Contraction: signal[t] = 1 while score[t] < score[t-1] Extreme: signal[t] = 1 while score[t] >= High Threshold OR score[t] <= Low Threshold
Pivot Points
The Pivot Points node computes support and resistance levels from a prior period's open, high, low, and close, holding them constant across the current period. It emits a signal from price relative to one selected level.
Parameters
- Method
- Timeframe
- Level
Which computed level drives the signal. The available levels depend on the Method (for example P, R1 through R3 and S1 through S3 for Traditional; P, TC, BC for CPR).
- Trigger
- Direction
- Pivot Levels
How many R/S pairs to compute and plot. Clamped to the maximum the Method supports.
- Rounding
Decimal places the computed level values are rounded to.
Outputs
- signal — Signal. Activates per the Level, Direction, and Trigger selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The computed level lines drawn as price overlays. Each level (P, R1, S1, TC, BC, and so on for the Method) is available by name on the output handle.
Formulas
P = (high + low + close) / 3 (from the prior period) R1 = 2*P - low S1 = 2*P - high R2 = P + (high - low) S2 = P - (high - low) R3 = P + 2*(high - low) S3 = P - 2*(high - low)
Bullish: signal[t] = 1 when close[t] > level[t] AND close[t-1] <= level[t-1] Bearish: signal[t] = 1 when close[t] < level[t] AND close[t-1] >= level[t-1]
Support & Resistance
The Support & Resistance node detects price levels that have been touched repeatedly, ranks them by how many times price bounced off them, and emits a signal from price interacting with the strongest levels.
Parameters
- Trigger Type
- Min Bounces
Minimum number of separate touches a price level needs before it is kept as a level.
- Bounce Tolerance
How close, as a percent of the level price, a bar must come to count as a touch of that level.
- Lookback Period
Window of recent bars searched for the pivot highs and lows that seed candidate levels.
- Levels
Maximum number of levels to keep, taken in order of strength.
- Level Strength Threshold
Minimum strength (bounce count) a level must reach to be kept.
- Rounding
Decimal places the level prices are rounded to.
Outputs
- signal — Signal. Activates per the Trigger Type; Level Detection never activates. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The kept level lines drawn as price overlays, ordered by strength (level_1, level_2, and so on), each available by name on the output handle.
Formulas
strength = number of separate touches within Bounce Tolerance of the level A touch counts separately from the previous one once enough bars have passed between them. Levels are kept when strength >= Min Bounces and strength >= Level Strength Threshold, then ranked by strength.
Resistance level: signal[t] = 1 when close[t] > level AND close[t-1] <= level Support level: signal[t] = 1 when close[t] < level AND close[t-1] >= level
Swing Pivots
The Swing Pivots node detects swing highs and lows, where a bar's high or low is the most extreme within a window on both sides. It emits a signal once each pivot is confirmed.
Parameters
- Mode
- Window
Number of bars on each side of a pivot that must be lower (for a swing high) or higher (for a swing low) than the pivot bar.
- Confirm Bars
Extra bars to wait after the window closes before the pivot is confirmed. Added to the window delay so the signal carries no look-ahead.
Outputs
- signal — Signal. Activates on the bar a pivot is confirmed (Window plus Confirm Bars after the pivot bar). Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The confirmed pivot price, carried on the confirmation bar.
Formulas
Swing high at bar i: high[i] is strictly greater than every high within Window bars on each side Swing low at bar i: low[i] is strictly lower than every low within Window bars on each side
signal fires at bar i + Window + Confirm Bars, the earliest bar at which the pivot is known without using future data
ZigZag
The ZigZag node connects significant swing turns, filtering out moves smaller than a threshold. It draws a line between confirmed turns and emits a signal on the bar each turn is confirmed.
Parameters
- Threshold Mode
- Threshold Value
The size of move required to confirm a reversal: a percent in Percent mode, or an ATR multiplier in ATR mode.
- ATR Period
Lookback for the ATR used as the threshold in ATR mode. Ignored in Percent mode.
- Pivot Source
- Mode
Outputs
- signal — Signal. Activates on the bar a turn is confirmed (when price has reversed past the threshold), not on the pivot bar itself, so it carries no look-ahead. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The ZigZag line, interpolated between confirmed turns, drawn as a price overlay.
Formulas
Percent: threshold[t] = close[t] * Threshold Value / 100 ATR: threshold[t] = Threshold Value * ATR(ATR Period)
After a swing high, a low turn is confirmed once price rises from the running low by at least the threshold; after a swing low, a high turn is confirmed once price falls from the running high by at least the threshold. The chart marks the turn at the pivot bar; the signal fires on the confirmation bar.
Volume
The Volume node exposes trading volume in raw or moving-average-smoothed form and emits a signal when that volume moves past a threshold. Its values output can also feed other nodes that accept a numeric series.
Parameters
- Volume Type
- MA Type
- Period
Lookback in bars for the volume moving average. Only used when Volume Type is Smoothed.
- Threshold
The volume level the processed series is compared against to produce the signal.
- Trigger
- Direction
- data_in
If connected, the volume series is taken from the connected input. If unconnected, the ticker's bar volume is used.
Outputs
- signal — Signal. Activates per the Trigger and Direction selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The processed volume series, raw or smoothed. Any input that accepts a Series receives this line.
Formulas
Total: volume[t] Smoothed: SMA(volume, period) or EMA(volume, period)
Bullish: signal[t] = 1 when volume[t] > threshold AND volume[t-1] <= threshold Bearish: signal[t] = 1 when volume[t] < threshold AND volume[t-1] >= threshold
Bullish: signal[t] = 1 while volume[t] > threshold Bearish: signal[t] = 1 while volume[t] < threshold
Relative Volume
The Relative Volume (RVOL) node computes the ratio of current volume to its lookback baseline and emits a signal when that ratio reaches a high- or low-activity threshold.
Parameters
- Lookback Period
Number of bars used to compute the baseline average volume.
- MA Type
- Mode
- Activity Filter
- High Threshold
RVOL level for high-activity signals. A value of 1.5 means current volume is 150% of the baseline. Must be greater than the Low Threshold.
- Low Threshold
RVOL level for low-activity signals. A value of 0.5 means current volume is 50% of the baseline.
- Trigger
- data_in
If connected, the volume series is taken from the connected input. If unconnected, the ticker's bar volume is used.
Outputs
- signal — Signal. Activates per the Activity Filter and Trigger selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. Three lines are drawn: the RVOL ratio, the baseline, and the raw volume. Any input that accepts a Series receives the RVOL ratio.
Formulas
baseline = MA(volume, lookback) (Default mode) baseline = mean of volume at the same time of day over the last `lookback` days (ToD mode) RVOL[t] = volume[t] / baseline[t]
High: signal[t] = 1 when RVOL[t] >= high AND RVOL[t-1] < high Low: signal[t] = 1 when RVOL[t] <= low AND RVOL[t-1] > low
High: signal[t] = 1 while RVOL[t] >= high Low: signal[t] = 1 while RVOL[t] <= low
OBV
The OBV (On-Balance Volume) node accumulates volume as a running total, adding it on up bars and subtracting it on down bars. It signals from the OBV line crossing its moving average, or from the OBV line's direction.
Parameters
- MA Length
Lookback in bars for the moving average of OBV. When set to 0 the moving average is disabled and the signal comes from the OBV line's direction instead of an MA cross.
- MA Type
- Direction
- data_in
If connected, the connected series replaces close for the up/down direction test; volume still comes from the ticker's bars. If unconnected, close is used.
Outputs
- signal — Signal. Activates per the MA Length and Direction selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The OBV line, plus its moving average when MA Length is greater than 0. Any input that accepts a Series receives the OBV line by default.
Formulas
OBV[t] = OBV[t-1] + volume[t] when close[t] > close[t-1] OBV[t] = OBV[t-1] - volume[t] when close[t] < close[t-1] OBV[t] = OBV[t-1] when close[t] = close[t-1] (bar 0 is seeded with the first bar's volume)
Bullish: signal[t] = 1 when OBV[t] > MA[t] AND OBV[t-1] <= MA[t-1] Bearish: signal[t] = 1 when OBV[t] < MA[t] AND OBV[t-1] >= MA[t-1]
Bullish: signal[t] = 1 when OBV[t] > OBV[t-1] Bearish: signal[t] = 1 when OBV[t] < OBV[t-1]
MFI
The MFI (Money Flow Index) node is a volume-weighted oscillator bounded between 0 and 100. It weights typical-price moves by volume and signals from the result crossing or sitting beyond the oversold and overbought levels.
Parameters
- Period
Lookback in bars for summing positive and negative money flow.
- Oversold
Lower threshold. Must be less than Overbought.
- Overbought
Upper threshold. Must be greater than Oversold.
- Trigger
- Direction
- data_in
If connected, the connected series replaces the typical price as the price component; volume still comes from the ticker's bars. If unconnected, typical price (high + low + close) / 3 is used.
Outputs
- signal — Signal. Activates per the Trigger and Direction selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The MFI line, from 0 to 100. Any input that accepts a Series receives this line.
Formulas
typical price = (high + low + close) / 3 raw money flow = typical price * volume positive flow counts bars where typical price rose; negative flow where it fell money ratio = sum(positive flow, period) / sum(negative flow, period) MFI = 100 - 100 / (1 + money ratio)
Bullish: signal[t] = 1 when MFI[t] > oversold AND MFI[t-1] <= oversold Bearish: signal[t] = 1 when MFI[t] < overbought AND MFI[t-1] >= overbought
Bullish: signal[t] = 1 while MFI[t] < oversold Bearish: signal[t] = 1 while MFI[t] > overbought
CMF
The CMF (Chaikin Money Flow) node is a volume-weighted average of where price closes within its high-low range over a lookback window. It oscillates around zero and signals from crossing a threshold buffer around the zero line.
Parameters
- Period
Lookback in bars for summing money flow volume and volume.
- Threshold
Buffer around the zero line. Signals fire at plus and minus this value instead of exactly zero. A value of 0 makes it a pure zero-line crossover.
- Trigger
- Direction
Outputs
- signal — Signal. Activates per the Trigger and Direction selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The CMF line, oscillating between -1 and +1. Any input that accepts a Series receives this line.
Formulas
money flow multiplier (MFM) = (2 * close - low - high) / (high - low) money flow volume (MFV) = MFM * volume CMF = sum(MFV, period) / sum(volume, period) (bars where high = low contribute 0 to money flow)
Bullish: signal[t] = 1 when CMF[t] > +threshold AND CMF[t-1] <= +threshold Bearish: signal[t] = 1 when CMF[t] < -threshold AND CMF[t-1] >= -threshold
Bullish: signal[t] = 1 while CMF[t] > +threshold Bearish: signal[t] = 1 while CMF[t] < -threshold
Volume Profile
The Volume Profile node aggregates volume across price levels over a rolling window and emits the Point of Control and the Value Area boundaries as price overlay lines. It signals from price crossing the selected level.
Parameters
- Lookback
Number of bars in the rolling window aggregated into the profile, recomputed each bar.
- Rows
Number of price bins the window's range is divided into. More rows give finer price granularity.
- VA %
Percentage of total window volume that defines the Value Area, expanded outward from the Point of Control.
- Signal Level
- Trigger
- Direction
Outputs
- signal — Signal. Activates per the Signal Level, Trigger, and Direction selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. Three price-overlay lines: POC, VAH, and VAL. Any input that accepts a Series receives the POC by default; the line selector on the output handle lets you pick VAH or VAL.
Formulas
For each bar in the lookback window, its volume is spread evenly across the price bins its high-low range covers. POC = the bin with the most accumulated volume. The Value Area expands outward from the POC, each step adding the adjacent bin with more volume, until VA % of total volume is captured. VAH and VAL are the upper and lower edges of that area.
level = POC, VAH, or VAL per Signal Level Bullish: signal[t] = 1 when close[t] > level[t] AND close[t-1] <= level[t-1] Bearish: signal[t] = 1 when close[t] < level[t] AND close[t-1] >= level[t-1]
Bullish: signal[t] = 1 while close[t] > level[t] Bearish: signal[t] = 1 while close[t] < level[t]
VWAP
The VWAP (Volume Weighted Average Price) node computes the volume-weighted average of typical price over an anchor window. It signals from price crossing the VWAP line, or from the VWAP line crossing its moving average.
Parameters
- Anchor
- Window
Number of trailing bars in the rolling average. Only used when Anchor is Rolling.
- MA Length
Lookback in bars for a moving average of the VWAP line. When set to 0 the moving average is disabled and the signal comes from close crossing VWAP instead of a VWAP-vs-MA cross.
- MA Type
- Direction
- data_in
If connected, the connected series replaces typical price as the price component; volume still comes from the ticker's bars. If unconnected, typical price (high + low + close) / 3 is used.
Outputs
- signal — Signal. Activates per the MA Length and Direction selection. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The VWAP line, plus its moving average when MA Length is greater than 0. Any input that accepts a Series receives the VWAP line by default.
Formulas
typical price = (high + low + close) / 3 Session: VWAP = cumulative(tp * volume) / cumulative(volume), reset each day Rolling: VWAP = sum(tp * volume, window) / sum(volume, window) Anchored: VWAP = cumulative(tp * volume) / cumulative(volume) from the start
Bullish: signal[t] = 1 when close[t] > VWAP[t] AND close[t-1] <= VWAP[t-1] Bearish: signal[t] = 1 when close[t] < VWAP[t] AND close[t-1] >= VWAP[t-1]
Bullish: signal[t] = 1 when VWAP[t] > MA[t] AND VWAP[t-1] <= MA[t-1] Bearish: signal[t] = 1 when VWAP[t] < MA[t] AND VWAP[t-1] >= MA[t-1]
Price
The Price node emits a chosen price field (or a connected series) as a numeric series for downstream nodes, with an optional backward lag. Its signal activates on any bar where the series changes from the prior bar.
Parameters
- Price Source
- Lag / Shift
Number of bars to shift the series backward, so bar t carries the value from bar t minus Lag. Negative values are rejected because they would read future bars.
Outputs
- values — Series. The selected price series after any lag. Any input that accepts a Series receives this; the chart does not draw a separate overlay for it.
- signal — Signal. Activates on bars where the series differs from the prior bar (price moved up or down). Any input that accepts a Signal reads this and reacts on bars where it's active.
Formulas
HL2[t] = (high[t] + low[t]) / 2 HLC3[t] = (high[t] + low[t] + close[t]) / 3 OHL4[t] = (open[t] + high[t] + low[t] + close[t]) / 4
VWAP[t] = sum(close[0..t] * volume[0..t]) / sum(volume[0..t])
signal[t] = 1 when source[t] != source[t-1], else 0
Candlestick
The Candlestick node detects classic candlestick patterns using relative classification: every size judgment (long body, small body, doji, shadow) is made against the bar's recent neighborhood rather than fixed ratios, and each pattern carries a trend role that the optional trend filter enforces. Its signal activates on bars where any selected pattern is detected, after the optional confirmation window.
Parameters
- Patterns
One or more patterns to detect. The signal activates when any selected pattern is detected on a bar. Patterns whose direction is excluded by the Direction setting are hidden from the list. Each pattern's exact condition and trend role is listed under Pattern conditions below.
- Confirm Bars
Bars of confirmation required after a pattern. With 0, the signal activates on the pattern bar. With N greater than 0, a bullish detection is confirmed only if the close N bars later breaks above the highest high of the confirmation window (a bearish detection, below the lowest low), and the signal is placed on that confirmation bar.
- Direction
Direction-less patterns (Doji, Spinning Top, Inside Bar) count as both bullish and bearish, so they activate under every Direction setting.
- Trend Filter
The gate applies each pattern's trend role: reversal patterns require the counter-trend (bullish reversals need a downtrend, bearish reversals an uptrend), continuation patterns require their own trend, and neutral patterns are never gated. While the moving averages are still forming, neither trend condition holds and gated patterns cannot activate.
- Body Avg Length
Bars in the exponential body average that decides long versus small bodies. Lower values react faster to volatility changes; higher values hold a steadier baseline.
- Doji Body %
Maximum body size, as a percent of the bar's own range, for the bar to count as a doji body.
- Shadow %
Minimum shadow size, as a percent of the body, for a shadow to count as present at all. Below this the shadow side is treated as bare (used by Marubozu and the hammer family's "no opposite shadow" conditions).
- Dominance Factor
How many times the body a shadow must be to dominate the bar. Used by the hammer family (Hammer, Hanging Man, Inverted Hammer, Shooting Star).
- data_in
If connected, the series replaces the close price for detection, trend context, and confirmation. Open, high, and low always come from the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where a selected pattern is detected, passes its trend gate, and is confirmed. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. Pattern strength: the count of selected patterns detected on each bar.
Classification
All pattern conditions are built from these shared definitions.
body[t] = abs(close[t] - open[t]) upperShadow[t] = high[t] - max(open[t], close[t]) lowerShadow[t] = min(open[t], close[t]) - low[t] range[t] = high[t] - low[t] white body = close[t] > open[t] black body = open[t] > close[t]
bodyAvg[t] = EMA(body, Body Avg Length) (seeded with the SMA of the first N bodies) long body : body[t] > bodyAvg[t] small body : body[t] < bodyAvg[t]
doji body : range[t] > 0 AND body[t] <= range[t] * DojiBodyPct / 100
has shadow : shadow[t] > ShadowPct / 100 * body[t] dominant shadow : shadow[t] >= DominanceFactor * body[t]
Pattern conditions
Each pattern lists its trend role in parentheses: bullish reversal and bearish reversal require the counter-trend when gated; reversal patterns that detect both directions gate each side against its counter-trend; continuation patterns require their own trend; neutral patterns are never gated.
- Bullish Engulfing (bullish reversal) — prior bar black with a small body; current bar white with a long body; the body overtakes the prior body: close at or above the prior open and open at or below the prior close, with at least one side strict.
- Bearish Engulfing (bearish reversal) — mirror of Bullish Engulfing: prior white small body, current black long body, body overtake downward.
- Hammer (bullish reversal) — small non-zero body sitting in the upper half of the range (body bottom above the bar midpoint), dominant lower shadow, no meaningful upper shadow.
- Hanging Man (bearish reversal) — same geometry as Hammer; the uptrend context is what distinguishes it.
- Inverted Hammer (bullish reversal) — small non-zero body in the lower half of the range, dominant upper shadow, no meaningful lower shadow.
- Shooting Star (bearish reversal) — same geometry as Inverted Hammer; the uptrend context distinguishes it.
- Doji (neutral) — doji body with balanced shadows: the shadows are equal, or each is less than twice the other.
- Marubozu (continuation) — long body with no meaningful shadow on either side. White is bullish, black bearish.
- Spinning Top (neutral) — small body that is not a doji body, with both shadows longer than the body.
- Piercing (bullish reversal) — prior black long body; current white bar opens at or below the prior low and closes above the prior body midpoint but below the prior open.
- Dark Cloud Cover (bearish reversal) — mirror of Piercing: prior white long body; current black bar opens at or above the prior high and closes below the prior body midpoint but above the prior open.
- Harami (reversal, both directions) — prior long body (the mother); current small body whose whole range (high to low) sits inside the mother's body. Black mother is bullish, white mother bearish; the baby's color is not constrained.
- Harami Cross (reversal, both directions) — Harami whose baby bar is a doji body.
- Inside Bar (neutral) — high below the prior high and low above the prior low (strict on both sides).
- Morning Star (bullish reversal) — black long body, then a small body whose body gaps below the first body, then a white long body closing above the first body's midpoint.
- Evening Star (bearish reversal) — mirror of Morning Star with the star gapping above and the third bar black.
- Three Inside (reversal, both directions) — a Harami, then a confirming third bar: white closing above the prior close (up) or black closing below it (down).
- Three Outside (reversal, both directions) — an Engulfing, then the same confirming third bar as Three Inside.
- Three Line Strike (continuation, both directions) — three white bodies with rising closes, then a black strike bar opening at or above the third close and closing below the first bar's open (mirrored for the bearish variant). The failed strike continues the trend.
- Abandoned Baby (reversal, both directions) — long first body, then a doji whose full range gaps away from it, then an opposite-color bar gapping away from the doji in the reversal direction.
- Gap Side-by-Side White (continuation) — two white bars with bodies within 30% of the body average of each other and opens within 20%, both holding a body gap above the bar before the pair.
- Separating Lines (continuation, both directions) — counter-trend bar, then a long bar of the opposite color re-opening at the same price (within 5% of the body average) and resuming the move.
- Tri-Star (reversal, both directions) — three consecutive doji bodies with the middle body gapped above (bearish) or below (bullish) both neighbors' bodies.
- Breakaway (reversal, both directions) — five bars: long first body in the trend direction, a same-color body gapping further, two more closes extending the move, then a long opposite-color bar closing back at or beyond the body gap.
- On Neck (continuation, bearish) — prior black long body; white bar opens below the prior low and closes at the prior low (within 5% of the body average).
- In Neck (continuation, bearish) — prior black long body; white bar opens below the prior low and closes at or slightly above the prior close (by at most 10% of the prior body).
- Homing Pigeon (bullish reversal) — prior black long body; current small black body contained inside the prior body.
Formulas
uptrend[t] : close[t] > SMA50[t] downtrend[t] : close[t] < SMA50[t]
uptrend[t] : close[t] > SMA50[t] AND SMA50[t] > SMA200[t] downtrend[t] : close[t] < SMA50[t] AND SMA50[t] < SMA200[t]
white body AND long body AND prior black body AND prior small body AND close[t] >= open[t-1] AND open[t] <= close[t-1] AND (close[t] > open[t-1] OR open[t] < close[t-1])
confirmed[t+N] = pattern[t] AND close[t+N] > max(high[t+1 .. t+N])
Bars
The Bars node detects price-bar patterns (rejection tails, range structure, gaps, breakouts, and volume events) using relative classification: size judgments are made against the bar's recent neighborhood rather than fixed ratios, and each pattern carries a trend role that the optional trend filter enforces. Its signal activates on bars where any selected pattern is detected, after the optional confirmation window.
Parameters
- Patterns
One or more patterns to detect. The signal activates when any selected pattern is detected on a bar. Patterns whose direction is excluded by the Direction setting are hidden from the list. Each pattern's exact condition and trend role is listed under Pattern conditions below.
- Confirm Bars
Bars of confirmation required after a pattern. With 0, the signal activates on the pattern bar. With N greater than 0, a bullish detection is confirmed only if the close N bars later breaks above the highest high of the confirmation window (a bearish detection, below the lowest low), and the signal is placed on that confirmation bar.
- Direction
Hammer is bullish-only and Inverted Hammer bearish-only; direction-less patterns (NR4, NR7, Inside Bar, IBID, Outside Bar, Climax Bar, Volume Dry-Up) count as both bullish and bearish, so they activate under every Direction setting.
- Trend Filter
The gate applies each pattern's trend role: reversal patterns require the counter-trend, continuation patterns require their own trend, Breakaway Gap is directional but never gated (it starts a new move), and neutral patterns are never gated. While the moving averages are still forming, neither trend condition holds and gated patterns cannot activate.
- Body Avg Length
Bars in the exponential body average that decides long versus small bodies and the pin bar's tail prominence (Pin Bar, Hammer, Inverted Hammer, Engulfing Bar, Key Reversal).
- Shadow %
Minimum shadow size, as a percent of the body, for a shadow to count as present at all (used by the hammer family's "no opposite shadow" conditions).
- Dominance Factor
How many times the body a rejection tail must be to dominate the bar (Pin Bar, Hammer, Inverted Hammer).
- Range Factor
How many times the range average a bar's range must be to count as wide range (Wide-Range Bar, Climax Bar, NR7 + WRB).
- Range Avg Length
Bars in the exponential range average behind the wide-range classification and the gap significance checks.
- data_in
If connected, the series replaces the close price for detection, trend context, and confirmation. Open, high, low, and volume always come from the strategy's ticker.
Outputs
- signal — Signal. Activates on bars where a selected pattern is detected, passes its trend gate, and is confirmed. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. Pattern strength: the count of selected patterns detected on each bar.
Classification
Size-classified patterns are built from these shared definitions. Structural patterns (NR4, NR7, Inside Bar, IBID, Outside Bar, 2-Bar Breakout, IIB, 1-2-3 Pullback) use only rank and containment comparisons and are unaffected by the classification parameters.
body[t] = abs(close[t] - open[t]) upperShadow[t] = high[t] - max(open[t], close[t]) lowerShadow[t] = min(open[t], close[t]) - low[t] range[t] = high[t] - low[t] white body = close[t] > open[t] black body = open[t] > close[t]
bodyAvg[t] = EMA(body, Body Avg Length) (seeded with the SMA of the first N values) rangeAvg[t] = EMA(range, Range Avg Length) (same seeding) long body : body[t] > bodyAvg[t] small body : body[t] < bodyAvg[t] wide range : range[t] > RangeFactor * rangeAvg[t] dominant tail: shadow[t] >= DominanceFactor * body[t]
Pattern conditions
Each pattern lists its trend role in parentheses: reversal patterns gate each direction against its counter-trend, continuation patterns require their own trend, directional patterns carry a direction but are never gated, and neutral patterns are never gated.
- Pin Bar (reversal, both directions) — small body, a rejection tail at least Dominance Factor times the body AND larger than the body average (a micro-bar's tail does not qualify), with the close pinned to the far quarter of the range. White with a lower tail is bullish; black with an upper tail bearish.
- Hammer (bullish reversal) — small non-zero body, dominant lower tail, no meaningful upper shadow, after a black bar.
- Inverted Hammer (bearish reversal) — small non-zero body, dominant upper tail, no meaningful lower shadow, after a white bar.
- Key Reversal Bar (reversal, both directions) — opens beyond the prior close in the move's direction, trades to a new extreme, then closes back through the prior close with a long body. Distinct from the Engulfing Bar: keyed on the open thrust and close reversal, not range containment.
- Wide-Range Bar (continuation, both directions) — wide range (per the classification above). White is bullish, black bearish; a zero-body wide bar carries no direction.
- NR4 (neutral) — the narrowest range of the last 4 bars (current included; ties qualify).
- NR7 (neutral) — the narrowest range of the last 7 bars (current included; ties qualify).
- Inside Bar (neutral) — high below the prior high and low above the prior low (strict on both sides).
- Inside Bar Inside Day (IBID) (neutral) — two consecutive inside bars.
- Outside Bar (neutral) — high above the prior high and low below the prior low (strict on both sides).
- Engulfing Bar (reversal, both directions) — full-range engulf (higher high and lower low) with a long body, closing against the prior bar's color.
- 2-Bar Breakout (continuation, both directions) — close above the prior high (bullish) or below the prior low (bearish).
- 3-Bar Inside-Inside-Break (IIB) (continuation, both directions) — four bars: a mother bar, two consecutively nested inside bars, then a close beyond the mother bar's high (bullish) or low (bearish).
- 1-2-3 Pullback (continuation, both directions) — two consecutive lower lows resolved by a close above the first bar's high (bullish), or two higher highs resolved by a close below the first bar's low (bearish).
- NR7 + WRB Combo (continuation, both directions) — an NR7 bar followed by a wide-range bar; the expansion bar's color is the direction.
- Breakaway Gap (directional, ungated) — full-range gap (low above the prior high, or high below the prior low) larger than 1.5 times the range average, on volume above 1.2 times its 20-bar mean.
- Runaway Gap (continuation, both directions) — full-range gap larger than 0.5 times the range average, with the bar closing in the gap's direction (white for a gap up, black for a gap down).
- Climax Bar (neutral) — wide range on volume at least 1.5 times its 20-bar mean. An exhaustion marker for the bar's own direction.
- Volume Dry-Up (VDU) (neutral) — three consecutive bars with volume at or below half its 20-bar mean.
Formulas
uptrend[t] : close[t] > SMA50[t] downtrend[t] : close[t] < SMA50[t]
uptrend[t] : close[t] > SMA50[t] AND SMA50[t] > SMA200[t] downtrend[t] : close[t] < SMA50[t] AND SMA50[t] < SMA200[t]
small body AND lowerShadow[t] >= DominanceFactor * body[t] AND lowerShadow[t] > bodyAvg[t] AND white body AND close[t] >= low[t] + 0.75 * range[t]
confirmed[t+N] = pattern[t] AND close[t+N] > max(high[t+1 .. t+N])
Heikin Ashi
The Heikin Ashi node computes smoothed Heikin Ashi candles from the raw OHLC using a recursive formula, and activates a signal from the candle color (bullish when HA close is above HA open, bearish when below).
Parameters
- Direction
- Trigger
Outputs
- signal — Signal. Activates per Direction and Trigger. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The four Heikin Ashi lines (ha_open, ha_high, ha_low, ha_close). The chart draws them as a price overlay; an input that accepts a Series receives ha_close by default, and the line selector on the output handle picks any of the four.
Formulas
HA_Close[t] = (open[t] + high[t] + low[t] + close[t]) / 4 HA_Open[t] = (HA_Open[t-1] + HA_Close[t-1]) / 2 HA_High[t] = max(high[t], HA_Open[t], HA_Close[t]) HA_Low[t] = min(low[t], HA_Open[t], HA_Close[t]) First bar: HA_Open[0] = (open[0] + close[0]) / 2
State: signal[t] = 1 when HA_Close[t] > HA_Open[t] Cross: signal[t] = 1 when HA_Close[t] > HA_Open[t] AND HA_Close[t-1] < HA_Open[t-1]
Dividend
The Dividend node detects cash dividend payments on the strategy's stock, using the ex-dividend date from the data provider. Its signal activates on the ex-dividend bar, shiftable by an offset, and its values output carries the cash amount paid per share on the active bar. Stock only; crypto symbols carry no dividend data.
Parameters
- Direction
- Offset
Number of days between the ex-dividend date and the active bar. 0 activates on the ex-dividend bar itself, regardless of Direction. The ex-dividend date, and any offset target, each map to the first trading bar on or after that date.
Outputs
- signal — Signal. Activates on the bar matching the ex-dividend date shifted by the offset. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The dividend amount per share on the active (shifted) bar, 0 on every other bar. Any input that accepts a Series receives this.
Formulas
target[k] = ex_dividend_date[k] + Offset (Offset is negative for Days Before) signal[t] = 1 on the first bar with date >= target[k], else 0 values[t] = dividend_amount[k] on that active bar, else 0
Earnings Event
The Earnings Event node marks each fiscal reporting period for the strategy's stock, using the company's quarter-end date from the data provider. It keys off the fiscal quarter-end (the reporting period close), not the earnings announcement date, which the provider does not supply; a positive offset shifts the signal toward the usual announcement window a few weeks later. Stock only.
Earnings coverage is currently limited to major large-cap tickers and roughly the most recent three years. Outside that coverage the node stays inactive for the run — no signals fire and no error is raised.
Parameters
- Direction
- Offset
Number of days between the quarter-end and the active bar. 0 activates on the quarter-end bar itself, regardless of Direction. The quarter-end, and any offset target, each map to the first trading bar on or after that date.
Outputs
- signal — Signal. Activates on the bar matching the quarter-end shifted by the offset. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. 1.0 on active bars, 0.0 on every other bar.
Formulas
target[k] = quarter_end[k] + Offset (Offset is negative for Days Before) signal[t] = 1 on the first bar with date >= target[k], else 0
Split Event
The Split Event node detects stock split events on the strategy's stock and can filter them by direction. Its signal activates on the split's effective bar, and its values output carries the split ratio. Stock only; crypto symbols carry no split data.
Parameters
- Split Type
Outputs
- signal — Signal. Activates on the effective bar of a split that passes the Split Type filter. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The split ratio on active bars (2.0 for a 2:1 forward split, 0.5 for a 1:2 reverse split), 1.0 on every other bar.
Formulas
ratio[t] = split factor on the split bar, else 1.0 All Splits: signal[t] = 1 when ratio[t] != 1.0 Forward: signal[t] = 1 when ratio[t] >= 2.0 Reverse: signal[t] = 1 when ratio[t] <= 0.5
Buy
The Buy node places a buy order on bars where its incoming signal is active.
Parameters
- Direction
- Amount Type
- Amount Value
The number consumed by the Amount Type formula. Percentage types accept 0.1 to 100. Dollar and share types accept any positive number.
- Order Type
- Limit Price, Stop Price, Trail Type, Trail Value
Each is required only when the chosen Order Type uses it. The node configuration panel shows and hides these fields as Order Type changes.
Inputs
- in0 — Signal. Accepts one wire from a Signal-emitting source.
Outputs
- signal — Signal. Activates on bars where the input signal is active. When activated, the strategy engine places the trade per the node's sizing and order configuration.
Signal timing
A trade fills at the next bar's open price, not the bar where the signal activates. Signals that activate on the last bar of the data range are dropped because there is no next bar to fill on. This matches real exchange behavior: an order placed after a bar closes can only fill at the next available open.
Chain aggregation
When multiple Buy signals activate on the same ticker without an intervening Sell, the engine merges them into a single position record. The combined quantity, total cost, and weighted-average entry price are tracked together. The position stays open until a Sell closes it, at which point realized profit and loss is computed against the aggregate entry.
Sell
The Sell node places a sell order on bars where its incoming signal is active.
Parameters
- Direction
- Amount Type
- Amount Value
The number consumed by the Amount Type formula. Percentage types accept 0.1 to 100. Dollar and share types accept any positive number.
- Order Type
- Limit Price, Stop Price, Trail Type, Trail Value
Each is required only when the chosen Order Type uses it. The node configuration panel shows and hides these fields as Order Type changes.
Inputs
- in0 — Signal. Accepts one wire from a Signal-emitting source.
Outputs
- signal — Signal. Activates on bars where the input signal is active. When activated, the strategy engine places the trade per the node's sizing and order configuration.
Signal timing
A trade fills at the next bar's open price, not the bar where the signal activates. Signals that activate on the last bar of the data range are dropped because there is no next bar to fill on. This matches real exchange behavior: an order placed after a bar closes can only fill at the next available open. If an Exit Long signal activates while the strategy's minimum holding period has not yet elapsed, the engine waits until the minimum is met before exiting.
Aggregate exit
If a long position has been built up via multiple chained Buy signals, a single Exit Long Sell at % of Position equal to 100 closes the entire aggregated position in one trade record. Realized profit and loss is computed against the weighted-average entry price across the full chain.
Wait
The Wait node gates its incoming signal by a timing rule and emits a Signal to downstream nodes. It either delays activation by a fixed number of bars or latches active once its input first becomes active.
Parameters
- Wait Type
- Periods
The number of bars N that the output stays inactive before activating. The node configuration panel shows this field only when Wait Type is Fixed Periods.
Inputs
- in0 — Signal. Accepts one wire from a Signal-emitting source. Read only in Until Input True mode; ignored in Fixed Periods mode.
Outputs
- signal — Signal. In Fixed Periods mode it activates on the bar at index N (the bars before it are inactive) and stays active through the end of the range. In Until Input True mode it activates on the first bar where the input is active and stays active afterward.
And
The And node combines its signal inputs and activates only on bars where every input is active at once. It has no parameters.
Inputs
- in0, in1
Two input handles, each accepting a Signal from another node. The node reads the active state of both on every bar.
Outputs
- signal — Signal. Activates on bars where both inputs are active, and is inactive on any bar where either input is inactive. Any input that accepts a Signal reads this and reacts on bars where it's active.
Formula
signal[t] = 1 when in0[t] = 1 AND in1[t] = 1, else 0
Or
The Or node combines its signal inputs and activates on bars where at least one input is active. It has no parameters.
Inputs
- in0, in1
Two input handles, each accepting a Signal from another node. The node reads the active state of both on every bar. A single wired input passes through unchanged.
Outputs
- signal — Signal. Activates on bars where either input is active, and is inactive only on bars where every input is inactive. Any input that accepts a Signal reads this and reacts on bars where it's active.
Formula
signal[t] = 1 when in0[t] = 1 OR in1[t] = 1, else 0
Split
The Split node is a fan-out: it takes one input and passes it through to two outputs unchanged, so two downstream nodes can consume the same payload independently. It has no parameters.
Inputs
- in0
A single input handle. It accepts whatever the connected source emits, a Signal or a Series, and carries that payload through without modifying it.
Outputs
- out0, out1 — the input payload, duplicated. Both outputs carry the same data as the input, unchanged. A downstream node reading a Signal sees it active on the same bars the input was active; a downstream node reading a Series receives the identical series. The two outputs are independent connection points for the one payload.
Relation
The Relation node compares two numeric inputs with a relational operator. Its signal activates on bars where the comparison holds.
Parameters
- Relation
Inputs
- in0 (A), in1 (B)
A is the left operand and B is the right operand of the comparison. Both must be wired. On any bar where either value is missing, the comparison is inactive.
Outputs
- signal — Signal. Activates on bars where the configured comparison between A and B holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
Formula
signal[t] = 1 when A[t] op B[t], else 0 where op is one of >, <, >=, <=, ==, !=
Sequence
The Sequence node detects an ordered pair of conditions. Its signal activates on bars where input B is active and input A was active within the last Candles bars, counting the current bar.
Parameters
- Candles
The length of the lookback window in bars. A counts as having occurred if it was active on any bar in the window ending at, and including, the current bar. With Candles set to 1, A and B must be active on the same bar.
Inputs
- in0 (A), in1 (B)
A is the trigger condition and B is the confirmation condition. Both must be wired. The node reads the active state of each on every bar.
Outputs
- signal — Signal. Activates on bars where B is active and A was active somewhere in the trailing Candles-bar window. Any input that accepts a Signal reads this and reacts on bars where it's active.
Formula
signal[t] = 1 when B[t] = 1 AND A was active on any bar in [t - Candles + 1, t], else 0
Transform
The Transform node applies one mathematical transformation to a numeric series. Transform Type selects the transformation; Period and a set of per-type parameters configure it.
Parameters
- Transform Type
- Period
The lookback window in bars. Used by SMA, EMA, WMA, Delta, Percent, ROC, Rolling Max, Rolling Min, Rolling Std, Z-Score, and Linear Regression.
- Alpha
The smoothing factor for EMA. When set, it overrides Period and the EMA weights the current bar by Alpha and the prior EMA by one minus Alpha. When left unset, EMA derives its smoothing from Period.
- Weight Scheme
- Custom Weights
A comma-separated list of weights, one per bar in the window. The list length must equal Period. The weights are normalized to sum to 1 before being applied.
- Offset
Shifts the series back by Offset bars before the rolling window is applied, so the aggregate covers bars ending Offset bars before the current one.
- Ddof
Delta degrees of freedom for the standard deviation. A value of 1 gives the sample standard deviation; 0 gives the population standard deviation.
- Multiplier
Scales the z-score before it is clipped to the range minus 10 to 10.
- Method
- Reset Window
The running total restarts every Reset Window bars. A value of 0 means the total never resets and accumulates over the whole series.
- Bars
The number of bars to shift the series. A positive value looks back, so the output at the current bar is the input from Bars bars earlier.
- Allow Negative
When true, Bars may be negative, shifting the series forward. When false, a negative Bars value is rejected.
- in0
If connected, the transform runs on the connected series. If unconnected, it runs on the close price of the strategy's ticker.
Outputs
- values — Series. The transformed series. The chart draws it as an overlay, and any input that accepts a Series receives it.
- signal — Signal. Activates on bars where the transform has produced a valid number, that is, once the lookback window has filled. Any input that accepts a Signal reads this and reacts on bars where it's active.
Formulas
SMA at bar t = (x[t-N+1] + x[t-N+2] + ... + x[t]) / N
alpha = 2 / (N + 1) EMA at bar t = alpha * x[t] + (1 - alpha) * EMA[t-1]
Delta at bar t = x[t] - x[t-N] Percent at bar t = (x[t] - x[t-N]) / x[t-N] * 100
z[t] = Multiplier * (x[t] - mean(x, N)[t]) / std(x, N, Ddof)[t] clipped to the range -10 to 10
Math
The Math node evaluates a free-text formula over its wired inputs and emits the result as a series. The formula references each input as input1 through input5 and may use a built-in library of math functions and constants.
Parameters
- Formula
The expression evaluated on every bar. It references inputs by name (input1 through input5), the arithmetic operators below, the function library, and the constants pi and e. Every input referenced in the formula must be wired, or the node reports an error.
- Input Count
How many input handles the node exposes. The handles map in order to input1 through input5 in the formula.
Inputs
- in0 through in4
One handle per input, mapped in order to input1 through input5 in the formula. The number of handles shown is set by Input Count.
Function library
The formula accepts these operators and functions, applied per bar:
- Operators
Addition, subtraction, multiplication, division, exponent, and modulo.
- Arithmetic
Rounding, sign, and remainder helpers.
- Exponential and logarithmic
Powers, roots, and logarithms. log is the natural logarithm.
- Trigonometric and hyperbolic
Angle functions and their inverses and hyperbolic forms.
- Comparison and selection
max and min take two operands per bar; clip(x, low, high) bounds a value; where(condition, a, b) selects a when the condition holds, otherwise b.
- Statistical
Reductions across a series.
- Constants and checks
Mathematical constants and validity checks.
Outputs
- values — Series. The result of the formula evaluated on each bar. The chart draws it as an overlay, and any input that accepts a Series receives it.
- signal — Signal. Activates on bars where the formula produces a valid number. Any input that accepts a Signal reads this and reacts on bars where it's active.
Numeric Value
The Numeric Value node emits a number as a series. In Value mode it emits a constant; in Percent mode it emits a percentage of a chosen source.
Parameters
- Value
In Value mode, the constant emitted on every bar. In Percent mode, the percentage applied to the selected source.
- Mode
- Percent Source
Inputs
- in0
Used only when Mode is Percent and Percent Source is Input. The node emits Value percent of this series. Ignored in all other configurations.
Outputs
- values — Series. The constant or computed number on each bar. Any input that accepts a Series receives it; a common use is the threshold operand of a Relation.
- signal — Signal. Active on bars where a valid value is present. Any input that accepts a Signal reads this and reacts on bars where it's active.
Capture
The Capture node stores a value on the bars its input wire's signal activates and holds that value until the next capture. The held value becomes available on the bar after the capture bar.
Parameters
- Mode
- Initial value
The value held before the first capture occurs. When left empty, no value is held until the first capture, and the output signal stays inactive until then.
- Trigger / Source
Its signal determines when a value is stored. By default the wire's own value is captured; sources that emit only a signal (AND, OR, Relation, Schedule, Sequence) carry no value, so the close price of the strategy's ticker is captured instead. The run is blocked while unwired.
- Value Override
When connected, this series is captured instead of the trigger wire's value.
Outputs
- signal — Signal. Active on every bar from the first captured value onward, while a value is being held. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The held value. Any input that accepts a Series receives the most recent captured value, carried forward until the next capture.
Availability
A captured value becomes available on the bar after the capture bar, not on the capture bar itself. Downstream nodes therefore read the value of the series as it was when the mask last activated, never the current bar's value at the moment of capture.
Schedule
The Schedule node activates its signal on bars that fall at a specific time of day (event mode) or inside a time-of-day window (range mode), restricted to the selected days of the week. Bar timestamps are converted to the configured timezone before matching.
Parameters
- Mode
- Timezone
The timezone the trigger and window times are interpreted in. Each bar's timestamp is converted to this zone before its time of day is matched.
- Days of week
The weekdays on which the signal may activate. Bars on unselected days never activate.
- Anchor time
- Manual time
The trigger time of day, used when Anchor time is Manual.
- Offset
Minutes added to (sign +) or subtracted from (sign −) the anchor time to produce the final trigger time.
- Start / End
The window bounds. Each is an anchor (market open, market close, or manual), a manual time, and a signed minute offset, resolved the same way as the event-mode trigger. A window whose start is later than its end wraps across midnight.
Outputs
- signal — Signal. Active on the day's first bar at or after the trigger time (event mode) or on every bar inside the window (range mode), on enabled days of the week. Any input that accepts a Signal reads this and reacts on bars where it's active.
Stop Loss
The Stop Loss node computes a stop price level a configurable distance from a reference price and activates its signal on the bar price crosses that level. It outputs the level and the cross signal; it does not place trades.
Parameters
- Stop type
- Stop value
The distance, in the unit set by Stop type: a percent for Percentage, a price amount for Fixed, an ATR multiple for ATR.
- ATR period
Lookback in bars for the Average True Range. Used only when Stop type is ATR.
- Direction
- data_in
The reference price the level is measured from, typically a captured entry price. If unconnected, the close price is used.
Outputs
- signal — Signal. Active on the bar price crosses the stop level. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The stop price level per bar. The chart draws this as a price overlay.
Formulas
Percentage: level = entry * (1 - value / 100) Fixed: level = entry - value ATR: level = entry - ATR(period) * value
Percentage: level = entry * (1 + value / 100) Fixed: level = entry + value ATR: level = entry + ATR(period) * value
ATR(period) = simple moving average of true range over period true range[t] = max(high[t] - low[t], |high[t] - close[t-1]|, |low[t] - close[t-1]|)
signal[t] = 1 when close[t] < level[t] AND close[t-1] >= level[t-1], else 0
signal[t] = 1 when close[t] > level[t] AND close[t-1] <= level[t-1], else 0
Profit Target
The Profit Target node computes a target price level a configurable distance from a reference price and activates its signal on the bar price crosses that level. It outputs the level and the cross signal; it does not place trades.
Parameters
- Target type
- Target value
The distance, in the unit set by Target type: a percent for Percentage, a price amount for Fixed, an ATR multiple for ATR.
- ATR period
Lookback in bars for the Average True Range. Used only when Target type is ATR.
- Direction
- data_in
The reference price the level is measured from, typically a captured entry price. If unconnected, the close price is used.
Outputs
- signal — Signal. Active on the bar price crosses the target level. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The target price level per bar. The chart draws this as a price overlay.
Formulas
Percentage: level = entry * (1 + value / 100) Fixed: level = entry + value ATR: level = entry + ATR(period) * value
Percentage: level = entry * (1 - value / 100) Fixed: level = entry - value ATR: level = entry - ATR(period) * value
ATR(period) = simple moving average of true range over period true range[t] = max(high[t] - low[t], |high[t] - close[t-1]|, |low[t] - close[t-1]|)
signal[t] = 1 when close[t] > level[t] AND close[t-1] <= level[t-1], else 0
signal[t] = 1 when close[t] < level[t] AND close[t-1] >= level[t-1], else 0
Trailing Stop
The Trailing Stop node computes a stop level that ratchets in the favorable direction and never loosens, and activates its signal on the bar price crosses it. It outputs the level and the cross signal; it does not place trades.
Parameters
- Trail type
- Trail value
The trailing distance, in the unit set by Trail type: a percent for Percentage, a price amount for Fixed, an ATR multiple for ATR.
- ATR period
Lookback in bars for the Average True Range. Used only when Trail type is ATR.
- Direction
Outputs
- signal — Signal. Active on the bar price crosses the trailing stop. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The trailing stop level per bar. The chart draws this as a price overlay.
Formulas
best_high[t] = running maximum of high up to bar t raw[t] = best_high[t] - distance (distance per Trail type, as in Stop Loss) level[t] = running maximum of raw up to bar t (only tightens, never loosens)
best_low[t] = running minimum of low up to bar t raw[t] = best_low[t] + distance level[t] = running minimum of raw up to bar t (only tightens, never loosens)
signal[t] = 1 when close[t] < level[t] AND close[t-1] >= level[t-1], else 0
signal[t] = 1 when close[t] > level[t] AND close[t-1] <= level[t-1], else 0
Divergence
The Divergence node compares swing points in two series and activates when the most recent matching pair of swings moves in opposite directions. It detects regular divergence (opposing extremes) and hidden divergence (the continuation variant). By default it compares the close against an internal RSI computed on close; wiring either input overrides that side.
Parameters
- RSI Length
Period of the internal RSI (computed on close) used as Series B when the indicator input is unwired. Ignored when an oscillator is connected.
- Pivot left
Bars to the left of a candidate swing that must be lower (for a swing high) or higher (for a swing low) to confirm it.
- Pivot right
Bars to the right of a candidate swing that must confirm it. A confirmed swing cannot produce a signal until this many bars have passed, so this also sets the confirmation delay.
- Max bars
The largest bar distance allowed between the two compared swing points. Pairs farther apart than this are not compared.
- Divergence type
- Direction
- Series A (Price)
Optional override for the price side. Unwired, Series A is the close.
- Series B (Indicator)
Optional override for the oscillator side. Unwired, Series B is the internal RSI (RSI Length, on close). Wire any oscillator such as MACD or Stochastic to compare against it instead.
Outputs
- signal — Signal. Activates on the confirmation bar (Pivot right bars after the swing) when a divergence is found. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The divergence kind on each active bar: regular bullish, regular bearish, hidden bullish, or hidden bearish.
Divergence cases
Regular: A makes a lower low AND B makes a higher low Hidden: A makes a higher low AND B makes a lower low
Regular: A makes a higher high AND B makes a lower high Hidden: A makes a lower high AND B makes a higher high
Direction Filter
The Direction Filter node passes an input signal through only on the bars where a separate direction series matches the selected sign, gating the signal by market direction.
Parameters
- Filter direction
- Signal to Filter
The signal being gated. The output can only be active on bars where this is active. The run is blocked while unwired.
- Direction Source
The direction reference, typically from a different node than the signal. Positive values mark bullish bars, negative values mark bearish bars. Connect any directional series whose sign carries the direction. The run is blocked while unwired.
Outputs
- signal — Signal. The input signal restricted to bars where the direction series matches Filter direction. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The direction series, passed through for downstream use.
Formulas
signal[t] = 1 when input[t] is active AND direction[t] > 0, else 0
signal[t] = 1 when input[t] is active AND direction[t] < 0, else 0
Crossover
The Crossover node compares two connected series and activates either on the bar one crosses the other (cross mode) or on every bar one stays above or below the other (state mode).
Parameters
- Mode
- Direction
- Series A
The first series in the comparison (for example a price or a fast line). The run is blocked while unwired.
- Series B
The second series in the comparison (for example a band level or a slow line). The run is blocked while unwired.
Outputs
- signal — Signal. Active per the configured Mode and Direction. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The difference series A minus B, available for downstream use.
Formulas
bullish[t] = 1 when A[t] > B[t] AND A[t-1] <= B[t-1], else 0 bearish[t] = 1 when A[t] < B[t] AND A[t-1] >= B[t-1], else 0
bullish[t] = 1 when A[t] > B[t], else 0 bearish[t] = 1 when A[t] < B[t], else 0
Portfolio Value
The Portfolio Value node compares the strategy's current portfolio equity against a target, in dollars or as a percentage of starting capital. Each ticker in a backtest runs its own isolated portfolio, so the equity is that ticker's portfolio only.
Parameters
- Mode
- Comparison
- Target Value
The dollar amount (Dollars mode) or percentage of starting cash (Percent mode) the equity is compared against.
- data_in
If connected, the comparison and the value output use the connected series instead of the portfolio's computed equity.
Outputs
- signal — Signal. Activates on bars where the configured comparison holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The portfolio equity in dollars on each bar (or the connected data_in series when wired).
Formulas
equity[t] = cash[t] + position_quantity[t] * close[t] - margin_debt[t]
target = (Target Value / 100) * starting_cash
Portfolio state evaluation
The node reads the portfolio's live state during trade execution rather than from precomputed price data. On each bar the equity reflects every fill that has already executed on that bar (fills happen at the bar's open), with the open position valued at that bar's close — the same valuation the equity curve records.
Because the output depends on live portfolio state, strategies that include this node cannot be exported to Python or Pine Script. The export dialog flags them before any code is generated.
Drawdown
The Drawdown node tracks the strategy's portfolio equity over a rolling lookback window and compares its decline from the window peak against a target percentage. Each ticker in a backtest runs its own isolated portfolio, so the drawdown is that ticker's equity drawdown.
Parameters
- Lookback Period
The size of the rolling window the peak is measured within, in the selected unit.
- Lookback Unit
- Trigger On
- Comparison Type
- Target Percentage
The drawdown percentage the selected metric is compared against. Drawdown is always expressed as a positive percentage below the peak.
- data_in
If connected, the drawdown is computed on the connected series instead of portfolio equity.
Outputs
- signal — Signal. Activates on bars where the configured comparison holds. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The current drawdown percentage on each bar.
Formulas
drawdown[t] = (window_peak - equity[t]) / window_peak * 100
equity[t] = cash[t] + position_quantity[t] * close[t] - margin_debt[t]
Portfolio state evaluation
The node reads the portfolio's live state during trade execution rather than from precomputed price data. On each bar the equity reflects every fill that has already executed on that bar, with the open position valued at that bar's close. When the window peak is not positive there is no valid peak to measure from and the drawdown reports as zero.
Because the output depends on live portfolio state, strategies that include this node cannot be exported to Python or Pine Script. The export dialog flags them before any code is generated.
Exposure
The Exposure node outputs the strategy portfolio's position exposure as a percentage of portfolio equity, for a selected metric. Each ticker in a backtest runs its own isolated portfolio holding at most one position, so the exposure reflects that ticker's position only.
Parameters
- Metric to Output
Outputs
- signal — Signal. Always active; the node is a value source, and conditions are built by comparing its value downstream. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The selected exposure metric in percent on each bar. A leveraged position can exceed 100.
Formulas
exposure[t] = position_value[t] / equity[t] * 100 where position_value is signed for Net, clamped to one side for Long/Short, absolute for Gross
Portfolio state evaluation
The node reads the portfolio's live state during trade execution rather than from precomputed price data. On each bar the position and equity reflect every fill that has already executed on that bar, valued at that bar's close. When equity is not positive there is no valid base to measure against and the exposure reports as zero.
Because the output depends on live portfolio state, strategies that include this node cannot be exported to Python or Pine Script. The export dialog flags them before any code is generated.
Position Count
The Position Count node outputs the number of open positions in the strategy's portfolio for the current ticker, filtered by direction. Each ticker in a backtest runs its own isolated portfolio, which holds at most one open position at a time, so the count is 0 or 1.
Parameters
- Direction
Outputs
- signal — Signal. Activates on bars where an open position matches the selected Direction. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The position count for the selected Direction on each bar: 0 while no matching position is open, 1 while one is.
Portfolio state evaluation
The node reads the portfolio's live state during trade execution rather than from precomputed price data. On each bar the count reflects every fill that has already executed on that bar (fills happen at the bar's open), so a position opened at the current bar's open is counted on that same bar. The count covers only the current ticker's portfolio; a multi-ticker strategy evaluates each ticker independently.
Because the output depends on live portfolio state, strategies that include this node cannot be exported to Python or Pine Script. The export dialog flags them before any code is generated.
Cash Balance
The Cash Balance node outputs a cash metric of the strategy's portfolio for the current ticker: total cash, cash available after the global reserve, or a reserve amount computed from a configurable percentage. Each ticker in a backtest runs its own isolated portfolio, so the value reflects that ticker's portfolio only.
Parameters
- Output Metric
- Reserve (%)
The percentage of current portfolio equity reported by the Reserved Amount metric. Only used when Output Metric is Reserved Amount.
- reserve_pct_in
If connected, the connected series value replaces the Reserve (%) setting on each bar.
Outputs
- signal — Signal. Always active; the node is a value source, and conditions are built by comparing its value downstream. Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The selected cash metric in dollars on each bar.
Portfolio state evaluation
The node reads the portfolio's live state during trade execution rather than from precomputed price data. On each bar the value reflects every fill that has already executed on that bar (fills happen at the bar's open), and equity-based amounts value the open position at that bar's close.
Because the output depends on live portfolio state, strategies that include this node cannot be exported to Python or Pine Script. The export dialog flags them before any code is generated.
Risk Per Trade
The Risk Per Trade node computes a risk-based position size from live portfolio equity and a volatility measure. By default it measures volatility itself with an internal ATR; wiring a series into its input overrides that. Each ticker in a backtest runs its own isolated portfolio, so the equity in the calculation is that ticker's portfolio.
Parameters
- Max Risk Pct
The percentage of current portfolio equity that defines the risk budget for one trade.
- ATR Period
Period of the internal ATR used when nothing is wired into the input. Ignored when a volatility series is connected.
- ATR Multiplier
Factor applied to the volatility value to define the stop distance used in the size calculation. Wider stop distance produces a smaller size.
- Value per Price Point
The monetary value of one full price point. One for most stocks; contract or pip value for other instruments.
- volatility_in
Optional override. Wire a volatility series to derive the stop distance from it instead of the internal ATR — an ATR node with different settings, a band width, or any numeric series.
Outputs
- signal — Signal. Activates on bars where a positive size is computable (the volatility input has warmed up and equity is positive). Any input that accepts a Signal reads this and reacts on bars where it's active.
- values — Series. The computed position size in shares or contracts on each bar; zero while no valid size is computable.
Formulas
position_size[t] = (equity[t] * max_risk_pct / 100) / (volatility[t] * atr_multiplier * value_per_price_point)
Portfolio state evaluation
The node reads the portfolio's live state during trade execution rather than from precomputed price data. On each bar the equity reflects every fill that has already executed on that bar, with the open position valued at that bar's close. Buy and Sell nodes size trades from their own configuration; this node's output is read through value comparisons, not as an order quantity.
Because the output depends on live portfolio state, strategies that include this node cannot be exported to Python or Pine Script. The export dialog flags them before any code is generated.
Charts
Overview
After running a backtest, Backtest Labs generates a suite of interactive charts and visualizations that break down your strategy's performance from multiple angles. This section documents each chart individually, covering how to read the data and the calculations behind it.
- Ticker selector
Switches between tickers when the strategy ran on more than one. Each ticker has its own per-ticker results, and the selected ticker drives every chart in the suite. Multi-ticker strategies do not combine positions across tickers.
Price Chart
The Price Chart shows candlestick price action for one ticker in the backtest, with indicator overlays, executed trade markers, and synchronized volume. It is where you check what the strategy actually did against the price it traded on.
Panels and overlays
- Price candles
One candle per bar at the strategy's execution interval, showing open, high, low, and close, colored by whether the bar closed above or below its open in the active theme. This is the ground truth the strategy traded against, and every marker and overlay is positioned relative to these bars.
- Indicator overlays
Indicator nodes whose output is on the price scale (moving averages, Bollinger Bands, Donchian Channels, VWAP, and similar line or band indicators) draw directly on the candles in the node's color. Reading a trade marker against its overlay is how you confirm the logic fired where you expected, such as an entry landing where price crossed a moving average.
- Indicator subpanels
Indicator nodes whose output is not on the price scale (RSI, MACD, ATR, volume-based oscillators) appear in their own subpanels beneath the price panel, all sharing its time axis. Because the axis is shared, you can line up a subpanel event, an RSI cross or an ATR spike, with the exact candle and any trade above it.
- Trade markers
Every executed entry and exit places a marker on the bar where the trade filled: long entries and short covers render as upward markers, short entries and long exits as downward markers, and hovering a marker shows the trade's direction, fill price, size, and realized profit and loss for closed positions. Scanning the markers along the candles shows the strategy's actual behavior, where it entered and exited relative to the swings it was trading.
- Volume
A bar chart of executed-interval volume rendered as an underlay in the same panel as the candles rather than a separate panel beneath, colored by the matching candle's direction. It gives context for the price bars, letting you see whether a move the strategy traded on came on heavy or thin volume.
Returns Analysis
The Returns Analysis view summarizes how the portfolio grew over the backtest, pairing a strip of headline performance metrics with three charts: the equity curve, returns grouped by calendar period, and the distribution of per-bar returns.
Performance metrics
- Total Return
Cumulative percentage gain or loss from the start to the end of the backtest, before annualization.
- CAGR
Compound annual growth rate, the return as if the portfolio grew at a steady rate each year; the fairest single number for comparing runs of different lengths.
- Ann. Volatility
Return standard deviation scaled to a yearly figure, the size of the typical swing.
- Sharpe Ratio
Excess return over the risk-free rate per unit of total volatility, with the risk-free rate used shown beneath it; higher means more return earned per unit of risk taken.
- Sortino Ratio
Like Sharpe but charging only downside volatility, so upside swings are not counted against the strategy.
- Calmar Ratio
Annualized return divided by maximum drawdown, return measured against the worst decline it took to earn it.
- Skewness
Asymmetry of the returns distribution; positive leans toward occasional large gains, negative toward occasional large losses.
- Kurtosis
Tail weight relative to a normal distribution; higher means extreme returns, good or bad, happened more often than normal.
Charts
- Equity Curve
A full-width line of the portfolio's cumulative result across the backtest, with any benchmarks overlaid as their own lines and dividend markers where the ticker paid them; hovering reports the value at that bar in a status bar beneath the chart. Read the shape, not just the endpoint: a smooth, steady rise is a more durable result than the same ending value reached through a few sharp jumps, and the gap between the strategy line and a benchmark line is the outperformance you are really after.
- Periodic Returns
One bar per calendar period, each the portfolio's return over that period, with a W / M / Q / Y toggle to switch between weekly, monthly, quarterly, and yearly grouping and the share of positive periods reported alongside. Coarser groupings smooth out noise to show whether the strategy is broadly consistent: a run of similar green bars is steadier than a few tall bars carrying an otherwise mixed set.
- Returns Distribution
A histogram binning per-bar returns by size, showing how often returns of each magnitude occurred, with any benchmark's distribution overlaid. A tall, narrow shape centered just above zero is a calm, consistent return stream; a wide shape or a long left tail means large swings, and comparing the strategy's spread against the benchmark's shows whether it delivered its return with more or less turbulence.
Drawdown Analysis
The Drawdown Analysis view shows how far and how long the portfolio fell below its prior equity peaks, pairing a strip of drawdown metrics with three charts: the underwater curve over time, the worst drawdown episodes, and the distribution of drawdown depths.
Drawdown metrics
- Max Drawdown
The largest peak-to-trough decline over the whole backtest, the single worst loss from a high.
- P95 Depth
95th-percentile drawdown depth; 95% of drawdowns were shallower than this, so it describes the routine bad stretch rather than the one worst.
- Avg Depth
Mean drawdown depth across the bars spent below a prior peak.
- Tail Average
Average of the worst 5% of drawdowns, the drawdown expected shortfall; how deep it tends to get once it gets bad.
- Time Underwater
Percentage of all bars spent below the previous equity peak, how much of the run was spent recovering rather than making new highs.
- Current
Drawdown at the end of the backtest; zero means it finished at or near an equity high.
- Longest
The longest single stretch below a prior peak before recovering, in calendar days (or hours/bars for intraday), the patience the strategy demands.
- Recovery Factor
Total net profit divided by maximum drawdown, how much reward the strategy produced per unit of its worst pain.
- Period Count
Number of distinct underwater periods (peak-to-recovery cycles).
- Ulcer Index
Root mean square of drawdowns, folding depth and duration into one figure, so it penalizes long shallow declines as well as short deep ones.
Charts
- Underwater Chart
A full-width plot of drawdown depth over time: at each bar, how far below the running equity peak the portfolio sits, in percent. The line touches zero every time equity makes a new high and dips through each decline, with benchmarks overlaid. Read both the depth and the width of the dips: a deep spike that snaps back is easier to live with than a shallow trough that drags on, and long flat stretches at zero are the healthy periods of steady new highs.
- Worst Drawdowns
The largest drawdown episodes ranked by depth, so the handful of most severe peak-to-trough declines read at a glance. Check whether one episode dwarfs the rest, which means the Max Drawdown figure hinges on a single event, or whether several are of similar size, which means deep declines are a recurring feature of the strategy rather than a one-off.
- Drawdown Distribution
A histogram binning drawdown depths by size, showing how often declines of each magnitude occurred, with any benchmark overlaid. Most of the mass bunched near zero with a thin tail means declines were usually mild; a fat tail toward deep drawdowns means severe declines were not rare, which matters more for survival than the average depth does.
Trade Distribution
The Trade Distribution view breaks the backtest down to the level of individual round-trip trades, spread across five tabs. This first tab is the headline read on trade quality: a vitals scorecard, the geometry of wins against losses, and a chronological pass over every trade.
Vitals
- Profit Factor
Gross profit divided by gross loss across closed trades; above 1 means the wins outweigh the losses overall, and the view labels above 2 excellent.
- Expectancy
Average profit or loss per trade, the dollar edge you can expect each time you trade.
- Payoff Ratio
Average winning trade divided by average losing trade; how many times larger a typical win is than a typical loss.
- SQN Score
System Quality Number (Van Tharp), a measure of how consistent the edge is relative to trade-to-trade variability. It needs at least 30 trades to show, and the view labels 2.5 and up good, 3 and up excellent.
- Trade Frequency
How often trades occur on average over the period.
- Closed Trades
Count of completed round-trip trades, the sample size behind every metric on the tab.
- Dividend Events and Div. Income
Number of dividend payouts received and total dividend income, shown when the ticker paid dividends.
Charts
- Win Rate
A donut of winning against losing trades, with the win rate and trade count at the center. Win rate alone does not decide profitability, so read it together with Payoff Ratio: a low win rate can still be very profitable when the winners are large, and a high win rate can lose money when the losses are bigger than the wins.
- Net P&L
Cumulative realized profit and loss across trades in sequence, drawn as an area sparkline. A steady climb means gains accrued broadly across many trades; a flat stretch broken by one steep jump means a single trade or two carried the result, which is the more fragile shape.
- Win/Loss Comparison
Diverging bars comparing winners and losers at six points of their size distribution (smallest, 25th percentile, median, average, 75th percentile, and largest), winners extending one way and losers the other. Read the symmetry: if the loser bars reach noticeably further than the winner bars at matching points, individual losses are outsizing individual wins, and the strategy is leaning on win rate to stay ahead.
- MAE/MFE Pain Map
A scatter of every closed trade by its worst unrealized loss (MAE, how far it moved against you before closing) against its largest unrealized gain (MFE, how far it ran in your favor), sized by profit and loss and colored by outcome. It shows how much heat trades took and how much of their move they captured: winners clustered at low MAE mean entries were well-timed, while trades with high MFE that still closed as losers were in profit and gave it back before the exit.
- Trade Rhythm
One bar per closed trade in chronological order, colored by win or loss with opacity scaled to trade size, shown next to max win streak, max loss streak, and average duration. Long runs of one color reveal streakiness, and pairing the streak lengths with the coloring shows whether losses arrived in clusters, which drives the deeper equity dips, or were spread evenly among the wins.
Distribution
The Distribution tab shows the spread of per-trade outcomes, so you can see the shape of the results rather than just their average. Outcomes can be viewed as dollar profit and loss, percent return, or R-multiple, and filtered to winners or losers.
Scorecard
- Trades
Count of trades in the current distribution after any winner or loser filter.
- Mean
Average of the selected outcome metric. Compare it against the median: a mean well above the median means a few large winners are pulling the average up.
- Median
The middle outcome, the typical trade, unaffected by outliers.
- Std Dev
Standard deviation of the outcomes; wider means less predictable results from one trade to the next.
- 5th %ile
Fifth-percentile (worst) outcome, the kind of loss that turns up roughly one trade in twenty.
- 95th %ile
95th-percentile (best) outcome.
Charts
- Histogram
Trade count binned by outcome size, on a linear or logarithmic count axis. The shape is the read: a single hump centered just above zero with a short left tail is the healthy picture, a long left tail means occasional large losses, and a tall spike in one bin means many trades cluster at the same outcome, often a fixed stop or target. The log axis makes rare large-outcome bins visible when one tall bin would otherwise flatten the rest.
- Cumulative Distribution
The cumulative share of trades plotted against outcome size, rising from 0 to 100%, with the median marked. Read off any point to answer what fraction of trades did worse than a given result: where the curve crosses zero is the share of losing trades, and a curve that climbs steeply through a narrow band means outcomes are tightly clustered.
- Q-Q Plot
Observed trade quantiles plotted against the quantiles of a normal distribution, with a straight reference line for a perfect match. Points hugging the line mean outcomes are roughly normal; points bending away at the ends mean fat tails, and the low end is the one to watch, since points dropping below the line flag losses larger and more frequent than a normal distribution would predict.
Trades
The Trades tab is the raw blotter, every closed trade laid out so you can audit individual results rather than aggregates. It reads two ways: ungrouped, one row per trade, or grouped into trade chains.
Views
- Ungrouped blotter
One row per trade carrying its ID, chain, action, outcome, timestamp, quantity, price, profit and loss, return percent, commission, slippage, MAE, MFE, R-multiple, and duration. This is where you verify what the aggregate charts summarize: scan the largest losers for a common thread, a shared entry time, duration, or cost profile that the averages hide.
- Grouped chains
Each trade chain rolled up into one row (outcome, first entry, last exit, leg count, duration, total profit and loss, MAE, and average R) and expandable to its individual legs. Chains matter because consecutive entries in the same direction are merged into one position, so a chain is the real economic trade; group here when a single-row trade looks small but was actually one leg of a larger scaled-in position.
Timing
The Timing tab covers when trades happen and how long they are held. The layout adapts to the strategy's interval, showing intraday breakdowns for intraday strategies and weekday and monthly breakdowns for end-of-day ones, and values can be shown as R-multiple or dollar profit and loss.
Scorecard
- Best Hour and Worst Hour
Intraday strategies: the hours of day with the strongest and weakest average performance, shown once each hour has enough trades to be meaningful.
- Best Day and Worst Day
Weekdays with the strongest and weakest average performance; a persistent gap can reflect real market patterns rather than noise.
- Median Hold
Median holding duration across closed trades, the typical time spent in a position.
- Hold Consistency
Coefficient of variation of holding durations; lower means the strategy holds for a consistent length, higher means duration swings widely from trade to trade.
- Avg Winner Hold and Avg Loser Hold
End-of-day strategies: average holding duration of winners versus losers. Winners held longer than losers is the healthy pattern; the reverse means the strategy tends to sit in losers hoping they recover.
Charts
- Hour × Day Performance
Intraday strategies: a heatmap of average performance by hour of day against day of week, each cell colored by result. Scan for bright or dark blocks: a cluster of strong cells at the same hours across days points to a time-of-day effect, while a scattered mix means timing is not driving results.
- Session Performance
Intraday strategies: average performance by trading session (pre-market, open hour, midday, power hour, after hours, or the crypto sessions) as horizontal bars, grouping the hourly view into the parts of the day that tend to behave differently.
- Day of Week Performance
End-of-day strategies: average performance by weekday as horizontal bars. Read it alongside the trade count per day, since a standout day built on only a handful of trades is more likely noise than a real weekday edge.
- Monthly Performance
End-of-day strategies: average performance by calendar month as vertical bars, useful for spotting seasonal tendencies, again weighed against how many trades fall in each month.
- Duration vs Payoff
A scatter of each trade's holding duration against its R-multiple or profit and loss. A cloud with no slope means holding time and payoff are unrelated; an upward tilt means longer holds tended to pay more, and a downward tilt means the edge decays the longer the strategy stays in.
- Holding Period Distribution
Trade count binned by how long positions were held, showing whether the strategy is consistently short-term, consistently long, or a mix. A wide spread here is the higher coefficient of variation that shows up as the less-consistent end of the Hold Consistency metric.
Execution
The Execution tab is the per-trade cost of doing business and how much it ate into performance. It covers what execution cost, how it accumulated over the run, and whether trade sizes were large enough to run into real-world liquidity limits.
Scorecard
- All-In Cost
Average execution cost per trade in basis points, commission and slippage combined.
- Total Costs
Total commission and slippage paid across the whole backtest.
- Cost % P&L
Share of gross profit and loss consumed by execution costs; the higher, the more of the edge went to friction.
- Turnover
Average monthly portfolio turnover rate; higher turnover means more trading and usually more total cost.
- Median %ADV
Median trade size as a percent of average daily volume (24h volume for crypto); the view flags sizes under about half a percent as small enough not to move the market.
- P95 %ADV
95th-percentile trade size as a percent of average daily volume, so you can see the largest trades' liquidity footprint, not just the typical one.
Charts
- Cost Drag
Gross return and net return over time, with the cost drag shaded between them. The gap is the read: when the two lines stay tight, execution is cheap relative to the edge, and a gap that widens as the backtest runs means costs are compounding against the strategy faster than it earns.
- Cost Waterfall
Gross profit stepped down through commission and then slippage to net profit, as a waterfall. It shows at a glance how much of the gross each cost type removed and which one dominates, which matters because slippage-heavy strategies behave very differently in live trading than commission-heavy ones, since slippage grows with size and volatility.
- Capacity
Trade count binned by trade size as a percent of average daily volume, with a cumulative-share overlay. It answers how much size the strategy could realistically carry: bins bunched at small percentages mean the modeled fills are believable, while a tail reaching into large-percent bins means some trades assumed liquidity that may not exist at scale.
- Periodic Costs
Commission and slippage per period as stacked bars, with a cost-in-basis-points efficiency line and a selectable period from hourly through yearly. Rising bars with a flat efficiency line just mean more trading; bars where the efficiency line climbs too mean each unit of trading got more expensive, the more worrying pattern.
Rolling Metrics
The Rolling Metrics view shows how the strategy's risk-adjusted performance changed across the backtest, recomputing each metric over a rolling window so every point reflects only its recent window rather than the whole run. Reading these as lines rather than single numbers is the point: a metric that looks strong overall can hide long weak stretches. This first tab covers the standalone metrics, each as a rolling line with a line per selected benchmark overlaid for comparison.
Scorecard
- Sharpe
Current (latest) rolling Sharpe ratio, the return earned per unit of total volatility right now.
- Sortino
Current rolling Sortino; like Sharpe but counting only downside volatility, so it rewards strategies whose swings are mostly to the upside.
- Calmar
Current rolling Calmar, return relative to the worst drawdown in the window, a return-per-pain measure.
- Volatility
Current annualized rolling volatility.
- Tail Ratio
Extreme gains over extreme losses, the 95th percentile of returns over the 5th; above 1 means the big up moves outweigh the big down moves.
- Med. Sharpe, Med. Sortino, Med. Calmar
The median rolling value of each ratio across the whole backtest, a more honest headline than the current or peak reading since it is not swayed by one good window.
- P95 Vol
95th-percentile rolling volatility, how high the swings got in the rougher stretches rather than on average.
- Skewness
Asymmetry of the return distribution; positive leans toward occasional large gains, negative toward occasional large losses.
Charts
- Sharpe Ratio
A rolling line of excess return over the risk-free rate divided by volatility. Read the line's level and its steadiness together: a line that holds well above zero across the run is a durable risk-adjusted edge, while one that spends long stretches near or below zero shows the edge came and went. The overlaid benchmark line tells you whether the strategy earned its risk better than simply holding the benchmark over the same windows.
- Sortino Ratio
The same idea as Sharpe but dividing by downside volatility only, so upside swings are not counted as risk. Where Sortino sits well above Sharpe, the strategy's volatility is mostly to the upside, the favorable kind; where the two track closely, the swings are roughly symmetric.
- Calmar Ratio
Rolling annualized return divided by the maximum drawdown within the window, so it rises when returns are strong relative to the worst decline and collapses right after a deep drawdown. Sharp drops in this line mark the windows where a large drawdown landed, even if returns stayed positive through them.
- Volatility
A rolling line of annualized return standard deviation, in percent. This is the context for every other line on the tab: rising volatility means the recent window was choppier, so a Sharpe or Sortino line falling while volatility climbs tells you the risk-adjusted metrics weakened because risk rose, not because returns dried up.
Benchmark
The Benchmark tab measures the strategy against each selected benchmark, each metric as a rolling line. It is available only when the backtest includes one or more benchmark tickers.
Scorecard
- Beta
Current rolling beta: how much the strategy moves for a given benchmark move, where 1 tracks it one-for-one, below 1 is less exposed, and above 1 amplifies it.
- R-squared
Fraction of the strategy's return variance explained by benchmark moves, from 0 to 1; high means it is largely riding the benchmark, low means its results come from something else.
- Correlation
Current rolling correlation with the benchmark, from -1 to +1.
- Track. Error
Current annualized tracking error: how far strategy returns stray from the benchmark; low hugs the benchmark, high goes its own way.
- Info Ratio
Current rolling information ratio, excess return per unit of active risk, the benchmark-relative cousin of Sharpe.
- Alpha
Current annualized alpha, return beyond what the benchmark exposure alone would predict.
- Batting Avg
Percentage of periods in which the strategy return exceeded the benchmark return.
- Up Capture
Share of the benchmark's gains the strategy captured in its up periods; above 100% means it outran the benchmark on the way up.
- Down Capture
Share of the benchmark's losses the strategy absorbed in its down periods; below 100% means it fell less than the benchmark, the goal.
- % IR > 0
Percentage of rolling periods with a positive information ratio.
Charts
- Alpha
A rolling line of return earned beyond what the benchmark's risk exposure alone would predict, drawn with a 95% confidence band. The band is essential: alpha wandering inside a band that spans zero is not distinguishable from luck, while alpha holding above the band's lower edge is the stronger claim to a genuine benchmark-beating edge.
- Beta
A rolling line of the strategy's sensitivity to benchmark moves, with a 95% confidence band, where 1 tracks the benchmark one-for-one. Watch for beta drifting over time: a strategy meant to be market-neutral should sit near zero throughout, and beta creeping up means it quietly took on more benchmark exposure in some windows.
- Correlation
Correlation between strategy and benchmark returns, from -1 to +1, viewable as a line over time or as a scatter of paired returns with a regression fit. On the line, stretches near zero mean the strategy moved independently of the benchmark; on the scatter, a tight cloud along the fit means a strong linear relationship and a diffuse cloud a weak one.
- Tracking Error
A rolling line of the annualized standard deviation of the return difference between strategy and benchmark. Low tracking error means the strategy stayed close to the benchmark; a rising line marks the windows where it diverged most, which is where alpha and information ratio are decided.
- Information Ratio
A rolling line of alpha divided by tracking error, the excess return earned per unit of active risk. It rewards outperformance that was steady rather than lucky: a high, stable line means the strategy beat the benchmark consistently, while a line swinging between strongly positive and negative means the outperformance was erratic even when the average looks fine.
Calendar Returns
The Calendar Returns view breaks the backtest down by calendar time, coloring each day by its return. It pairs a per-year heatmap and a month-by-month detail grid with a strip of calendar-based summary metrics.
Metrics
- Best Day and Worst Day
The single highest- and lowest-return days over the backtest, with their dates, the extremes the strategy produced in one session.
- Avg Daily
Mean return per trading day across the whole backtest.
- Win/Loss Days
Count of positive versus negative days, with the resulting day win rate.
- Max Loss Streak and Max Win Streak
Longest runs of consecutive losing and winning closed trades.
- Prof. Months
Number of months with a positive cumulative return, out of the total, a quick read on how often a full month ended green.
- Avg Monthly
Mean return per month across all months in the backtest.
Charts
- Year Overview
A heatmap of a single year, one cell per day colored by that day's return, laid out either as months-by-days or weekday-by-week, with the axis labels carrying each month's or weekday's running total and traded days marked (weekends dimmed on stock calendars). Scan for color clusters: a block of green in certain months, or a persistent column of red on one weekday, points to a seasonal or day-of-week pattern, while an even scatter of green and red means returns were not tied to the calendar.
- Month Detail
A calendar grid of a single month, each cell a trading day showing its return, trade count, and a secondary profit-and-loss or percentage figure (days with no position read "No Shares Held"), with per-weekday totals above and each week's total in a trailing column; benchmarks add their day return to each cell. This is the close-up for a month that stood out in the year heatmap, letting you see whether its result came from one large day or accumulated steadily across many.
Display modes
- Value
Returns are shown either as percentages or as dollar profit and loss.
- Layout
The year heatmap lays out by day (months by days 1 to 31) or by week (weekday by week). Stock calendars span Monday to Friday; crypto calendars span all seven days.
- Color
Positive days shade green and negative days red, scaled symmetrically around zero up to a configurable percentage ceiling for each side, so a brighter cell is a larger move in that direction.
Exposure Analysis
The Exposure Analysis view shows how much of the portfolio's equity was deployed over the backtest, broken into long, short, net, and gross exposure plus a leverage multiplier. It pairs a strip of exposure metrics with charts of leverage, exposure composition, net and gross exposure, and the distribution of exposure levels.
Series
- Long
Long-position exposure as a percent of portfolio equity.
- Short
Short-position exposure as a percent of portfolio equity.
- Net Exposure
Directional bias, long exposure minus short exposure, as a signed percent of equity.
- Gross Exposure
Total capital at risk, long exposure plus short exposure, as a percent of equity.
- Leverage
Total market exposure as a multiple of equity; values above 1.0x mean combined long and short exposure exceeds equity.
Metrics
- Time Invested
Percentage of bars that held any long or short exposure, how much of the time capital was at work rather than sitting in cash.
- Avg When Active
Average gross exposure across only the bars that held a position, the typical size when in the market.
- Avg Net
Average net exposure across all bars, the typical directional bias.
- Avg Leverage
Average leverage multiplier across all bars.
- Exposure Periods
Number of distinct contiguous runs of bars that held exposure.
- Avg Period
Average number of bars per exposure period.
- Max Long and Max Short
Highest long and highest short exposure reached at any bar.
- Max Leverage
Highest leverage multiplier reached at any bar, the peak risk the strategy took on.
- Net Volatility
Standard deviation of net exposure, how much the directional bias varied over the run.
Charts
- Leverage
A step line of the leverage multiplier over time, with a dashed reference line at 2x. Time spent above 1x means combined long and short exposure exceeded equity, and stretches pushing toward or past the 2x line mark the periods of greatest risk, where a move against the book is amplified.
- Exposure Composition
A mirrored area chart with long exposure as a positive area above zero and short exposure as a negative area below, each in percent of equity. It shows the makeup of the book at a glance: a chart living entirely above zero is long-only, balanced areas above and below are a hedged or market-neutral posture, and the total height at any point is how much capital was committed.
- Net & Gross Exposure
An overlaid area chart of net and gross exposure over time, in percent of equity, with a dashed zero line. The gap between the two is the read: when net and gross sit close together the book is directional, mostly one side, and when gross runs well above a near-zero net the strategy is holding offsetting long and short positions that cancel in direction but still carry risk.
- Distribution
A histogram of how often the portfolio sat at each exposure level, binning either net exposure or leverage, with a line at the mean, over the currently visible window. It shows the strategy's habitual posture rather than its moment-to-moment moves: a tall cluster at one level means consistent sizing discipline, while a wide spread means exposure varied a lot from bar to bar.
Aggregation
The series can be aggregated to a coarser calendar interval than the strategy's native interval, and the metrics recompute at the selected aggregation level. When portfolio equity was zero or negative on some bars, exposure for those bars is shown as 0 and a notice appears above the charts.
Multi-Chart
The Multi-Chart view is a grid that displays several result charts at once for side-by-side comparison. Each panel renders one visualization drawn from the catalog below, for a chosen strategy or benchmark ticker, and the time-series panels share one zoom slider and a synchronized crosshair. Its value is relational: putting two views on the same screen and the same time window surfaces cause and effect that the single-chart views cannot.
Layout
- Panel grid
Panels arrange in one of four layouts: two, three, or four stacked rows, or a two-by-two grid. A single zoom slider spans the full width beneath the panels.
- Synchronized time axis
Time-series panels are linked: zooming or panning one, or moving the shared slider, scrolls every linked panel to the same time window, and a crosshair tracks the same timestamp across them. Panels that are not time series, such as period bars, histograms, and heatmaps, do not link to the shared axis. The linking is what makes the view worth using: line up a drawdown in one panel with the exposure or volatility in another at the exact same moment, and a relationship that a single chart only hints at becomes visible.
The catalog below groups the panels you can place in the grid. Each is the same visualization documented in its own results view, so reach for that section when you want how to read a given panel; here they can be combined freely.
Value
- Price (Line + Events)
The asset's price over time as a line, with trade and corporate-event markers.
- Equity Curve
The portfolio's account value over time.
- Cumulative Returns
The strategy's compounded return over time.
- Net P&L
Cumulative dollar profit and loss over time.
Returns
- Daily Returns
Per-bar return as a time-series bar chart.
- Log Returns
Per-bar logarithmic return as a line.
- Weekly Returns
Return aggregated by week as period bars.
- Monthly Returns
Return aggregated by month as period bars.
- Yearly Returns
Return aggregated by year as period bars.
- Calendar Returns
Per-day returns laid out as a calendar barcode.
- Returns Distribution
Histogram of how often returns of each size occurred.
- Returns Heatmap
Returns laid out as a colored heatmap grid.
Risk Metrics
- Rolling Sharpe
Sharpe ratio over a rolling window.
- Rolling Sortino
Sortino ratio over a rolling window.
- Rolling Volatility
Annualized volatility over a rolling window.
- Rolling Max Drawdown
Maximum drawdown over a rolling window.
- Rolling Calmar
Calmar ratio over a rolling window.
- Tracking Error
Annualized standard deviation of the strategy-minus-benchmark return, over time.
- Information Ratio
Alpha divided by tracking error, over time.
- Rolling Beta
Sensitivity of strategy returns to a benchmark over a rolling window.
- Rolling Correlation
Correlation between strategy and benchmark returns over a rolling window.
- Rolling Alpha
Return beyond the benchmark's predicted contribution over a rolling window.
- Active Risk
Active risk against a benchmark, shown as tracking error or information ratio.
Oscillator-type indicators used in the strategy (such as RSI, MACD, CCI, ATR, OBV, and DMI/ADX) can also appear here, each in its own panel.
Drawdown
- Drawdown
Underwater equity decline from prior peaks, as a filled area.
- Drawdown Periodic
Drawdown aggregated into daily, weekly, monthly, or yearly periods as bars.
- Drawdown Distribution
Histogram of drawdown magnitudes.
Exposure
- Exposure Composition
Long and short exposure over time as mirrored areas.
- Net & Gross Exposure
Net and gross exposure over time as areas.
- Leverage
Leverage multiplier over time as a line.
- Exposure Distribution
Histogram of exposure levels.
- Exposure Heatmap
Exposure laid out as a colored heatmap.
Trade Analysis
- Trade Distribution
Histogram of per-trade outcomes, as dollar P&L, percent return, or R-multiple.
- Holding Period Distribution
Histogram of how long trades were held.
- Trade P&L Timeline
Each trade's profit and loss plotted as a point along time.
- Trade Rhythm
Heatmap of trade activity by time pattern.
- Trade Timeline
Heatmap of trades along the time axis.
- Trade Costs
Cumulative commission and slippage as stacked bars.
- Volume
Traded volume per bar as bars.
- Volume Indicators
All volume-scale indicator lines from the strategy (total or smoothed volume, relative volume baseline and raw volume) on one shared axis. Present only when the strategy uses such a node.
The relative volume ratio also appears here in its own panel.
Validations
The Validations category carries no built-in visualization and is available only when the run has validation data; validation results are shown in the dedicated Validations view.
Validations
The Validations view presents the results of the validation tests that ran with the backtest, each method on its own page in the results sidebar. The entries appear only when a backtest was run with validations enabled, and a method's page carries results only when that test produced them. How each test is computed is covered in the Validation Engine documentation; each validation page describes what its view displays.
Monte Carlo
Monte Carlo takes the trades your strategy actually made and resamples them into many alternate runs, building a distribution of the outcomes the same trades could have produced in a different order. The real backtest is just one path through that distribution, so where it lands tells you whether the result reflects a durable edge or leaned on the particular sequence the trades happened to occur in. The view pairs a scorecard of where the actual run ranks with two distributions and an equity fan that show the full range.
Scorecard
- Equity Rank
Percentile where the actual final equity ranks among the simulations; higher means the real run finished ahead of more of the resampled paths.
- DD Rank
Percentile where the actual maximum drawdown ranks; higher means the real run's worst decline was milder than more of the simulations.
- Final Equity
The backtest's ending equity, with its percent return. This is the value the distribution and bands below are measured against.
- Max Drawdown
The backtest's largest peak-to-trough decline, compared against the simulated expected and worst-case declines.
- Trades
Number of trades resampled, the sample size behind every simulation. Fewer trades widen the distributions and lower confidence.
- Confidence
Reliability rating of the result (high, medium, or low), set from the trade count, sample diversity, and data sufficiency.
- Expected Eq
Median final equity across the simulations, the typical outcome the trades support.
- 95% CI Low and 95% CI High
Lower and upper bounds of the 95% confidence interval for final equity; the middle range where the outcome is expected to fall.
- Expected DD
Median maximum drawdown across the simulations.
- Worst-Case DD
Fifth-percentile (worst) maximum drawdown across the simulations, the decline to plan around rather than the one the real run happened to hit.
- Risk of Ruin
Estimated probability that some ordering of the trades would breach a large drawdown.
- Worst Streak
Longest losing streak seen across the simulations.
- Typical Streak
Median losing streak across the simulations.
Charts
- Final Equity
A histogram of the ending portfolio value from every simulated run: the horizontal axis is final equity and the height of each bar is how many simulations landed in that value range. A marker shows where your actual backtest fell, labelled with its percentile. Read the width first, since it is the span of results the same trades could have produced by reordering alone: a narrow, tall shape means the outcome held up regardless of sequence, while a wide, flat shape means the ending value depended heavily on the order trades arrived in. Then read the marker: near the middle is a typical result for these trades, toward the high end means the real run finished ahead of most orderings (a favorable, possibly lucky, sequence), and down in the low tail means it underperformed what the same trades usually produce.
- Max Drawdown
A histogram of the deepest peak-to-trough decline in each simulated run, with the actual backtest's drawdown marked and ranked by percentile. This is the range of worst declines the trades can generate, so it answers a different question than the equity view: not how much you made, but how bad the ride could get. Because a shallower drawdown is better, the percentile reads in reverse of the equity one, where a high rank means the real run's worst decline was milder than most simulations. A marker in the shallow part of the distribution is a caution rather than a comfort: the real run got off lightly, and the deeper declines to the far side are outcomes the same trades can still produce, which is what the Worst-Case DD figure captures.
- Equity Confidence Bands
The equity fan plots portfolio value (vertical axis) across the run's progression (horizontal axis). Nested shaded bands show, at each point, the middle 50% (25th to 75th percentile), 80% (10th to 90th), and 90% (5th to 95th) of simulated equity paths around the median path, with your actual equity curve drawn on top. The cone is the spread of paths the trades could take over time: a narrow cone means the trajectory was insensitive to trade order, and a cone that widens quickly means small differences in sequencing compound into very different endings. Track where your actual curve rides relative to the median, since sustained position matters more than brief excursions: hugging the median is a representative run, riding the upper band for much of the length is a persistently favorable sequence, and dipping into or below the lower band marks the real path as one of the weaker outcomes.
Rolling Window
Rolling Window splits the backtest into sequential time windows and evaluates each one as its own mini-backtest, so you can see whether the strategy performed consistently across changing conditions or leaned on one or two good stretches. A strategy that only worked in a single period stands out here as a couple of strong windows surrounded by weak ones.
Scorecard
- Consistency
Number of profitable windows out of the total, with the percentage. Higher means the strategy held up across more periods rather than a lucky few.
- Confidence
Reliability rating (high, medium, or low), based on how many windows there were and how comparable they are.
- Avg Return
Average return per window; positive means the strategy was profitable on average across periods.
- Variability
Standard deviation of window returns; lower means more predictable performance from one period to the next.
- Best Window
Highest single-window return.
- Worst Window
Lowest single-window return. A large gap between best and worst signals inconsistent behavior.
- Trend
Direction of returns across the windows over time, from improving to degrading.
Charts
- Window Returns
A bar per window showing that window's total return, with a horizontal line at the average across all windows. This is the fastest read on consistency: bars clustered near the average line mean steady performance period to period, while a few tall bars carrying an otherwise flat or negative set means the headline result rode a couple of exceptional stretches. Bars below zero are losing periods, and their count is what the Consistency score summarizes.
- Multi-Metric Comparison
Each window is drawn as a line traced across eight metric axes (return, Sharpe, max drawdown, win rate, profit factor, average trade, payoff, and trade count), so you can compare every window on every metric at once instead of one at a time. Lines that bunch together mean the strategy behaved similarly whenever it traded, the signature of a stable edge; lines that fan far apart mean the metrics swung hard between periods, so the average hides very different regimes. A single window that diverges on several axes at once is usually the period doing the heavy lifting.
- Window Equity Curves
Each window's equity curve normalized to percent return and aligned to a common start day, overlaid so their shapes compare directly regardless of when they occurred or how large the account was. Curves rising at similar angles mean the strategy made money the same way across periods; one curve shooting far above the pack, or a couple sliding steadily down, shows which windows the overall result depended on. The spread between the curves at the right edge is the same story the Best and Worst Window figures tell, drawn out over time.
Hold-Out
Hold-Out divides the backtest into an in-sample segment the strategy is measured on first and a later out-of-sample segment held back as an honest test. Because the out-of-sample period stands in for data the strategy never had a chance to fit, the gap between the two is the clearest signal of whether an edge generalizes or was tuned to one stretch of history. A result that holds up out-of-sample travels; one that collapses was likely fit to the in-sample period.
Scorecard
- Risk Level
Overall hold-out risk inferred from how far out-of-sample fell short of in-sample; the larger the drop, the higher the level.
- Confidence
Reliability rating: high, medium, or low.
- Avg Degradation
Average drop from in-sample to out-of-sample performance across the metrics; lower is better.
- IS Sharpe
In-sample Sharpe ratio.
- OOS Sharpe
Out-of-sample Sharpe ratio, the honest number to weigh against the in-sample one.
- CAGR Diff
Out-of-sample CAGR minus in-sample CAGR; negative means growth slowed on unseen data.
Charts
- Win Rate
In-sample versus out-of-sample win rate as stacked bars, the won portion filled against the full-height total so the split reads at a glance. Compare the two bars: a similar fill on both means the hit rate carried over to unseen data, while a much shorter out-of-sample fill means the strategy won less often once it left the period it was measured on.
- Max Drawdown
The out-of-sample maximum drawdown drawn as a bullet chart, banded into low, moderate, and high risk zones with a reference marker at the in-sample drawdown. Read where the bar lands relative to both the zones and the marker: a bar reaching well past the in-sample marker, or into the high zone, means losses ran deeper than the in-sample test suggested, which is the more dangerous kind of surprise.
- Total Return
In-sample versus out-of-sample total return as side-by-side bars. A comparable out-of-sample bar means the strategy kept earning on unseen data; a much shorter or negative one means most of the return lived in the period the strategy was fit to.
- CAGR
The same in-sample versus out-of-sample comparison expressed as compound annual growth rate, which puts the two segments on an annualized footing even when they cover different spans. Read it like Total Return, with a shortfall on the out-of-sample bar as the warning.
- Trades
A donut splitting closed trades into in-sample and out-of-sample, with the total at the center. Treat this as a sample-size check: if the out-of-sample slice holds only a handful of trades, read every out-of-sample metric on the view as tentative, since a short test can look strong or weak by chance.
- In-Sample vs Out-of-Sample Equity
The two equity curves, drawn from the independent in-sample and out-of-sample runs, each rebased to a common 100% start and plotted over percent of period elapsed so their shapes line up despite different lengths. Compare the trajectories rather than the endpoints: an out-of-sample curve that climbs with the same character as the in-sample one is the goal, while one that flattens or rolls over shows the edge fading on data the strategy never saw.
Sensitivity
Sensitivity re-runs the strategy many times with its parameters nudged above and below their set values, then measures how much the results move. A strategy whose performance barely changes as you vary its inputs is standing on a broad, stable plateau; one that only works at the exact numbers you picked is balanced on a narrow peak that real markets are unlikely to reproduce.
Scorecard
- Stability
How consistently the Sharpe ratio holds across the variations, where 100% means varying the parameters had no effect.
- Sharpe Range
Lowest to highest Sharpe ratio across the variations; a wide range means the result depends heavily on the exact settings.
- Best Varied
The best variation result relative to the baseline.
- Baseline Sharpe
The Sharpe ratio at the strategy's set parameters, the reference every variation is measured against.
- Avg Varied
Average Sharpe ratio across the variations; well below baseline means most nearby settings do worse.
- Most Sensitive
The parameter with the largest impact, with its impact percentage.
- DD Range
Lowest to highest maximum drawdown across the variations.
- Worst Case DD
Deepest maximum drawdown any variation produced.
- DSR
Deflated Sharpe Ratio, the Sharpe adjusted for how many variations were tested; near or below zero flags a headline result that is likely luck from searching many settings.
Charts
- Sensitivity Heatmap
A grid of parameters (rows) against variation levels (columns), each cell colored by how its Sharpe ratio compares to the baseline, green where a nudge improved it and red where it degraded. Read across a row to see how fragile one parameter is: a row that stays near neutral means the strategy tolerates changes to that input, while a row that turns deep red a step either side of center means small mis-estimates of that value break the result. A mostly calm heatmap is the healthy picture; broad red is a warning the edge is parameter-specific.
- Sharpe Impact
Bidirectional bars ranking the parameters by how far varying each one moves the Sharpe ratio, spreading up and down from a center line. The longer a parameter's bars, the more the result rides on getting that value right, so the parameters at the top are the ones a live market is most likely to punish if your estimate is even a little off.
- Sensitivity Curves
Sharpe ratio plotted against percent variation for each parameter, with a horizontal line at the baseline Sharpe. A flat curve sitting near the baseline means that parameter can drift without much cost; a curve that falls away steeply on either side of center means performance is perched on a narrow setting. A curve whose high point sits away from center shows the chosen value was not the test's best-scoring one, which more often reflects noise than a genuinely better setting.
- 3D Parameter Surface
A three-dimensional surface of Sharpe ratio over the two most sensitive parameters, showing their combined effect rather than one at a time. A broad, gently sloping surface means the strategy works across a wide neighborhood of both settings; a sharp isolated spike means the result needs a specific pairing of the two values, the visual signature of overfitting.
- Stability Band
The baseline equity curve with a shaded band spanning the 10th to 90th percentile of the varied runs around it. A narrow band hugging the baseline means the equity path barely changed as parameters moved, while a wide band means plausible alternative settings would have produced very different account trajectories, so the single baseline curve should be read as one draw from that range rather than a promise.
Robustness
Robustness re-runs the strategy with entry and exit fills pushed back by one to three bars, separately and together, to see how much the edge depends on getting filled exactly when the signal fires. Real fills slip for all kinds of reasons, so a result that survives a delayed fill is far more trustworthy than one whose profit lives entirely in same-bar execution.
Scorecard
- Tolerance
How consistently the Sharpe ratio holds up under delay, where 100% means the delays had no effect.
- Baseline Sharpe
The Sharpe ratio with no delay, the reference for the delayed runs.
- Avg Delayed
Average Sharpe ratio across all the delayed runs; well below baseline means timing matters a lot.
- Worst Case
The weakest delayed run.
- Best Case
The strongest delayed run.
- Entry Sens.
How much delaying entry fills alone hurt the result.
- Exit Sens.
How much delaying exit fills alone hurt the result. Comparing the two shows which side of the trade is fragile.
- Delay Impact
The delay effect measured relative to the strategy's average holding time.
Charts
- Trade Impact
The per-trade profit-and-loss change under each delay scenario, grouped by one, two, and three bars of delay. This shows where the damage lands: if a handful of trades account for most of the loss under delay, the strategy leans on a few precisely-timed fills, whereas a small, even haircut spread across all trades means the edge degrades gracefully. Larger bars at longer delays trace how quickly the cost compounds as fills slip further.
- Multi-Metric Comparison
Each run drawn as a line traced across eight metric axes (Sharpe, return, CAGR, max drawdown, degradation, trades, win rate, and profit factor), with the no-delay baseline emphasized. Delayed lines that track close to the baseline mean the result barely moved when fills slipped; lines that pull away, and the axes where they pull away most, show which metrics decay with delay and by how much.
- Equity Curves
The baseline equity curve overlaid with every delayed run, the best and worst highlighted. Tightly bunched curves mean the account path is largely indifferent to fill timing, the robust picture; a wide fan, or delayed curves drifting well below the baseline, means the strategy's growth depended on catching fills at the signal bar.
Cost Stress
Cost Stress re-runs the strategy with its trading costs multiplied across several levels, so you can see how much headroom the edge has before commissions and slippage eat it. Modeled costs are only an estimate, and real spreads and fills are often worse, so a strategy that clears its own cost assumptions by only a hair is fragile in a way the headline result hides.
Scorecard
- Breakeven
The cost multiplier at which profit crosses zero; the further above 1x, the more cost shock the strategy can absorb.
- Baseline
Profit at the strategy's unmodified costs.
- Profit @ 2x
Profit at twice the modeled cost.
- Sharpe @ 2x
Sharpe ratio at twice the modeled cost.
- Max DD @ 2x
Maximum drawdown at twice the modeled cost.
- Degradation
Performance lost per added unit of cost; steeper means more cost-sensitive.
- Survival
How many core metrics still clear their thresholds at 2x cost (profit still positive, profit factor still above 1, drawdown still contained, and so on).
- Profit @ 3x
Profit at three times the modeled cost.
- Confidence
Reliability rating: high, medium, or low.
Charts
- Metric Degradation Heatmap
A grid of five metrics (profit change, Sharpe, average trade P&L, profit factor, and max drawdown) against rising stress levels, each cell colored by how well that metric survives the added cost. Read down a column to see the strategy's overall health at a given cost level, and across a row to see which metric gives out first as costs climb. A block that stays green well into the higher multipliers is a durable edge; a row that flips red at 2x marks the first thing to break.
- Profit Erosion
Profit plotted against the cost multiplier, with the breakeven point marked where the line crosses zero. The steepness is the read: a line that descends gently and crosses zero far to the right has plenty of cost headroom, while a steep line crossing near 1x means the strategy barely covers its own assumed costs and any real-world slippage would push it into the red.
- Profit %Δ
Percent change in profit at 1x, 2x, and 3x cost, with a survival-threshold line. This and the next three charts share one reading: each shows a single metric at the modeled cost and at two and three times it, and the threshold line marks the level below which that metric is no longer holding up. Bars that stay above the line as cost rises mean the metric survives the stress; a bar dropping below it flags the cost level where that part of the edge fails.
- Sharpe
Sharpe ratio at 1x, 2x, and 3x cost against its survival-threshold line; watch whether it stays positive as costs climb.
- Avg Trade P&L
Average trade profit and loss at 1x, 2x, and 3x cost. Once the average trade turns negative, cost is eating more than the edge produces per trade.
- Profit Factor
Profit factor at 1x, 2x, and 3x cost against a survival line at 1.0, the level where gross profit and gross loss break even.
- Resilience
A resilience score at 1x, 2x, and 3x cost, summarizing how well the strategy holds together at each level in a single bar.
- Equity Curves Under Stress
Equity curves at baseline, 2x, and 3x cost overlaid. Curves that stay close together mean cost has little grip on the account path; a 2x or 3x curve that flattens or turns down while the baseline climbs shows how much of the result was really just sitting above the cost line.
Walk-Forward
Walk-forward analysis asks whether a strategy that gets periodically re-tuned would have kept working on data the tuning never saw. It divides the date range into sequential cycles, re-optimizes your selected parameters on each cycle's in-sample period, applies the winning values unchanged to the out-of-sample period that follows, and grades what survived. The view pairs a scorecard led by Walk-Forward Efficiency with a window timeline, per-window comparisons, a parameter stability panel, and the stitched out-of-sample equity curve.
Scorecard
- WFE
Walk-Forward Efficiency: how much of the optimized in-sample performance survived out-of-sample, measured as annualized out-of-sample return over annualized in-sample return. Marked passing from 50%; a reading above 100% is flagged as an anomaly to investigate, not a strength.
- OOS Return
Total return of the stitched out-of-sample track, built only from bars the optimizer never saw. The smaller figure beneath it is the same track expressed as a CAGR, its steady per-year growth rate.
- OOS Sharpe
Risk-adjusted return of the stitched out-of-sample track, annualized at the strategy's native interval.
- OOS Max DD
Deepest peak-to-trough decline anywhere on the stitched out-of-sample track.
- Risk
Overall risk rating (low, medium, or high) from the WFE band and a battery of checks: whether the stitched track is profitable, whether any single window's drawdown breached the bound, and whether profits are spread across windows rather than concentrated in one. The notes behind the rating list exactly which checks failed.
- Confidence
Reliability rating of the result (high, medium, or low), set from how many trades each out-of-sample window produced and whether any windows produced none. The limitations behind the rating spell out what is thin.
Charts
- Window Timeline
One row per walk-forward cycle on a shared time axis. The muted span is the in-sample period where parameters were optimized; the colored span that follows is the out-of-sample period where the winning parameters were applied unchanged, green when it made money and red when it lost. A dashed dark red span is a window that placed no trades. In rolling mode the rows step forward together; in anchored mode every in-sample span starts at the beginning of the range and grows with each cycle. Click any window to highlight it in every panel.
- In-Sample vs Out-of-Sample
Paired bars per window in run order: the outlined bar is the optimized in-sample return and the filled bar is what those same parameters earned out-of-sample, green or red by outcome. The gap between the pair is the degradation. The dotted line tracks each window's own WFE on the right axis against the dashed 50% line, and it breaks where a window's WFE is unavailable because its in-sample lost money. Dark red window labels mark no-trade windows, which show no filled bar. Consistent small gaps suggest a real edge; large in-sample bars collapsing out-of-sample suggest curve fitting, and a WFE line sliding downhill means the edge is fading over time.
- Window Detail
A parallel-coordinates panel where every line is one window traced across its chosen parameter values and its results: in-sample return, out-of-sample return, WFE, out-of-sample drawdown, and trade count. Lines that hold their level across the return axes with steady parameter picks are the signature of a stable edge; lines that spike in-sample and collapse out-of-sample are not. Dark red lines placed no out-of-sample trades and run along their true zeros. Click a line to highlight that window in every panel.
- Parameter Stability
Each optimized parameter gets its own lane, with windows in time order and the parameter's tested range on the vertical axis. The shaded band covers every value that scored nearly as well as that window's winner, and the brighter the shade, the closer to the best. The stepped line marks the value each window actually chose. A wide, steady band with a calm line means a whole region of values kept working, which is what a robust parameter looks like; a thin or wandering band, or a line that jumps sharply between windows, means the optimizer was chasing whatever worked last time. The lane title states the verdict along with the size of the largest jump.
- Stitched Out-of-Sample Equity
All out-of-sample segments joined into one continuous equity curve: the closest picture of what trading the strategy live, re-optimizing as you go, would have produced. A thinner overlay shows buying and holding the same instrument over the same stitched bars. Alternating background bands mark the window boundaries, and thin dark red slices are no-trade windows where equity simply carried flat. Look for gains spread across many windows rather than one lucky stretch, and for the strategy line holding above the buy-and-hold line: if it cannot, the re-optimization is not earning its keep.
Overfitting
Overfitting detection asks whether a strategy's result is a real edge or an artifact of picking the best of many parameter settings. It builds a pool of variants around your configuration, varying every tunable parameter together within the spread you set, runs each variant over the full period, and judges the pool with combinatorially symmetric cross-validation: every half-and-half split of the history picks a winner on one half and checks how that winner finished on the other. Each ticker gets its own pool and its own result. The view pairs a scorecard led by the Probability of Backtest Overfitting and the Deflated Sharpe Ratio with the trial pool distribution, the in-sample winner's out-of-sample finish, a luck benchmark curve, the in-sample to out-of-sample degradation, and a stochastic dominance comparison. The band above the view states the run's settings: the number of trials, the spread, the ranking metric, and the number of CSCV slices.
Scorecard
- Baseline Sharpe
The annualized Sharpe ratio of your exact configuration over the full period, the reference every panel below is measured against.
- PBO
Probability of Backtest Overfitting: across every half-and-half split of the history, the share of splits where the variant that ranked best on one half finished in the bottom half of the pool on the other. Lower is better; at 50% and above, picking the in-sample winner did no better than a random pick. Labelled robust up to 20%, borderline between 20% and 50%, and likely overfit from 50%.
- DSR
Deflated Sharpe Ratio: the probability that your Sharpe beats the best Sharpe pure luck would produce across the configurations in this pool. The luck benchmark is computed from this pool only, not from everything you have ever tried. Labelled survives deflation from 95%, inconclusive between 50% and 95%, and plausibly luck below 50%. The notes behind the figure also give the probability that the Sharpe beats zero at all.
- OOS Loss
Share of splits where the in-sample winner went on to lose money out-of-sample, meaning a negative out-of-sample Sharpe. Lower is better.
- Risk
Overall risk rating (low, medium, or high), the worse of the PBO band and the DSR band. The notes behind the rating state where each of the two figures landed.
- Confidence
Reliability rating of the result (high, medium, or low), set from how many trials produced usable returns, how many bars the history holds, how long each CSCV slice is, and whether any trials were excluded from the pool. The limitations behind the rating spell out what is thin, along with the track record and data length the pool would need for the statistics to be stable.
Charts
- Trial Sharpe ECDF
A cumulative distribution of full-period annualized Sharpe across every configuration in the pool: the horizontal axis is Sharpe and the height at any point is the share of the pool at or below it, climbing one step per configuration. The ringed point is your configuration at its percentile in the pool, with its rank stated in the panel corner. Dashed vertical lines mark Sharpe zero and the luck bar, the expected maximum Sharpe of a pool this size with no true edge, which is the DSR benchmark. Hover any step to see that variant's settings against your own. Read your point against the luck bar: a ringed point to the right of it is a Sharpe that chance alone is not expected to reach with this many trials, while a point to the left of it is a Sharpe the pool's own spread can produce by luck.
- Logit Distribution
The in-sample winner's out-of-sample finishing position across every CSCV split, drawn as a survival curve: the horizontal axis is the finish position from 1st (best) to last, and the height at each position is the share of splits where the winner finished at that position or worse. A dashed vertical line marks the out-of-sample median of the pool, the marked point where the curve crosses it is the PBO, and the region past the median is shaded. A curve that drops steeply within the first few positions means the in-sample winner usually stayed near the top once re-ranked on unseen data; a curve still high at the median line means the winner often finished in the bottom half, which is what a high PBO records.
- Expected Max Sharpe
The expected maximum Sharpe of a pool of configurations with no true edge, plotted against the number of configurations tried from 2 to 200, the largest pool the validation card allows. The curve is computed from the spread of Sharpes in this pool and rises as the pool grows, because the best of more draws is higher. A horizontal line marks your configuration's Sharpe, a vertical line marks the number of usable trials in this run, and a dot marks where the curve crosses your Sharpe line: the pool size at which the expected maximum from chance alone equals your Sharpe. The panel corner states whether that crossing falls inside this run's pool, beyond it, or not at all within 200 trials. A crossing at a pool size well below the one you ran means a pool that size is expected to produce your Sharpe by luck; a curve that stays under your Sharpe line through 200 trials means it is not.
- Performance Degradation
A density grid of in-sample Sharpe (horizontal axis) against out-of-sample Sharpe (vertical axis), with one point per CSCV split: each split picks its winner by the ranking metric on one half and plots the Sharpe that winner earned on that half against the Sharpe it earned on the unseen half, and brighter cells hold more splits. Both axes are in Sharpe whatever the ranking metric. The dashed diagonal is equal in-sample and out-of-sample Sharpe, so points below it degraded. The solid line is the least-squares fit of out-of-sample Sharpe on in-sample Sharpe, with its slope stated in the panel corner, and the shaded band below out-of-sample zero holds the splits where the selected configuration lost money, the share the OOS Loss figure counts. A cloud hugging the diagonal with a positive slope means the winners' in-sample performance carried over; a cloud sitting well below the diagonal, or a negative slope, means the higher a winner scored in-sample, the worse it tended to do out-of-sample, the signature of overfitting. Changing the ranking metric on the validation card rebuilds this cloud from the winners that metric picks.
- Stochastic Dominance
Two cumulative distributions of out-of-sample Sharpe across every split on the left axis: in-sample winners, the configuration that ranked best in-sample in each split, and all configurations, every configuration in every split, which is the distribution a random pick would draw from. Both are plotted in Sharpe whatever the ranking metric, and a dashed vertical line marks Sharpe zero. The winners' curve sitting at or below the all-configurations curve at every Sharpe, and below it somewhere, is first-order stochastic dominance: the selection procedure puts more of its probability mass at higher Sharpe than a random pick would. The dotted SD2 trace on the right axis is the second-order statistic, the area between the two curves accumulated from the far left up to each Sharpe: SD2 at a Sharpe x is the integral up to x of the all-configurations curve minus the winners' curve. SD2 at or above the dashed zero line everywhere, and above it somewhere, is second-order dominance, the weaker condition under which a risk-averse decision maker prefers the selection procedure to a random pick; first-order dominance implies second-order. Curves that lie on top of each other, or an SD2 trace that dips below zero, mean selecting by the ranking metric did not beat choosing a configuration at random. Hover anywhere for the three values at that Sharpe.
Execution Engine
Overview
The execution engine is the core of Backtest Labs. When you hit execute, it takes your node-based strategy, resolves the graph of connections into an execution order, computes every indicator, evaluates your conditions, and simulates trades against historical market data with realistic cost modeling. This section covers each stage of that pipeline in detail, from how the graph is resolved to how trades are executed and positions are managed.
Graph Resolution
When you execute a strategy, the engine processes your node graphonce for every bar of data in your backtest range. On each bar, it runs through your entire graph in the order determined by how you've connected your nodes. If an EMA feeds into a Crossover node, the EMA always calculates first so the Crossover has fresh data to work with. The engine figures out this ordering automatically from your connections.
Every node runs on every bar, regardless of whether a trade signal is produced. This is how the engine ensures that indicator values, conditions, and signals are always up to date.
When you select multiple tickers, the engine runs your entire strategy graph independently on each ticker's data. Tickers do not share state or interact with each other during execution.
Data Pipeline
Backtest Labs sources stock data from Tiingo and cryptocurrency data from Binance. Both provide standard OHLCV (Open, High, Low, Close, Volume) data, which is what every indicator and chart in the platform operates on.
Available timeframes vary by asset class. Stocks support 1-minute through 12-hour intraday intervals as well as daily, and follow regular US market hours. Crypto supports the same interval range but trades 24/7, which means significantly more data bars per day at shorter intervals.
Price adjustments are applied automatically. Stock prices are adjusted for historical splits so that indicators and charts reflect actual trading conditions rather than raw unadjusted prices. Dividends are tracked separately rather than being folded into the price, which allows dividend analysis and DRIP reinvestment to work correctly. Crypto assets do not have corporate actions, so no adjustments are needed.
Trade Execution
When a Buy or Sell node receives a signal from its connected conditions, it evaluates whether or not to fire. If a node has multiple inputs,all conditions must be true simultaneously for the signal to trigger.
Trades fill at the next bar's open price, not at the bar where the signal fires. This matches how real brokers work: when your conditions trigger at bar close, you can't actually execute at that close because it's already happened. Your order fills at the next available price, which is the following bar's open. Signals that fire on the last bar of the data range are dropped since there is no next bar to fill on.
The platform supports both long and short trading. Buy nodes can open a long position or cover an existing short. Sell nodes can exit a long position or open a new short. Each node's direction is configured in its parameters.
Order types include market, limit, stop, stop-limit, and trailing stop. These are configured directly on the Buy and Sell nodes and determine how the fill price is evaluated relative to the next bar's open.
When multiple buy signals fire consecutively on the same ticker without an intervening sell, those buys are aggregated into a single position. The engine tracks the combined entry cost, total quantity, and weighted average entry price across all entries. The position stays open until a sell signal closes it, at which point the full realized P&L is calculated against the aggregate entry.
Holding periods can enforce minimum and maximum trade durations. A minimum holding period prevents a position from being closed too early, even if a sell signal fires. A maximum holding period forces a position to close after a set number of bars, regardless of signals. Forced closes from max holding periods also execute at the next bar's open for consistency.
As covered in Graph Resolution, each ticker operates with its own independent portfolio. Cash, positions, and trade history are completely isolated between tickers.
Cost Modeling
Every trade in the backtest has commission and slippage applied to simulate realistic execution costs. These are deducted automatically and reflected in your trade log, P&L calculations, and performance metrics.
Slippage adjusts the fill price itself. When you buy, slippage pushes your fill price higher than the market price. When you sell, it pushes your fill price lower. The execution price you see in the trade log already has slippage baked in. This means your realized P&L accounts for the true cost of getting in and out of a position, not just the theoretical market price.
Volume-based slippage scales with how large your trade is relative to the bar's actual volume. A trade that represents 10% of the bar's volume will experience more slippage than one that represents 1%. This models real market impact since larger orders move the market more. If you're testing strategies with large position sizes on low-volume stocks, this is where you'll see the biggest difference between theoretical and realistic results.
Commission is deducted from your cash balance separately from the fill price. The engine enforces minimum and maximum commission bounds per trade regardless of which commission model you use, so very small trades still incur a minimum cost and very large trades are capped.
Dividends & Corporate Actions
The engine automatically processes stock splits and dividends during backtest execution. These are not triggered by your strategy's nodes. They happen based on the actual historical corporate action data for the ticker you're testing.
When a stock split occurs, the engine adjusts your position's share count and average entry price to reflect the split. A 2-for-1 split doubles your shares and halves your entry price. Your P&L remains accurate because both sides of the equation are adjusted. This happens automatically on the bar where the split historically occurred.
When a dividend is paid, the engine either adds the cash directly to your portfolio or reinvests it depending on whether DRIP is enabled. With DRIP on, dividend cash is used to purchase additional shares at the current price, and those shares are added to your existing position. With DRIP off, the dividend is deposited as cash. Either way, dividend events appear in your trade history as separate entries from your signal-driven trades, which means they are reflected in your total return and equity curve.
Dividends are credited on the ex-dividend date at that bar's price. Real brokers deposit dividend cash on the payment date, typically two to six weeks later, and execute DRIP purchases around that date. The engine reinvests immediately on the ex-dividend bar instead, which matches how total-return indexes are calculated and keeps results independent of payment schedules that vary by company and broker.
Eligibility follows the record-date convention: only shares held before the ex-dividend bar's open receive the dividend. A position opened on the ex-dividend bar does not collect that dividend, and a position sold at the ex-dividend bar's open still does, paid as cash.
Validation Engine
The validation engine runs after your main backtest completes, using its results to stress-test your strategy from multiple angles. Each validation method re-runs or resamples your strategy in a different way to answer a specific question about its reliability.
Monte Carlo takes the actual trades from your backtest and randomly resamples them with replacement (the same trade can be drawn more than once, and others not at all) across thousands of simulations. This produces a spread of possible equity curves, summarized as confidence bands, a drawdown distribution, and risk-of-ruin probabilities at drawdown levels from 10% to 50%. It answers the question: how much of your performance is a durable edge versus luck, and how severe could the drawdowns realistically get?
Hold-Out Validation splits your data range into an in-sample period and an out-of-sample period, then runs your strategy on both independently. If performance is significantly stronger on the in-sample data than the out-of-sample data, the strategy may be overfit to the specific conditions it was tested on. Performance is compared across Sharpe, CAGR, return, win rate, and max drawdown, and the average out-of-sample degradation drives a low, medium, or high risk rating.
Rolling Window divides the full date range into sequential windows and runs your strategy independently on each one. This reveals whether performance is consistent across different market conditions or concentrated in a specific time period. It uses 3 to 8 windows (rolling or non-overlapping), and the consistency score is the share of windows that finished profitable.
Cost Stress progressively increases transaction costs beyond your configured levels and re-runs the backtest at each step. Commission and slippage are scaled from 1x up to 3x across six steps to find the breakeven point where the strategy stops being profitable, showing how sensitive your profitability is to cost assumptions.
Execution Robustness delays your trade signals and re-runs the backtest for each delay. It applies positive delays of 1 to 3 bars only (simulating latency, never acting earlier than the signal) across 10 configurations covering entry-only, exit-only, and both delayed together. This tests whether your strategy still works if you are consistently a bar or two late on entries and exits.
Parameter Sensitivity automatically discovers all tunable numeric parameters across your strategy's nodes, varies each one independently, and re-runs the backtest for each variation. Parameters are ranked by how much they affect performance, scored from the coefficient of variation across each parameter's variations, and the two most sensitive parameters from different nodes are automatically selected for the interaction heatmap. This tests whether your results depend on very specific parameter choices or remain stable across a range of values; strategies that collapse with small parameter changes are likely fragile.
Walk-Forward divides your date range into 10 to 25 sequential cycles (up to 12 in anchored mode), each pairing an in-sample period with the out-of-sample period that immediately follows it, with the out-of-sample share set between 10% and 40%. In every cycle the strategy is re-run across every combination of your selected parameters (up to two parameters at up to five values each), the best combination on the in-sample data is picked by your chosen objective (CAR/MDD, Sharpe ratio, profit factor, or CAGR), and the winning values are applied unchanged to the out-of-sample period. In rolling mode the windows slide forward together; in anchored mode the in-sample period always starts at the beginning of the range and grows with each cycle. The out-of-sample segments are then stitched into a single continuous equity track and compared against buying and holding the same bars, and Walk-Forward Efficiency measures how much of the annualized in-sample performance survived out-of-sample, against the 50% passing line. It answers the question: would the strategy have kept working if you had traded it live, re-optimizing as time moved forward, on data the optimizer never saw?
Overfitting Detection builds a pool of 10 to 200 variants of your strategy per ticker: your configuration plus the rest drawn by Latin hypercube sampling, so that every tunable numeric parameter varies together in each variant within a spread of up to 100% around your settings. The draw is seeded from the strategy itself, so an unchanged strategy reproduces the identical pool. Each variant is run over the full period, and the pool's per-bar returns are then put through combinatorially symmetric cross-validation: the history is cut into an even number of equal slices from 8 to 16, every way of choosing half the slices forms an in-sample set with the other half held out, the best variant on the in-sample set is picked by your chosen ranking metric (Sharpe ratio, Sortino ratio, profit factor, or total return), and its out-of-sample rank is recorded. The Probability of Backtest Overfitting is the share of those splits where the in-sample winner finished in the bottom half of the pool out-of-sample, and the Deflated Sharpe Ratio is the probability that your configuration's Sharpe beats the best Sharpe luck alone would produce across this pool, using the pool's own spread of Sharpes as the benchmark. CAR/MDD is not offered as a ranking metric because drawdown depends on the exact bar order, which the cross-validation splits do not preserve. It answers the question: is the edge real, or an artifact of picking the best of many parameter settings?
Code Export
Any strategy can be exported as runnable code in two targets: Python andPine Script. An export reproduces the strategy's signal logic so it can run outside Backtest Labs.
The Python export generates a generate_signals() function, built on TA-Lib, that returns the strategy's buy and sell signals for a bar series you provide. The Pine Script export generates a TradingView indicator that plots buy and sell markers and exposes them as alerts.
Portfolio nodes cannot be exported. Nodes that read live portfolio state (Portfolio Value, Cash Balance, Drawdown, Exposure, Position Count, and Risk Per Trade) depend on the running portfolio that Backtest Labs maintains during a backtest. Standalone Python and charting platforms such as TradingView have no equivalent, so a strategy that uses any of these nodes cannot be exported. The builder flags this and asks you to remove the portfolio node before exporting.
Indicator math is based on TA-Lib, the industry-standard reference library the platform itself uses to compute every indicator. Because the Python export is also TA-Lib-based, it reproduces the platform's indicator values to floating-point tolerance: the signals it produces are the same signals you saw on the platform.
Pine Script matches in nearly all cases, since TradingView's built-in ta.* functions implement the same standard math. A few indicators cannot match exactly, and the export labels these in-line. ATR, MACD, and Supertrend seed their Wilder and EMA averages one bar earlier in Pine than in TA-Lib, so values differ by a tiny, decaying amount over roughly the first period bars, then converge to identical values.Volume Profile needs tick or lower-timeframe data that Pine does not expose to a charting indicator, so its Point of Control and value-area levels are approximated and will differ from Backtest Labs. The Python export reproduces the full histogram exactly.
Exports are signal logic, not execution. A signal activates on the bar its condition is met, computed from that bar's close, and the export emits the signal on that bar. The exports describe when a signal fired, not when a simulated trade was filled.
Execution belongs to your own system. A bar's close is known only after the bar completes, so the earliest an order can fill is the following bar's open. When you wire an export into your broker, automation, or notifications, that system places the order on the next bar. That is the realistic one-bar delay. The exports therefore do notshift the signal forward; shifting it would push your real order a further bar out. Backtest Labs applies this same one-bar fill internally when it simulates trades and draws the equity curve, which is why a Backtest Labs trade marker sits one bar after the signal that triggered it.
For Pine alerts, set the alert to Once Per Bar Close so it triggers on the confirmed bar rather than intrabar on the still-forming live bar.