Alerts

Introduction

TradingView alerts run 24x7 on our servers and do not require users to be logged in to execute. Alerts are created from the charts user interface (UI). You will find all the information necessary to understand how alerts work and how to create them from the charts UI in the Help Center’s About TradingView alerts page.

Some of the alert types available on TradingView (generic alerts, drawing alerts and script alerts on order fill events) are created from symbols or scripts loaded on the chart and do not require specific coding. Any user can create these types of alerts from the charts UI.

Other types of alerts (script alerts triggering on alert() function calls, and alertcondition() alerts) require specific Pine Script™ code to be present in a script to create an alert event before script users can create alerts from them using the charts UI. Additionally, while script users can create script alerts triggering on order fill events from the charts UI on any strategy loaded on their chart, Programmers can specify explicit order fill alert messages in their script for each type of order filled by the broker emulator.

This page covers the different ways Pine Script™ programmers can code their scripts to create alert events from which script users will in turn be able to create alerts from the charts UI. We will cover:

  • How to use the alert() function to alert() function calls in indicators or strategies, which can then be included in script alerts created from the charts UI.
  • How to add custom alert messages to be included in script alerts triggering on the order fill events of strategies.
  • How to use the alertcondition() function to generate, in indicators only, alertcondition() events which can then be used to create alertcondition() alerts from the charts UI.

Keep in mind that:

  • No alert-related Pine Script™ code can create a running alert in the charts UI; it merely creates alert events which can then be used by script users to create running alerts from the charts UI.
  • Alerts only trigger in the realtime bar. The operational scope of Pine Script™ code dealing with any type of alert is therefore restricted to realtime bars only.
  • When an alert is created in the charts UI, TradingView saves a mirror image of the script and its inputs, along with the chart’s main symbol and timeframe to run the alert on its servers. Subsequent changes to your script’s inputs or the chart will thus not affect running alerts previously created from them. If you want any changes to your context to be reflected in a running alert’s behavior, you will need to delete the alert and create a new one in the new context.

Background

The different methods Pine programmers can use today to create alert events in their script are the result of successive enhancements deployed throughout Pine Script™‘s evolution. The alertcondition() function, which works in indicators only, was the first feature allowing Pine Script™ programmers to create alert events. Then came order fill alerts for strategies, which trigger when the broker emulator creates order fill events. Order fill events require no special code for script users to create alerts on them, but by way of the alert_message parameter for order-generating strategy.*() functions, programmers can customize the message of alerts triggering on order fill events by defining a distinct alert message for any number of order fulfillment events.

The alert() function is the most recent addition to Pine Script™. It more or less supersedes alertcondition(), and when used in strategies, provides a useful complement to alerts on order fill events.

Which type of alert is best?

For Pine Script™ programmers, the alert() function will generally be easier and more flexible to work with. Contrary to alertcondition(), it allows for dynamic alert messages, works in both indicators and strategies and the programmer decides on the frequency of alert() events.

While alert() calls can be generated on any logic programmable in Pine, including when orders are sent to the broker emulator in strategies, they cannot be coded to trigger when orders are executed (or filled) because after orders are sent to the broker emulator, the emulator controls their execution and does not report fill events back to the script directly.

When a script user wants to generate an alert on a strategy’s order fill events, he must include those events when creating a script alert on the strategy in the “Create Alert” dialog box. No special code is required in scripts for users to be able to do this. The message sent with order fill events can, however, be customized by programmers through use of the alert_message parameter in order-generating strategy.*() function calls. A combination of alert() calls and the use of custom alert_message arguments in order-generating strategy.*() calls should allow programmers to generate alert events on most conditions occurring in their script’s execution.

The alertcondition() function remains in Pine Script™ for backward compatibility, but it can also be used advantageously to generate distinct alerts available for selection as individual items in the “Create Alert” dialog box’s “Condition” field.

Script alerts

When a script user creates a script alert using the “Create Alert” dialog box, the events able to trigger the alert will vary depending on whether the alert is created from an indicator or a strategy.

A script alert created from an indicator will trigger when:

  • The indicator contains alert() calls.
  • The code’s logic allows a specific alert() call to execute.
  • The frequency specified in the alert() call allows the alert to trigger.

A script alert created from a strategy can trigger on alert() function calls, on order fill events, or both. The script user creating an alert on a strategy decides which type of events he wishes to include in his script alert. While users can create a script alert on order fill events without the need for a strategy to include special code, it must contain alert() calls for users to include alert() function calls in their script alert.

`alert()` function events

The alert() function has the following signature:

alert(message, freq)

message

A “series string” representing the message text sent when the alert triggers. Because this argument allows “series” values, it can be generated at runtime and differ bar to bar, making it dynamic.

freq

An “input string” specifying the triggering frequency of the alert. Valid arguments are:

  • alert.freq_once_per_bar: Only the first call per realtime bar triggers the alert (default value).
  • alert.freq_once_per_bar_close: An alert is only triggered when the realtime bar closes and an alert() call is executed during that script iteration.
  • alert.freq_all: All calls during the realtime bar trigger the alert.

The alert() function can be used in both indicators and strategies. For an alert() call to trigger a script alert configured on alert() function calls, the script’s logic must allow the alert() call to execute, and the frequency determined by the freq parameter must allow the alert to trigger.

Note that by default, strategies are recalculated at the bar’s close, so if the alert() function with the frequency alert.freq_all or alert.freq_once_per_bar is used in a strategy, then it will be called no more often than once at the bar’s close. In order to enable the alert() function to be called during the bar construction process, you need to enable the calc_on_every_tick option.

Using all `alert()` calls

Let’s look at an example where we detect crosses of the RSI centerline:

//@version=6 indicator("All `alert()` calls") r = ta.rsi(close, 20) // Detect crosses. xUp = ta.crossover( r, 50) xDn = ta.crossunder(r, 50) // Trigger an alert on crosses. if xUp alert("Go long (RSI is " + str.tostring(r, "#.00)")) else if xDn alert("Go short (RSI is " + str.tostring(r, "#.00)")) plotchar(xUp, "Go Long", "▲", location.bottom, color.lime, size = size.tiny) plotchar(xDn, "Go Short", "▼", location.top, color.red, size = size.tiny) hline(50) plot(r)

If a script alert is created from this script:

  • When RSI crosses the centerline up, the script alert will trigger with the “Go long…” message. When RSI crosses the centerline down, the script alert will trigger with the “Go short…” message.
  • Because no argument is specified for the freq parameter in the alert() call, the default value of alert.freq_once_per_bar will be used, so the alert will only trigger the first time each of the alert() calls is executed during the realtime bar.
  • The message sent with the alert is composed of two parts: a constant string and then the result of the str.tostring() call which will include the value of RSI at the moment where the alert() call is executed by the script. An alert message for a cross up would look like: “Go long (RSI is 53.41)“.
  • Because a script alert always triggers on any occurrence of a call to alert(), as long as the frequency used in the call allows for it, this particular script does not allow a script user to restrict his script alert to longs only, for example.

Note that:

  • Contrary to an alertcondition() call which is always placed at column 0 (in the script’s global scope), the alert() call is placed in the local scope of an if branch so it only executes when our triggering condition is met. If an alert() call was placed in the script’s global scope at column 0, it would execute on all bars, which would likely not be the desired behavior.
  • An alertcondition() could not accept the same string we use for our alert’s message because of its use of the str.tostring() call. alertcondition() messages must be constant strings.

Lastly, because alert() messages can be constructed dynamically at runtime, we could have used the following code to generate our alert events:

// Trigger an alert on crosses. if xUp or xDn firstPart = (xUp ? "Go long" : "Go short") + " (RSI is " alert(firstPart + str.tostring(r, "#.00)"))

Using selective `alert()` calls

When users create a script alert on alert() function calls, the alert will trigger on any call the script makes to the alert() function, provided its frequency constraints are met. If you want to allow your script’s users to select which alert() function call in your script will trigger a script alert, you will need to provide them with the means to indicate their preference in your script’s inputs, and code the appropriate logic in your script. This way, script users will be able to create multiple script alerts from a single script, each behaving differently as per the choices made in the script’s inputs prior to creating the alert in the charts UI.

Suppose, for our next example, that we want to provide the option of triggering alerts on only longs, only shorts, or both. You could code your script like this:

//@version=6 indicator("Selective `alert()` calls") detectLongsInput = input.bool(true, "Detect Longs") detectShortsInput = input.bool(true, "Detect Shorts") repaintInput = input.bool(false, "Allow Repainting") r = ta.rsi(close, 20) // Detect crosses. xUp = ta.crossover( r, 50) xDn = ta.crossunder(r, 50) // Only generate entries when the trade's direction is allowed in inputs. enterLong = detectLongsInput and xUp and (repaintInput or barstate.isconfirmed) enterShort = detectShortsInput and xDn and (repaintInput or barstate.isconfirmed) // Trigger the alerts only when the compound condition is met. if enterLong alert("Go long (RSI is " + str.tostring(r, "#.00)")) else if enterShort alert("Go short (RSI is " + str.tostring(r, "#.00)")) plotchar(enterLong, "Go Long", "▲", location.bottom, color.lime, size = size.tiny) plotchar(enterShort, "Go Short", "▼", location.top, color.red, size = size.tiny) hline(50) plot(r)

Note how:

  • We create a compound condition that is met only when the user’s selection allows for an entry in that direction. A long entry on a crossover of the centerline only triggers the alert when long entries have been enabled in the script’s Inputs.
  • We offer the user to indicate his repainting preference. When he does not allow the calculations to repaint, we wait until the bar’s confirmation to trigger the compound condition. This way, the alert and the marker only appear at the end of the realtime bar.
  • If a user of this script wanted to create two distinct script alerts from this script, i.e., one triggering only on longs, and one only on shorts, then he would need to:
    • Select only “Detect Longs” in the inputs and create a first script alert on the script.
    • Select only “Detect Shorts” in the Inputs and create another script alert on the script.

In strategies

alert() function calls can be used in strategies also, with the provision that strategies, by default, only execute on the close of realtime bars. Unless calc_on_every_tick = true is used in the strategy() declaration statement, all alert() calls will use the alert.freq_once_per_bar_close frequency, regardless of the argument used for freq.

While script alerts on strategies will use order fill events to trigger alerts when the broker emulator fills orders, alert() can be used advantageously to generate other alert events in strategies.

This strategy creates alert() function calls when RSI moves against the trade for three consecutive bars:

//@version=6 strategy("Strategy with selective `alert()` calls") r = ta.rsi(close, 20) // Detect crosses. xUp = ta.crossover( r, 50) xDn = ta.crossunder(r, 50) // Place orders on crosses. if xUp strategy.entry("Long", strategy.long) else if xDn strategy.entry("Short", strategy.short) // Trigger an alert when RSI diverges from our trade's direction. divInLongTrade = strategy.position_size > 0 and ta.falling(r, 3) divInShortTrade = strategy.position_size < 0 and ta.rising( r, 3) if divInLongTrade alert("WARNING: Falling RSI", alert.freq_once_per_bar_close) if divInShortTrade alert("WARNING: Rising RSI", alert.freq_once_per_bar_close) plotchar(xUp, "Go Long", "▲", location.bottom, color.lime, size = size.tiny) plotchar(xDn, "Go Short", "▼", location.top, color.red, size = size.tiny) plotchar(divInLongTrade, "WARNING: Falling RSI", "•", location.top, color.red, size = size.tiny) plotchar(divInShortTrade, "WARNING: Rising RSI", "•", location.bottom, color.lime, size = size.tiny) hline(50) plot(r)

If a user created a script alert from this strategy and included both order fill events and alert() function calls in his alert, the alert would trigger whenever an order is executed, or when one of the alert() calls was executed by the script on the realtime bar’s closing iteration, i.e., when barstate.isrealtime and barstate.isconfirmed are both true. The alert() function events in the script would only trigger the alert when the realtime bar closes because alert.freq_once_per_bar_close is the argument used for the freq parameter in the alert() calls.

Order fill events

When a script alert is created from an indicator, it can only trigger on alert() function calls. However, when a script alert is created from a strategy, the user can specify that order fill events also trigger the script alert. An order fill event is any event generated by the broker emulator which causes a simulated order to be executed. It is the equivalent of a trade order being filled by a broker/exchange. Orders are not necessarily executed when they are placed. In a strategy, the execution of orders can only be detected indirectly and after the fact, by analyzing changes in built-in variables such as strategy.opentrades or strategy.position_size. Script alerts configured on order fill events are thus useful in that they allow the triggering of alerts at the precise moment of an order’s execution, before a script’s logic can detect it.

Pine Script™ programmers can customize the alert message sent when specific orders are executed. While this is not a pre-requisite for order fill events to trigger, custom alert messages can be useful because they allow custom syntax to be included with alerts in order to route actual orders to a third-party execution engine, for example. Specifying custom alert messages for specific order fill events is done by means of the alert_message parameter in functions which can generate orders: strategy.close(), strategy.entry(), strategy.exit() and strategy.order().

The argument used for the alert_message parameter is a “series string”, so it can be constructed dynamically using any variable available to the script, as long as it is converted to string format.

Let’s look at a strategy where we use the alert_message parameter in both our strategy.entry() calls:

//@version=6 strategy("Strategy using `alert_message`") r = ta.rsi(close, 20) // Detect crosses. xUp = ta.crossover( r, 50) xDn = ta.crossunder(r, 50) // Place order on crosses using a custom alert message for each. if xUp strategy.entry("Long", strategy.long, stop = high, alert_message = "Stop-buy executed (stop was " + str.tostring(high) + ")") else if xDn strategy.entry("Short", strategy.short, stop = low, alert_message = "Stop-sell executed (stop was " + str.tostring(low) + ")") plotchar(xUp, "Go Long", "▲", location.bottom, color.lime, size = size.tiny) plotchar(xDn, "Go Short", "▼", location.top, color.red, size = size.tiny) hline(50) plot(r)

Note that:

  • We use the stop parameter in our strategy.entry() calls, which creates stop-buy and stop-sell orders. This entails that buy orders will only execute once price is higher than the high on the bar where the order is placed, and sell orders will only execute once price is lower than the [low] on the bar where the order is placed.
  • The up/down arrows which we plot with plotchar() are plotted when orders are placed. Any number of bars may elapse before the order is actually executed, and in some cases the order will never be executed because price does not meet the required condition.
  • Because we use the same id argument for all buy orders, any new buy order placed before a previous order’s condition is met will replace that order. The same applies to sell orders.
  • Variables included in the alert_message argument are evaluated when the order is executed, so when the alert triggers.

When the alert_message parameter is used in a strategy’s order-generating strategy.*() function calls, script users must include the {{strategy.order.alert_message}} placeholder in the “Create Alert” dialog box’s “Message” field when creating script alerts on order fill events. This is required so the alert_message argument used in the order-generating strategy.*() function calls is used in the message of alerts triggering on each order fill event. When only using the {{strategy.order.alert_message}} placeholder in the “Message” field and the alert_message parameter is present in only some of the order-generating strategy.*() function calls in your strategy, an empty string will replace the placeholder in the message of alerts triggered by any order-generating strategy.*() function call not using the alert_message parameter.

While other placeholders can be used in the “Create Alert” dialog box’s “Message” field by users creating alerts on order fill events, they cannot be used in the argument of alert_message.

`alertcondition()` events

The alertcondition() function allows programmers to create individual alertcondition events in their indicators. One indicator may contain more than one alertcondition() call. Each call to alertcondition() in a script will create a corresponding alert selectable in the “Condition” dropdown menu of the “Create Alert” dialog box.

While the presence of alertcondition() calls in a strategy script will not cause a compilation error, alerts cannot be created from them.

The alertcondition() function has the following signature:

alertcondition(condition, title, message)

condition

A “series bool” value (true or false) which determines when the alert will trigger. It is a required argument. When the value is true the alert will trigger. When the value is false the alert will not trigger. Contrary to alert() function calls, alertcondition() calls must start at column zero of a line, so cannot be placed in conditional blocks.

title

A “const string” optional argument that sets the name of the alert condition as it will appear in the “Create Alert” dialog box’s “Condition” field in the charts UI. If no argument is supplied, “Alert” will be used.

message

A “const string” optional argument that specifies the text message to display when the alert triggers. The text will appear in the “Message” field of the “Create Alert” dialog box, from where script users can then modify it when creating an alert. As this argument must be a “const string”, it must be known at compilation time and thus cannot vary bar to bar. It can, however, contain placeholders which will be replaced at runtime by dynamic values that may change bar to bar. See this page’s Placeholders section for a list.

The alertcondition() function does not include a freq parameter. The frequency of alertcondition() alerts is determined by users in the “Create Alert” dialog box.

Using one condition

Here is an example of code creating alertcondition() events:

//@version=6 indicator("`alertcondition()` on single condition") r = ta.rsi(close, 20) xUp = ta.crossover( r, 50) xDn = ta.crossunder(r, 50) plot(r, "RSI") hline(50) plotchar(xUp, "Long", "▲", location.bottom, color.lime, size = size.tiny) plotchar(xDn, "Short", "▼", location.top, color.red, size = size.tiny) alertcondition(xUp, "Long Alert", "Go long") alertcondition(xDn, "Short Alert", "Go short ")

Because we have two alertcondition() calls in our script, two different alerts will be available in the “Create Alert” dialog box’s “Condition” field: “Long Alert” and “Short Alert”.

If we wanted to include the value of RSI when the cross occurs, we could not simply add its value to the message string using str.tostring(r), as we could in an alert() call or in an alert_message argument in a strategy. We can, however, include it using a placeholder. This shows two alternatives:

alertcondition(xUp, "Long Alert", "Go long. RSI is {{plot_0}}") alertcondition(xDn, "Short Alert", 'Go short. RSI is {{plot("RSI")}}')

Note that:

  • The first line uses the {{plot_0}} placeholder, where the plot number corresponds to the order of the plot in the script.
  • The second line uses the {{plot("[plot_title]")}} type of placeholder, which must include the title of the plot() call used in our script to plot RSI. Double quotes are used to wrap the plot’s title inside the {{plot("RSI")}} placeholder. This requires that we use single quotes to wrap the message string.
  • Using one of these methods, we can include any numeric value that is plotted by our indicator, but as strings cannot be plotted, no string variable can be used.

Using compound conditions

If we want to offer script users the possiblity of creating a single alert from an indicator using multiple alertcondition() calls, we will need to provide options in the script’s inputs through which users will indicate the conditions they want to trigger their alert before creating it.

This script demonstrates one way to do it:

//@version=6 indicator("`alertcondition()` on multiple conditions") detectLongsInput = input.bool(true, "Detect Longs") detectShortsInput = input.bool(true, "Detect Shorts") r = ta.rsi(close, 20) // Detect crosses. xUp = ta.crossover( r, 50) xDn = ta.crossunder(r, 50) // Only generate entries when the trade's direction is allowed in inputs. enterLong = detectLongsInput and xUp enterShort = detectShortsInput and xDn plot(r) plotchar(enterLong, "Go Long", "▲", location.bottom, color.lime, size = size.tiny) plotchar(enterShort, "Go Short", "▼", location.top, color.red, size = size.tiny) hline(50) // Trigger the alert when one of the conditions is met. alertcondition(enterLong or enterShort, "Compound alert", "Entry")

Note how the alertcondition() call is allowed to trigger on one of two conditions. Each condition can only trigger the alert if the user enables it in the script’s inputs before creating the alert.

Placeholders

These placeholders can be used in the message argument of alertcondition() calls. They will be replaced with dynamic values when the alert triggers. They are the only way to include dynamic values (values that can vary bar to bar) in alertcondition() messages.

Note that users creating alertcondition() alerts from the “Create Alert” dialog box in the charts UI are also able to use these placeholders in the dialog box’s “Message” field.

{{exchange}}

Exchange of the symbol used in the alert (NASDAQ, NYSE, MOEX, etc.). Note that for delayed symbols, the exchange will end with “_DL” or “_DLY.” For example, “NYMEX_DL.”

{{interval}}

Returns the timeframe of the chart the alert is created on. Note that Range charts are calculated based on 1m data, so the placeholder will always return “1” on any alert created on a Range chart.

{{open}}, {{high}}, {{low}}, {{close}}, {{volume}}

Corresponding values of the bar on which the alert has been triggered.

{{plot_0}}, {{plot_1}}, […], {{plot_19}}

Value of the corresponding plot number. Plots are numbered from zero to 19 in order of appearance in the script, so only one of the first 20 plots can be used. For example, the built-in “Volume” indicator has two output series: Volume and Volume MA, so you could use the following:

alertcondition(volume > ta.sma(volume,20), "Volume alert", "Volume ({{plot_0}}) > average ({{plot_1}})")

{{plot("[plot_title]")}}

This placeholder can be used when one needs to refer to a plot using the title argument used in a plot() call. Note that double quotation marks (") must be used inside the placeholder to wrap the title argument. This requires that a single quotation mark (') be used to wrap the message string:

//@version=6 indicator("") r = ta.rsi(close, 14) xUp = ta.crossover(r, 50) plot(r, "RSI", display = display.none) alertcondition(xUp, "xUp alert", message = 'RSI is bullish at: {{plot("RSI")}}')

{{ticker}}

Ticker of the symbol used in the alert (AAPL, BTCUSD, etc.).

{{time}}

Returns the time at the beginning of the bar. Time is UTC, formatted as yyyy-MM-ddTHH:mm:ssZ, so for example: 2019-08-27T09:56:00Z.

{{timenow}}

Current time when the alert triggers, formatted in the same way as {{time}}. The precision is to the nearest second, regardless of the chart’s timeframe.

Avoiding repainting with alerts

The most common instances of repainting traders want to avoid with alerts are ones where they must prevent an alert from triggering at some point during the realtime bar when it would not have triggered at its close. This can happen when these conditions are met:

  • The calculations used in the condition triggering the alert can vary during the realtime bar. This will be the case with any calculation using high, low or close, for example, which includes almost all built-in indicators. It will also be the case with the result of any request.security() call using a higher timeframe than the chart’s, when the higher timeframe’s current bar has not closed yet.
  • The alert can trigger before the close of the realtime bar, so with any frequency other than “Once Per Bar Close”.

The simplest way to avoid this type of repainting is to configure the triggering frequency of alerts so they only trigger on the close of the realtime bar. There is no panacea; avoiding this type of repainting always entails waiting for confirmed information, which means the trader must sacrifice immediacy to achieve reliability.

Note that other types of repainting such as those documented in our Repainting section may not be preventable by simply triggering alerts on the close of realtime bars.