Low-code — Intermediate

Before going through the intermediate alert module, complete the Syntax and EA Settings modules first.

In the basic low-code module, you learnt where to place the plotshape() function to plot the arrows and the basic alert() codes to create the alert function.

In this intermediate alert module, the focus will be to transform the static alert messages to be comprehensive and dynamic.

In our alert functions, we use alert.freq_once_per_bar_close to minimise repainting. Repainting is when the script behaviour differs when running the script in real-time compared to historical prices. Read TradingView’s comprehensive address regarding repainting here (strong coffee recommended).

Level 1 — Basic

In the basic module, we create static alerts using:

alert('LicenseID,buy,EURUSD,risk=1', alert.freq_once_per_bar_close)

The above code generates an alert message with a static symbol and risk value.

Level 2 — Multiple Parameters

alert('LicenseID,buy,EURUSD,risk=1,sl=10,tp=20', alert.freq_once_per_bar_close)

The alert message is still static, but with sl= and tp= parameters.

Level 3 — Dynamic Symbol

alert('LicenseID,buy,' +syminfo.ticker+ ',sl=10,tp=20,risk=1', alert.freq_once_per_bar_close)

Now, the symbol will change based on the ticker you create the alert on.


In the example above, we created the alert on the US100 chart. Should an alert trigger, the alert message will print:

What if my symbol is NAS100? If your broker uses NAS100 instead of the TradingView’s ticker of US100, you may manipulate the symbol printed.
symbol = syminfo.ticker

if syminfo.ticker == "US100"
    symbol := "NAS100"
if LongEntryCondition
    alert('LicenseID,buy,'+symbol+',sl=10,tp=20,risk=1', alert.freq_once_per_bar_close)

On the first line, we have a string named “symbol” set as TradingView’s ticker by default.

At the first “if”, “symbol” changes to NAS100 if the ticker is US100.

At the second “if”, we simply use “symbol” instead of “syminfo.ticker” for the alert function.

New code? New alert. If you make changes to your code, saving it will not affect pre-existing alerts, which will still use the original code at the time of creation. To implement the updated code, you must delete the old alerts and create a new one.

Level 4 — Dynamic Values

LongSL = low[1]
LongTP = ta.ema(close,50)
RiskValue = 1

if LongEntryCondition
    alert('LicenseID,buy,' +syminfo.ticker+ ',sl=' +str.tostring(LongSL)+ ',tp=' +str.tostring(LongTP)+ ',risk='+str.tostring(RiskValue), alert.freq_once_per_bar_close)

Instead of hardcoding your sl=, tp= and risk=, you may use variables which may be dynamic such as low[1].

LongSL - Candle Data

The low[1] represents the low price of the the most recent candle while low[2] represent the low price 2 candles ago.

LongTP - Formula

LongTP is also dynamic which stores the latest Exponential Moving Average value of the 50 most recent close prices, changing at the close of each candle.

RiskValue - Static Value

You may also store static values, as seen for the “RiskValue” parameter where we stored a fixed value of 1.


The alert() function only accept strings (texts) while “LongSL”, “LongTP” and “RiskValue” are floats (numbers). We will use the “str.tostring()” function to convert floats to string — to be compliant to the alert() function’s requirement.

Level 5 — Multiple License IDs

If you have multiple License IDs, we can send create alerts to all very easily.

if LongEntryCondition
    alert('LicenseID1,buy,' +syminfo.ticker+ ',risk=1,sl=20', alert.freq_once_per_bar_close)
    alert('LicenseID2,buy,' +syminfo.ticker+ ',risk=1,sl=30', alert.freq_once_per_bar_close)
    alert('LicenseID3,buy,' +syminfo.ticker+ ',risk=1,sl=40', alert.freq_once_per_bar_close)
    alert('LicenseID4,buy,' +syminfo.ticker+ ',risk=1,sl=40', alert.freq_once_per_bar_close)
    alert('LicenseID5,buy,' +syminfo.ticker+ ',risk=1,sl=40', alert.freq_once_per_bar_close)

To implement, simply duplicate the alert code and change the LicenseID accordingly.


Even with 1 alert created, when entry conditions are met, 5 alerts will trigger at the same time.

Sky’s not the limit — 15 is While you send in multiple alerts at the same time, note that you can only send a maximum of 15 alerts in 3 minutes. Having more than 15 alerts in that period will result in your alerts being paused automatically.

Putting it all Together

indicator("EMA", overlay=true)

ema20 = ta.ema(close,20)
ema50 = ta.ema(close,50)
plot(ema20,, 5))
plot(ema50,, 5))

long = ta.crossover(ema20, ema50) and close > ema20
short = ta.crossunder(ema20, ema50) and close < ema20

//plotting arrows to print entries on the chart
plotshape(long, style=shape.labelup, location=location.belowbar,, 0), size=size.large, text='PineConnector \n Buy',, 0)) //plotting up arrow when buy/long conditions met 
plotshape(short, style=shape.labeldown, location=location.abovebar,, 0), size=size.large, text='PineConnector \n Sell',, 0)) //plotting down arrow when sell/short conditions met

//manipulating symbol to NAS100 if ticker is US100 
symbol = syminfo.ticker

if syminfo.ticker == "US100"
    symbol := "NAS100"

//variables to store dynamic values
LongSL = low[1]
LongTP = ta.ema(close,50)
RiskValue = 1

//trigger 3 alerts to the various License IDs with dynamic syntax
if long
    alert('LicenseID1,buy,' +symbol+ ',sl=' +str.tostring(LongSL)+ ',tp=' +str.tostring(LongTP)+ ',risk='+str.tostring(RiskValue), alert.freq_once_per_bar_close)
    alert('LicenseID2,buy,' +symbol+ ',sl=' +str.tostring(LongSL)+ ',tp=' +str.tostring(LongTP)+ ',risk='+str.tostring(RiskValue), alert.freq_once_per_bar_close)
    alert('LicenseID3,buy,' +symbol+ ',sl=' +str.tostring(LongSL)+ ',tp=' +str.tostring(LongTP)+ ',risk='+str.tostring(RiskValue), alert.freq_once_per_bar_close)

← Previous

Next →

PineConnector Code Adapter