Skip to content
ChartDeck ChartScript docs Account Open the terminal

Alerts

Alert conditions with alert.on, messages with alert.send, script alerts checked on ChartDeck's servers, triggers, placeholders and limits.

A script can describe the moments worth being told about: a cross, a breakout, a level touched. ChartScript has two ways to do that. alert.on declares a named condition, and alert.send sends a message from your code when something happens.

#alert.on: named conditions

ChartScriptFragmentOpen in editor
const fast = ta.ema(close, 9)
const slow = ta.ema(close, 21)
alert.on(ta.crossover(fast, slow), "Bull cross", "{{ticker}} fast EMA crossed above the slow one")
  • condition is a bool series: the alert condition is met on bars where it is true.
  • title is the name shown in the list of conditions. It must be a constant string.
  • message is the default text of the alert, also a constant; it may contain placeholders.

alert.on must be at the top level of the script, never inside an if, loop or function: the list of conditions has to be known without running the script. Inside a branch it is error CS3201:

ChartScriptError: CS3201
//@chartscript 1
indicator("Alert in a branch")
if (close > open) {
    alert.on(close > high[1], "Breakout")
}

Compute the condition first and pass it in instead: alert.on(close > open && close > high[1], "Breakout"). A script may declare up to 200 conditions.

#Seeing the conditions on the chart

Every script with alert.on gets an Alert conditions switch on the Style tab of its settings (off by default). Turn it on and a small dot appears under each bar where a condition is true. It is the quickest way to check that a condition fires where you expect, including on history.

#alert.send: messages from code

ChartScriptFragmentOpen in editor
if (ta.crossover(close, ta.highest(high, 20)[1]) && barstate.isconfirmed) {
    alert.send("New 20-bar high at " + str.tostring(close, format.mintick), alert.freq_once_per_bar_close)
}

Unlike alert.on, alert.send can be called anywhere (inside if blocks, loops, functions) and its message is a series string, so it can carry values computed on the bar. The second argument is how often it may fire:

ConstantFires
alert.freq_once_per_bar (default)at most once per bar, as soon as the call runs; on the live bar that may be before the bar closes
alert.freq_once_per_bar_closeat most once per bar, when the bar closes
alert.freq_allon every run that reaches the call, so on every update of the live bar

alert.freq_once_per_bar_close is the one that never fires for a bar that later turns around; see repainting.

#Creating a script alert

Add the script to a chart, then open Create alert… from the script's legend row (or its row in the object tree). The alert dialog opens on the chart's market and timeframe with the script's conditions:

  • every alert.on condition, by its title;
  • Any alert.send() call, when the script calls alert.send.

You can also open Create alert from the toolbar and pick the script under Or a script on this chart in the market menu.

The dialog shows the inputs the alert will run with: the script's settings on that chart when you create it. Changing the chart's settings later does not change the alert; create a new one, or edit the alert from the chart again. Your own script's alert runs the version you had on the chart; an alert on a Community script follows the version its author publishes.

Then choose the trigger (below), the expiry, the message and where to be notified: in the app, with a sound, by browser push, and on Plus, Pro and Elite also by email, Telegram, Discord, webhook or plain-text email, exactly as for ChartDeck's other alerts.

#It runs on ChartDeck's servers

A script alert does not need your browser. ChartDeck runs the script on its own servers, on exactly the same bars as the script on your chart (its calc_bars_count, else 5,000 bars, within your plan's bars per run), and checks the condition there, also while every tab is closed. The values are the ones your chart shows at each bar close. Alerts on the same script, market, timeframe and inputs share one run, so a popular Community script costs no more for a thousand members than for one.

A protected Community script stays protected: you get its conditions' titles and its messages, never its code.

#Triggers

TriggerWhen it fires
Once per bar close (default)when a bar closes with the condition true; at most once a bar; never for a bar that later turns around
Once per baron the live bar, as soon as the condition is true; at most once a bar. It can fire on a bar that closes the other way
Oncelike once per bar close, and then the alert ends

For Any alert.send() call the call's own frequency applies too: with once per bar close only calls made when the bar closes count; with once per bar the calls of the live bar count as well, except those made with alert.freq_once_per_bar_close. One alert fires at most once a bar, with the first message of that bar.

If a script is too slow to run on every update of the live bar, a once per bar alert is checked at bar close only, and the Alerts panel says so ("too slow on the live bar: checked at bar close only"). It keeps firing on closes.

#A restart never fires twice

If ChartDeck restarts, the alert picks up where it was: a bar it already checked is never checked again, and a bar that closed while the servers were restarting is checked once.

#When a script alert pauses

A script alert pauses, and the bell tells you once, when it can no longer run:

  • the author removed your access to an invite-only script, or the script left the Community;
  • you deleted the script, or the version the alert runs;
  • the script no longer compiles, or no longer has the condition;
  • script alerts are not available on your plan.

The Alerts panel shows the reason under the alert. Resume checks again first and tells you if the reason is still there.

#Plan limits

Script alerts have no count of their own: they share your plan's alerts total with price, technical, watchlist and calendar alerts.

BeginnerPlusProElite
Alerts of every kind together (active or paused)102507002,500

A script alert can use any timeframe your plan can chart, seconds included, like every other alert. How long an alert runs before it expires follows your plan, as for every alert. When every alert of your total is in use, creating one more says "Your plan allows 10 active alerts in total. Upgrade for more." (on Beginner; your plan's own number on the others); delete or let an alert end to make room.

#Message placeholders

ChartDeck's alert messages replace {{name}} placeholders with the values of the moment the alert fires. These are the ones the alert system understands:

PlaceholderBecomes
{{ticker}}the symbol, e.g. BTCUSDT
{{exchange}}the exchange, e.g. Binance Futures
{{interval}}the alert's timeframe, e.g. 1h
{{open}} {{high}} {{low}} {{close}} {{volume}}the bar's values ({{close}} is the last price)
{{time}}when it fired (UTC, ISO 8601)
{{value}}the level of the condition
{{alert_name}}the alert's name
{{plan}}your ChartDeck plan

A script alert understands three more:

PlaceholderBecomes
{{plot_0}}, {{plot_1}}, … {{plot_63}}the value of the script's first, second, … plotted output on the bar that fired, in the order the script declares them
{{plot("Title")}}the value of the plot with that title
{{message}}the text of the alert.send call (the default message of an "Any alert.send() call" alert)

The default message of an alert.on condition is the message the script gives it; you can change it in the dialog. Placeholders that are not in these lists are left exactly as written, and messages are always plain text. Text that alert.send puts into {{message}} is inserted as it is: placeholders inside it are not filled. With alert.send you can also put any value into the message yourself with str.tostring or str.format.

#A whole example

A breakout indicator that declares both directions as named conditions, sends a message with the breakout size, and draws the levels it watches:

ChartScriptOpen in editor
//@chartscript 1
indicator("Range breakout", { overlay: true })

const len = input.int(20, "Range length", { minval: 2, maxval: 200 })

const top = ta.highest(high, len)[1]
const bottom = ta.lowest(low, len)[1]
plot(top, "Range top", color.up, { style: plot.style_stepline })
plot(bottom, "Range bottom", color.down, { style: plot.style_stepline })

const breakUp = close > top && barstate.isconfirmed
const breakDown = close < bottom && barstate.isconfirmed
plotshape(breakUp, "Break up", shape.triangleup, location.belowbar, color.up)
plotshape(breakDown, "Break down", shape.triangledown, location.abovebar, color.down)

alert.on(breakUp, "Breakout up", "{{ticker}} {{interval}} closed above the range at {{close}}")
alert.on(breakDown, "Breakout down", "{{ticker}} {{interval}} closed below the range at {{close}}")

if (breakUp || breakDown) {
    const size = breakUp ? (close - top) / top * 100 : (bottom - close) / bottom * 100
    alert.send(
        (breakUp ? "Up" : "Down") + " breakout of " + str.tostring(size, "0.00") + " % beyond the " + str.tostring(len) + "-bar range",
        alert.freq_once_per_bar_close
    )
}

#sound.play: a sound on the chart

An alert reaches you wherever you are. Sometimes you only want the chart to make a short sound while you watch it: sound.play does that.

ChartScriptFragmentOpen in editor
if (ta.crossover(close, ta.sma(close, 20))) {
    sound.play(sound.chime, 0.5)
}
  • The first argument is one of the built-in sounds: sound.chime, sound.ping, sound.pop, sound.tick, sound.knock, sound.rise, sound.fall, sound.coin, sound.thud or sound.alarm. They are made in the browser; no file is loaded.
  • sound.custom1 to sound.custom3 play the viewer's own clips: files each member picks in Settings > Sounds, kept in their browser. A script can not name a web address or a file: anything that is not a sound.* id is ignored.
  • The volume goes from 0 to 1; the viewer's own volume and mute apply on top. The third argument is the same alert.freq_* as for alert.send (default: once per bar).

When it plays: only while the chart is open and its tab is in front, only for the newest bar as it updates live (never while the history is calculated), at most one sound per run, and the page spaces sounds out so that a burst of signals does not turn into a burst of noise. Browsers allow sound only after you click or press a key on the page once. For a sound while the tab is in the background, create an alert with a sound instead.

The ChartScript documentation is in English for now; translations will follow.