Reviewed: 14 August 2026
Use alert.freq_once_per_bar_close when the decision must use the completed candle. Use alert.freq_once_per_bar when an earlier intrabar alert is more important and you accept that the condition may disappear before close. Use alert.freq_all only when you deliberately want every eligible realtime execution.
Frequency controls when an alert() call is allowed to trigger. It does not repair repainting elsewhere in the script, guarantee webhook delivery, or prevent a broker from receiving the same order twice.
The three Pine Script alert frequencies
| Frequency | Allowed trigger | Typical use | Main risk |
|---|---|---|---|
alert.freq_once_per_bar | The first eligible call during each realtime bar | One early signal per candle | The condition can be false by candle close |
alert.freq_once_per_bar_close | An eligible call on the realtime bar’s closing execution | Confirmed-candle alerts | Later notification; underlying data can still be flawed |
alert.freq_all | Every eligible call during the realtime bar | Deliberate tick-by-tick monitoring | Repeated alerts while a condition remains true |
If the freq argument is omitted, alert.freq_once_per_bar is the default.
Why once per bar can fire before the candle is finished
An indicator recalculates when the realtime price updates. Suppose a 15-minute candle trades above a moving average halfway through the bar and falls back below it before close. With alert.freq_once_per_bar, the first qualifying execution can send the alert immediately. The candle does not need to remain above the average.
With alert.freq_once_per_bar_close, the call can trigger only on the bar’s closing execution. That reduces intrabar reversals, but it necessarily waits until the 15-minute candle closes.
A minimal Pine Script v6 example
//@version=6
indicator("Confirmed crossover alert", overlay = true)
int length = input.int(20, "EMA length", minval = 1)
float average = ta.ema(close, length)
bool crossedUp = ta.crossover(close, average)
if crossedUp
alert("Close crossed above EMA", alert.freq_once_per_bar_close)
plot(average, "EMA")
This example sends a script alert only when the crossover is true on the realtime bar’s closing update. After adding the indicator to a chart, create an alert and choose the script’s Any alert() function call condition.
Assumptions: the example uses the chart symbol and timeframe, contains no higher-timeframe request, and does not place orders. It does not prove profitability or account for slippage, latency or broker rejection.
Strategies behave differently from indicators
By default, a Pine strategy recalculates at the close of each realtime bar. In that normal mode, changing an alert() call to alert.freq_all does not make the strategy run on every price update. TradingView’s documentation explains that intrabar strategy execution requires calc_on_every_tick = true or the matching strategy setting.
Turning on every-tick recalculation is not a harmless speed switch. Historical bars do not contain the same tick-by-tick path as realtime bars, so a strategy can behave differently after reloading. Order-fill events are another alert source and are not governed in exactly the same way as ordinary alert() calls.
Why bar-close frequency is not a complete repainting fix
A closing alert confirms the chart bar, but a script can still use data incorrectly. Common examples include:
- Requesting an unconfirmed higher-timeframe value.
- Using future-looking settings in a data request.
- Running on Renko, range or another synthetic chart.
- Using a value that changes after a data correction.
- Assuming an existing alert automatically updates when the script changes.
TradingView alerts run from a saved copy of the script and its inputs. Delete and recreate the alert after changing the code, inputs, symbol or timeframe. For higher-timeframe patterns, follow the non-repainting Pine Script guide.
Prevent duplicate webhook orders outside Pine
Even a well-chosen frequency is not an order-safety system. Networks retry, workers restart, users create duplicate alerts, and a broker can take time to return an order status. A webhook receiver should validate the payload and reject repeated events.
Include a stable event identifier such as the strategy name, symbol, timeframe, bar timestamp and action. Store accepted identifiers for a suitable period. Before sending another order, check the previous response and the broker’s order book. Do not treat a network timeout as proof that an order failed.
If the destination is Kite Connect, also apply the operational checks in the TradingView-to-Zerodha webhook guide.
Which frequency should you choose?
- Manual notification: once per bar can be reasonable when you want time to inspect the chart.
- Webhook that acts on candle-close logic: once per bar close is the safer default.
- Intrabar monitoring: once per bar limits repeated messages but can still signal before close.
- Every-tick event stream: use all only with explicit deduplication and rate controls.
- Strategy order fills: evaluate order-fill alerts separately from ordinary script calls.
Pre-launch alert checklist
- Confirm whether the trading rule is intrabar or candle-close.
- Test on the exact symbol, session and timeframe.
- Check every
request.security()call for confirmed data. - Create the alert only after the final code and inputs are on the chart.
- Use a unique event identifier in each webhook payload.
- Log the received time, event ID, validation result and broker response.
- Paper-test through live candles; historical plots cannot reproduce webhook delivery.
- Set a fail-safe that blocks new orders when state is uncertain.
Primary sources
Need help tracing an alert? Share the smallest reproducible script, the chart timeframe, the alert log and a redacted webhook event. Never send API secrets or account credentials.

Leave a Reply