Skip to content
Algo Trade Analytics Docs

Pine Script math.clamp: What to Use Instead

TL;DR Pine Script has no math.clamp(). Compose the equivalent with math.max(minVal, math.min(maxVal, value)) 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=6
indicator("Clamp demo", overlay=false)
clamp(float value, float minVal, float maxVal) =>
math.max(minVal, math.min(maxVal, value))
value = close - close[1]
clamped = clamp(value, -1.5, 1.5)
plot(clamped, "Change clamped to ±1.5")
There is no built-in clamp. Unlike C++, Rust, or Python's numpy.clip, Pine Script's math namespace does not include a clamp() function in any version, v5 or v6. Calling math.clamp() fails to compile with "Could not find function or function reference 'math.clamp'". The two-call composition above is the idiomatic equivalent, and it is what the rest of this guide uses.

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.max(minVal, math.min(maxVal, value))Full clamp between lower and upper bounds — the math.clamp replacement.
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.max(minVal, math.min(maxVal, value))

    Order matters only if your bounds can cross: math.max(minVal, ...) applied last guarantees the floor wins when 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=6
// `strategy.equity` is only available in a strategy — this example must not be
// declared as an indicator.
strategy("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.max(minVal, math.min(maxVal, value))
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.
  • The math.max / math.min pair works with series values, so you can clamp per bar using prior calculations.
  • When only one side matters, limitMin or limitMax keeps logic lighter than a full clamp.

Why does math.clamp() throw “Could not find function or function reference”?

Section titled “Why does math.clamp() throw “Could not find function or function reference”?”

Because it does not exist. Pine Script’s math namespace covers abs, avg, ceil, floor, log, max, min, pow, round, sign, sqrt, sum, the trigonometric functions, todegrees and toradians — but never clamp, in any version. Replace the call with math.max(minVal, math.min(maxVal, value)).

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.

  • Pine Script has no math.clampmath.max(minVal, math.min(maxVal, value)) is the equivalent.
  • 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.