Skip to content

How to limit a number to a range of values in Pine Script?

How to limit a number to a range of values in Pine Script?

Section titled “How to limit a number to a range of values in Pine Script?”

TL;DR
Use math.clamp(value, min, max) (or pair math.max / math.min) to enforce lower and upper bounds on any series so calculated values stay inside the range you set.

DifficultyBeginner
Time to implement10-15 min
CategoryInputs
//@version=5
indicator("Clamp demo", overlay=false)
value = close - close[1]
clamped = math.clamp(value, -1.5, 1.5)
plot(clamped, "Change clamped to ±1.5")
Tip. `math.clamp()` first appeared in Pine Script v5. On earlier versions, compose `math.max(minValue, math.min(maxValue, value))` for the same effect.

Indicators and strategies frequently calculate metrics that spike outside realistic bounds (ATR-derived position sizes, momentum readings, user inputs). Clamping keeps your logic stable: you avoid oversized orders, sanitize noisy signals, and guarantee downstream formulas receive valid ranges.

  • Apply lower-only, upper-only, or fully clamped ranges around any numeric series.
  • Package clamps in helpers (limitMin, limitMax, limitRange) for reuse.
  • Combine clamped values with plots, alerts, or order sizing.
  • Inspect the before/after impact directly on chart.
CallPurpose
math.max(a, b)Enforces a minimum by returning the larger of two values.
math.min(a, b)Enforces a maximum by returning the smaller of two values.
math.clamp(value, min, max)One-call clamp between lower and upper bounds.
input.float(...)Collects user-configurable limits.
plot(series, ...)Visualises clamped vs unclamped data.
  1. Decide the limits
    Hard-code them, retrieve them from inputs, or compute them from another indicator.

    minPct = input.float(-2.0, "Minimum % move", step=0.1)
    maxPct = input.float(2.0, "Maximum % move", step=0.1)
  2. Clamp the value
    Use helpers for readability, especially when you reuse the logic across the script.

    limitMin(float value, float minVal) => math.max(value, minVal)
    limitMax(float value, float maxVal) => math.min(value, maxVal)
    limitRange(float value, float minVal, float maxVal) => math.clamp(value, minVal, maxVal)
  3. Apply the bounded result
    Feed the clamped number into plots, calculations, or order sizing routines.

    rawChange = 100 * (close / close[1] - 1)
    boundedChange = limitRange(rawChange, minPct, maxPct)
    plot(boundedChange, "Bounded % change")
//@version=5
indicator("ATR-based sizing with clamps", overlay=false)
eosPct = input.float(1.5, "Equity at stake (%)", minval=0.1, step=0.1)
minQty = input.float(0.2, "Minimum qty", minval=0.01, step=0.01)
maxQty = input.float(5.0, "Maximum qty", minval=0.1, step=0.1)
atrLen = input.int(14, "ATR length", minval=1)
atrMult = input.float(1.2, "ATR multiplier", step=0.1)
atrValue = ta.atr(atrLen)
positionRisk = atrValue * atrMult
rawQty = strategy.equity * (eosPct * 0.01) / positionRisk
limitMin(float value, float minVal) => math.max(value, minVal)
limitMax(float value, float maxVal) => math.min(value, maxVal)
limitRange(float value, float minVal, float maxVal) => math.clamp(value, minVal, maxVal)
qtyBounded = limitRange(rawQty, minQty, maxQty)
qtyCeiling = limitMax(rawQty, maxQty)
qtyFloor = limitMin(rawQty, minQty)
plot(rawQty, "Raw quantity", color=color.new(color.orange, 0))
plot(qtyBounded, "Clamped quantity", color=color.new(color.teal, 0), linewidth=2)
plot(qtyCeiling, "Only max applied", color=color.new(color.red, 40))
plot(qtyFloor, "Only min applied", color=color.new(color.blue, 40))
Why this works.
  • The helper functions make intent obvious: floor, ceiling, or full clamp.
  • Plots contrast the raw quantity against each bounded version, making the clamp effect transparent.
  • User inputs control bounds so traders can tighten risk without editing code.
  • Clamp before passing values into order functions (strategy.entry, strategy.exit) to avoid rejections from brokers specifying min/max contract sizes.
  • Consider dynamic bounds (e.g., ATR percentile) instead of static numbers when markets evolve.
  • Remember that math.clamp works with series values; you can clamp per bar using prior calculations.
  • When only one side matters, limitMin or limitMax keeps logic lighter than a full clamp.

Why do I still see values outside the range?

Section titled “Why do I still see values outside the range?”

Check whether you use the clamped result everywhere. It’s easy to continue plotting or executing trades with the unclamped variable.

Yes. Pine casts integers to float automatically inside math.* functions, but you can wrap the output with int() if you need an integer result afterwards.

Wrap the clamp inside an if statement: only apply it when volatility spikes, or when user inputs signal strict mode.

  • math.clamp (or paired math.max / math.min) keeps any number inside a desired range.
  • Helpers like limitRange make multiple clamps reusable and self-documenting.
  • Visualising the bounded and raw values helps confirm the limits behave as intended.
  • Tight control over value ranges prevents runaway order sizes and keeps indicators robust.

Adapted from tradingcode.net, optimised for Algo Trade Analytics users.