Instructions/probuilder · probacktest · proorder · proscreener

LowestBars

LowestBars in ProBuilder returns the offset in bars to the lowest value of a series over a period, with 0 meaning the current bar holds the lowest value.

Syntax

probuilder
offset = LowestBars[Period](source)

Parameters

NameTypeDefaultDescription
PeriodintegerrequiredNumber of past bars included in the search, counting the current bar.
sourceseriesrequiredThe data series to scan, such as close, low, high, or any calculated series.

How it works

LowestBars scans the last Period bars of the given series and reports the position of the minimum as an offset from the current bar. The count is zero-based: 0 is the current bar, 1 is one bar back. The companion function Lowest returns the minimum value itself, while LowestBars returns where that minimum sits, which is what timing logic usually needs.

When several bars share the same minimum value, the function reports the occurrence closest to the current bar, that is, the smallest offset. If the chart holds fewer bars than Period, the search simply covers the bars that are available.

The offset feeds naturally into bar-indexed expressions. For example, close[LowestBars[20](low)] reads the close of the bar where the 20-bar lowest low was made. The result also acts as a freshness measure: a small offset means the market printed its period low recently, a large offset means the low is aging and has not been challenged for many bars.

According to the source behavior, the function returns -1 when no lower value can be resolved within the requested range, so code that uses the result as an index should guard against negative values.

Examples

Example 1, Locating the 20-bar lowest low (Indicator)

probuilder
// Offset in bars to the lowest low of the last 20 bars
a = LowestBars[20](low)
RETURN a

The plotted value drops to 0 whenever the current bar makes a new 20-bar low, then climbs by one on each bar that fails to break it.

Example 2, Entering only when the low is old (ProOrder)

probuilder
// The 50-bar lowest low must be at least 20 bars old,
// meaning no fresh low has printed recently
lowAge = LowestBars[50](low)

IF lowAge >= 20 AND close crosses over average[20](close) THEN
  BUY 1 CONTRACT AT MARKET
ENDIF

SET STOP %LOSS 2

LowestBars acts as a stabilization filter: the strategy only buys when the most recent period low was set at least 20 bars ago.

Example 3, Screening for a fresh period low (ProScreener)

probuilder
// Flag instruments that printed their 100-bar low within the last 3 bars
recentLow = LowestBars[100](low)

SCREENER[recentLow <= 3 AND recentLow >= 0] (recentLow AS "Bars since low")

The screener lists markets trading at or near a fresh 100-bar low and shows how many bars ago that low occurred.

Common errors and gotchas

  • Offset confused with value. LowestBars returns a bar count, not a price. To read the minimum itself use Lowest[Period](source), or index the series with the offset.
  • Zero-based counting. A result of 0 refers to the current bar. Treating 0 as "no low found" silently discards the most important case, a fresh low on the bar being evaluated.
  • Negative result used as an index. When the function cannot resolve a lower value it returns -1, and expressions such as low[LowestBars[20](low)] then index a negative offset. Check the result before using it as an index.
  • Ties resolve to the nearest bar. When two bars share the exact minimum, the smaller offset wins. Logic that expects the oldest occurrence will misread flat or gapped series.
  • Lowest, returns the lowest value of a series over a period.
  • Highest, returns the highest value of a series over a period.
  • HighestBars, offset in bars to the highest value, the mirror function.
  • BarsSince, counts bars since a condition was last true.
  • BarIndex, zero-based position of the current bar in the loaded history.
  • Summation, sums a series over a period.
  • DRAWTEXT, prints values on the chart, useful for verifying offsets.