Instructions/probuilder · probacktest · proorder · proscreener

ONCE

ONCE in ProBuilder executes an assignment only on the first bar the script processes, keeping initial values from being overwritten on every later bar.

Syntax

probuilder
ONCE variable = expression

How it works

A ProBuilder script executes from top to bottom on every bar of the chart, and variables keep their values from one bar to the next. A plain assignment such as counter = 0 therefore wipes the variable back to zero on each bar. Prefixing the line with ONCE restricts the assignment to the first evaluation only, so later bars leave the variable untouched and it can accumulate state across the chart.

The expression on the right side is evaluated with the data available on that first bar. History is short at that point, so functions that need a lookback, such as lowest[10](low), work with whatever bars exist when the script starts.

The value set by ONCE persists until the script is recalculated from scratch, for example after editing the code, changing the timeframe, or restarting the platform. In trading systems, ONCE is the standard way to define counters, flags, and fixed settings that entry and exit logic reads on every bar.

Examples

Example 1, Tracking new lows against an initial reference (Indicator)

probuilder
// capture the 10-bar low a single time when the script starts
ONCE myFirstLowest = lowest[10](low)
IF low < myFirstLowest OR low < recentLow THEN
  recentLow = low
ELSE
  recentLow = recentLow
ENDIF
RETURN recentLow

myFirstLowest is computed on the first bar only and never refreshed. The indicator then tracks every new low printed after that initial reference.

Example 2, Fixed strategy constants (ProOrder)

probuilder
DEFPARAM CumulateOrders = false
// define risk settings a single time
ONCE stopPoints = 40
ONCE targetPoints = 80
IF NOT onmarket AND close CROSSES OVER Average[50](close) THEN
  BUY 1 CONTRACT AT MARKET
  SET STOP pLOSS stopPoints
  SET TARGET pPROFIT targetPoints
ENDIF

The two risk constants are assigned on the first evaluation and reused on every bar afterward, keeping the configuration in one obvious place at the top of the strategy.

Example 3, Gain since the first scanned bar (ProScreener)

probuilder
// record the close of the first bar in the scanned history
ONCE startLevel = close
gainPct = (close - startLevel) / startLevel * 100
SCREENER[gainPct > 10] (gainPct AS "Gain %")

startLevel freezes the close of the earliest processed bar. Each later bar compares the current close against it, and the screener keeps instruments up more than 10 percent over the scanned window.

Common errors and gotchas

  • Expecting a reset on each session or day. ONCE fires on the first evaluation of the script and never again until a full recalculation. Values that must reset daily need explicit logic, for example comparing the current date against a stored one.
  • First-bar data is thin. The expression is evaluated when history is at its shortest. A lookback function inside ONCE may see fewer bars than requested, which can make the initial value unrepresentative. In strategies, PRELOADBARS controls how much history is available before the start.
  • ONCE on a line that should run per bar. Only true initializations belong behind ONCE. Marking a calculation that depends on current prices makes it permanently stale after bar one.
  • Redundant self-assignment instead of ONCE. Writing x = x on every bar to preserve a value works but hides the intent. ONCE x = startValue states the initialization explicitly and avoids accidental overwrites.
  • IF, conditional logic that typically consumes ONCE-initialized state.
  • ELSE, fallback branch inside that conditional logic.
  • ENDIF, closes an IF block.
  • BarIndex, bar counter, useful for logic keyed to the first bars.
  • DEFPARAM, script-level execution settings, also defined at the top.
  • RETURN, outputs the final value of an indicator.