Skip to content
ChartTailor
WorkServicesPricingField NotesAbout Start a build
← Pine Discoveries

Alert frequency is a timing contract, not a dropdown

TradingView alert frequency settings decide what the receiver is allowed to believe about a signal.

Alert frequency is one of those Pine settings that looks operational until it breaks a trade flow. The wording in the alert dialog makes it feel like a preference: once, once per bar, once per bar close, all. In a real indicator, especially one driving a webhook, it is closer to a timing contract. It says when the script is allowed to speak and when the receiver is allowed to act.

This is worth writing down because a lot of alert problems are misdiagnosed as bad conditions. The condition is often fine. What is wrong is that the script is producing a provisional state while the alert is configured as if the state were final, or the script is running only on closes while the user expects intrabar updates.

Why this catches people

The tempting shortcut is to think of alert.freq_once_per_bar_close as the safe answer for everything. It is safe in the narrow sense that it avoids many intrabar flips. It is not automatically right. A scalping alert that must react while the bar is still forming will feel late. A confirmation alert that must never move should usually wait for the bar close. A strategy alert may behave differently again because strategies do not have the same default realtime cadence as indicators.

Frequency also interacts with script type. Indicators can call alert() during realtime updates. Strategies normally calculate on the bar close unless they are configured otherwise. That means the same-looking condition can have a different alert surface depending on whether it lives in an indicator, a strategy, or an order event message.

The Pine bit

The useful distinction is not “fast” versus “slow”. It is “forming” versus “confirmed”. Once I name the state, the frequency choice usually becomes obvious. If the payload is a heads-up, the alert can fire while the bar is live and the receiver should treat it as provisional. If the payload is an execution instruction, the script should normally wait until the condition is confirmed and include that state in the payload.

A small pattern I trust is to make the timing visible in the code instead of hiding it in the alert dialog. The alert frequency still matters, but the script itself says what kind of event it is sending.

//@version=6
indicator("Confirmed alert example", overlay = true)

setup = close > ta.highest(high[1], 20)
confirmedSetup = setup and barstate.isconfirmed

if confirmedSetup
    alert("breakout_confirmed", alert.freq_once_per_bar_close)

How I handle it in builds

For client work, I write the alert spec before I polish the visual. I want to know whether the alert is a setup, a confirmation, a cancellation, or an order event. I want to know whether repeated alerts on the same bar are useful or dangerous. If the downstream tool cannot handle duplicates, I add a state key or a bar-time key so the receiver can reject repeated messages.

This is especially important when users test in Bar Replay or by watching a live chart for five minutes. A quick visual test rarely proves the alert contract. It only proves that one path through the realtime bar produced the expected message. The real test is whether the alert behaves the same way when the condition appears, disappears, reappears, and then closes in or out of confirmation.

Where this shows up

A good field test is to put the same condition under two different alert modes and watch the current bar, not the historical chart. If the condition turns true, false, and true again before the bar closes, the script has to decide whether that was one idea, two events, or a cancelled event followed by a new one. TradingView can limit how often the message is sent, but it cannot decide what those state changes mean for the receiver.

I like to test a quiet market and a fast market. In a quiet market, almost any alert design looks sensible. In a fast market, duplicate prevention, bar-close confirmation, and intrabar warnings become much easier to judge. If the script is meant to trigger external automation, the fast-market test is not optional.

How I test it

I test this by checking the alert log, not only the chart. The chart tells me when a condition appeared. The log tells me what TradingView actually sent. If a webhook is involved, I compare the received payload with the intended state. That closes the gap between visual signal and operational event.

Checks before I trust it

  • Decide whether the alert is provisional, confirmed, cancelled, or an update.
  • Use barstate.isconfirmed deliberately instead of assuming the alert dialog will solve repainting.
  • Remember that strategies need their own cadence decisions, especially around intrabar calculation.
  • Include enough state in webhook messages for the receiver to reject duplicates.
  • Test the condition on a live-forming bar, not only on static historical bars.

The useful rule is that alert frequency is not a convenience setting. It is part of the signal definition. Once that is written down, the alert becomes easier to explain, easier to test, and much less likely to surprise the person relying on it.