Low-code Alert

Low-code Alert

Low-Code Alert

💡
If you do not have access to the code in the TradingView indicator or strategy, refer to the No-Code Guide.

In the Basic Alert module, you'll gain an understanding of adding arrows to your entries and creating alerts with pre-defined messages.

As you advance to the Intermediate Alert module, you'll learn how to generate alerts with dynamic and customisable messages.

Basic

💡
PineScript Version 5 This guide is based on PineScript Version 5. How to check? At the bottom of your TradingView terminal, open “Pine Editor” and see the first few lines of code.
image

In this example, the script is on PineScript Version 5 — evident from:

//@version=5
💡
If you are using Versions 4 or lower, convert your script to Version 5.

Script Type

On the first few lines of your script, you should see the word “strategy” or “indicator”.

//@version=5
strategy('Supertrend Strategy - PineConnector', overlay=true)
//@version=5
indicator('AlphaTrend - PineConnector', overlay=true)
💡
If you are using an indicator script, jump to indicator.

Strategy

In this demonstration, we'll utilize the SuperTrend strategy script to add arrows for visual cues and implement an alert feature.

The following is the original script before any modification:

//@version=5
strategy('Supertrend Strategy', overlay=true)

[supertrend, direction] = ta.supertrend(3, 10)

bodyMiddle = plot((open + close) / 2, display=display.none)
upTrend = plot(direction < 0 ? supertrend : na, 'Up Trend', color=color.new(color.green, 0), style=plot.style_linebr)
downTrend = plot(direction < 0 ? na : supertrend, 'Down Trend', color=color.new(color.red, 0), style=plot.style_linebr)

fill(bodyMiddle, upTrend, color.new(color.green, 90), fillgaps=false)
fill(bodyMiddle, downTrend, color.new(color.red, 90), fillgaps=false)

if ta.change(direction) < 0
    strategy.entry('My Long Entry Id', strategy.long)

if ta.change(direction) > 0
    strategy.entry('My Short Entry Id', strategy.short)

1. Add Visual Confirmation

First, identify the exact entry conditions to add the visual cue. Add the plotshape code at the bottom of your script:

plotshape(LongEntryCondition, style=shape.labelup, location=location.belowbar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Buy', textcolor=color.new(color.white, 0)) //plotting up arrow when buy/long conditions met 
plotshape(ShortEntryCondition, style=shape.labeldown, location=location.abovebar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Sell', textcolor=color.new(color.white, 0)) //plotting down arrow when sell/short conditions met
💡
Update Entry Conditions Change LongEntryCondition and ShortEntryCondition to your actual long and short entry conditions. What is my entry condition? Your entry condition is after the “if” — copy everything on the row after the “if” and before strategy.entry. Example The underlined and bolded text are the Actual Entry Conditions. if ta.change(direction) < 0 strategy.entry('My Long Entry Id', strategy.long) if ta.change(direction) > 0 strategy.entry('My Short Entry Id', strategy.short)

After adding the plotshape code to the last two lines, it should look like this:

//@version=5
strategy('Supertrend Strategy', overlay=true)

[supertrend, direction] = ta.supertrend(3, 10)

bodyMiddle = plot((open + close) / 2, display=display.none)
upTrend = plot(direction < 0 ? supertrend : na, 'Up Trend', color=color.new(color.green, 0), style=plot.style_linebr)
downTrend = plot(direction < 0 ? na : supertrend, 'Down Trend', color=color.new(color.red, 0), style=plot.style_linebr)

fill(bodyMiddle, upTrend, color.new(color.green, 90), fillgaps=false)
fill(bodyMiddle, downTrend, color.new(color.red, 90), fillgaps=false)

if ta.change(direction) < 0
    strategy.entry('My Long Entry Id', strategy.long)

if ta.change(direction) > 0
    strategy.entry('My Short Entry Id', strategy.short)
    
plotshape(ta.change(direction) < 0, style=shape.labelup, location=location.belowbar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Buy', textcolor=color.new(color.white, 0)) //plotting up arrow when buy/long conditions met 
plotshape(ta.change(direction) > 0, style=shape.labeldown, location=location.abovebar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Sell', textcolor=color.new(color.white, 0)) //plotting down arrow when sell/short conditions met

Click 'Save' to preserve your code, then click 'Add to chart' to apply it.

image

The chart should display PineConnector's Blue arrows indicating Buy and Sell points.

💡
Difference between PineConnector and Strategy arrows

The Blue arrows from PineConnector should appear one candle prior to the strategy's entries (My Long Entry Id, and My Short Entry Id). The Blue arrows are plotted at the end of the candle, whereas the strategy entries are triggered at the beginning of the next candle.

As the closing price of the first candle is equal to the opening price of the second candle, the plotting difference is not an issue.

2. Add the Alert Function

With the visual cues in place, let's proceed to add the alert codes. The alert codes are to appear near the strategy.entry, usually found at the bottom few rows.

💡
Quick Search Use the keyboard shortcut CTRL+F (Windows) or CMD+F (Mac) to find strategy.entry.

Since the first “strategy.entry” is strategy.long, we inject the following code:

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

Since the second “strategy.entry” is strategy.short, we inject the following code:

alert('LicenseID,sell,EURUSD,risk=1', alert.freq_once_per_bar_close)
💡
Update License ID Update the LicenseID in the codes above to your actual License ID.

After adding the arrows and alert function, you should have the following:

//@version=5
strategy('Supertrend Strategy', overlay=true)

[supertrend, direction] = ta.supertrend(3, 10)

bodyMiddle = plot((open + close) / 2, display=display.none)
upTrend = plot(direction < 0 ? supertrend : na, 'Up Trend', color=color.new(color.green, 0), style=plot.style_linebr)
downTrend = plot(direction < 0 ? na : supertrend, 'Down Trend', color=color.new(color.red, 0), style=plot.style_linebr)

fill(bodyMiddle, upTrend, color.new(color.green, 90), fillgaps=false)
fill(bodyMiddle, downTrend, color.new(color.red, 90), fillgaps=false)

if ta.change(direction) < 0
    strategy.entry('My Long Entry Id', strategy.long)
    alert('60123456789,buy,EURUSD,risk=1', alert.freq_once_per_bar_close)

if ta.change(direction) > 0
    strategy.entry('My Short Entry Id', strategy.short)
    alert('60123456789,sell,EURUSD,risk=1', alert.freq_once_per_bar_close)

plotshape(ta.change(direction) < 0, style=shape.labelup, location=location.belowbar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Buy', textcolor=color.new(color.white, 0)) //plotting up arrow when buy/long conditions met 
plotshape(ta.change(direction) > 0, style=shape.labeldown, location=location.abovebar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Sell', textcolor=color.new(color.white, 0)) //plotting down arrow when sell/short conditions met

Once you've updated LicenseID, LongEntryCondition, and ShortEntryCondition, save the revised script.

3. Create the Alert

💡
Bring Your Alerts to Life Please note that simply adding the alert code to your strategy does not activate alerts. You must create alerts for the symbol and timeframe of your choice.

For this illustration, we will set up alerts for FXCM's 'EURUSD' on a 1 second chart.

3.1 Create an Alert

Use the keyboard shortcut Alt+A (Windows) or Option+A (Mac) to create an alert.

3.2 Configure Alert

Configure your alert as per the following:

Component
Configuration
Condition
Supertrend Strategy alert() function calls only
Webhook URL
https://webhook.pineconnector.com
image
image
💡
Name it as desired The 'Alert name' is flexible and can be modified to your preference for ease of identification.

Select “Create” once you have configured the alert.

3.3 Alert Firing

When the entry conditions in your strategy are met, you will observe a blue arrow plotted on the chart and a new row in the Alerts Log.

The alert will also be recorded in the Alerts Log with the time it was triggered.

image

You should see a new EURUSD position on your MetaTrader terminal.

💡
Facing an error or your trades aren’t triggering? Browse through potential causes and remedies.
💡
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.

Indicator

In this demonstration, we'll utilize the Exponential Moving Average (EMA) crossover indicator script to add arrows for visual cues and implement an alert feature.

The following is the original script before any modification:

//@version=5
indicator("EMA", overlay=true)

ema20 = ta.ema(close,20)
ema50 = ta.ema(close,50)
plot(ema20, color=color.new(color.blue, 5))
plot(ema50, color=color.new(color.red, 5))

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

1. Add Visual Confirmation

First, identify the exact entry conditions to add the visual cue.

Add the plotshape code at the bottom of your script:

plotshape(LongEntryCondition, style=shape.labelup, location=location.belowbar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Buy', textcolor=color.new(color.white, 0)) //plotting up arrow when buy/long conditions met 
plotshape(ShortEntryCondition, style=shape.labeldown, location=location.abovebar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Sell', textcolor=color.new(color.white, 0)) //plotting down arrow when sell/short conditions met
💡
Update Entry Conditions Change LongEntryCondition and ShortEntryCondition to your actual long and short entry conditions. What is my entry condition? The entry condition can often be found at the bottom of your script. If you are unfamiliar with reading codes, it may take some trial and error to determine it. Typically, they are at the bottom of your script — look there first.

After adding the plotshape code to the last two lines, it should look like this:

//@version=5
indicator("EMA", overlay=true)

ema20 = ta.ema(close,20)
ema50 = ta.ema(close,50)
plot(ema20, color=color.new(color.blue, 5))
plot(ema50, color=color.new(color.red, 5))

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

plotshape(long, style=shape.labelup, location=location.belowbar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Buy', textcolor=color.new(color.white, 0)) //plotting up arrow when buy/long conditions met 
plotshape(short, style=shape.labeldown, location=location.abovebar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Sell', textcolor=color.new(color.white, 0)) //plotting down arrow when sell/short conditions met

Click 'Save' to preserve your code, then click 'Add to chart' to apply it.

image

The chart should display PineConnector's Blue arrows indicating Buy and Sell points.

💡
Verify the Plotted Arrows Check that the arrows are plotted where you expect them to be by reviewing the chart. If the arrows appear in unexpected locations, it may indicate that you have used incorrect entry conditions.

2. Add the Alert Function

With the visual cues in place, let's proceed to add the alert codes. The alert codes are to appear near your long and short entry conditions, usually found at the bottom few rows.

For instance:

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

if ShortEntryCondition
    alert('LicenseID,buy,EURUSD,risk=1', alert.freq_once_per_bar_close)
💡
Update Entry Conditions and License ID Change LongEntryCondition and ShortEntryCondition to your actual entry conditions Change LicenseID in the codes above to your actual License ID

Your code, including the arrows and alert function, should now look like this:

//@version=5
indicator("EMA", overlay=true)

ema20 = ta.ema(close,20)
ema50 = ta.ema(close,50)
plot(ema20, color=color.new(color.blue, 5))
plot(ema50, color=color.new(color.red, 5))

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

plotshape(long, style=shape.labelup, location=location.belowbar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Buy', textcolor=color.new(color.white, 0)) //plotting up arrow when buy/long conditions met 
plotshape(short, style=shape.labeldown, location=location.abovebar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Sell', textcolor=color.new(color.white, 0)) //plotting down arrow when sell/short conditions met

if long
    alert('60123456789,buy,EURUSD,risk=1', alert.freq_once_per_bar_close)

if short
    alert('60123456789,buy,EURUSD,risk=1', alert.freq_once_per_bar_close)

Once you've updated LicenseID, LongEntryCondition, and ShortEntryCondition, save the revised script.

3. Create the Alert

💡
Bring Your Alerts to Life Please note that simply adding the alert code to your strategy does not activate alerts. You must create alerts for the symbol and timeframe of your choice.

For this example, we will creating alerts based on “EURUSD” on the 1 second chart.

3.1 Create an Alert

Press Alt+A (Windows) or Option+A (Mac), to create an alert.

3.2 Configure Alert

Configure your alert as per the following, and create click “Create”.

Component
Configuration
Condition
EMA Any alert() function calls only
Webhook URL
https://webhook.pineconnector.com
image
image
💡
Name it as desired The 'Alert name' is flexible and can be modified to your preference for ease of identification.

3.3 Alert Firing

Once the conditions for entering a trade are met, a blue arrow will appear on the chart and an alert will be triggered at the same time.

The alert will also be recorded in the Alerts Log with the time it was triggered.

image

You should see a new EURUSD position on your MetaTrader terminal.

💡
Facing an error or your trades aren’t triggering? Browse through potential causes and remedies.
💡
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.

Intermediate

💡
Slow & Steady Before going through the intermediate alert module, we recommend that you first understand the basics of the Syntax and EA Settings modules.

The intermediate alert module builds upon the foundation laid in the basic low-code module.

Here, we will take the static alert messages and enhance them to be more informative and dynamic.

💡
Repainting In our alert functions, we use alert.freq_once_per_bar_close to minimise repainting. Repainting occurs when the script behaves differently during live trading than when applied to historical prices. Read TradingView’s comprehensive address regarding repainting here (strong coffee recommended). A (slightly) shorter summary of repainting:

Repainting refers to the difference in script behavior when running it in real-time compared to historical prices.

This behavior is widespread and can result from many factors. More than 95% of indicators in existence repaint, including commonly used indicators like MACD and RSI.

They show different values on historical and real-time bars.

Type
Definition
Acceptable
Widespread and often acceptable
Recalculation during the real-time bar (e.g. MACD, RSI)
If the user is aware of the behavior, can live with it, or can circumvent it
Misleading
Plotting in the past, calculating results in real-time that cannot be replicated on historical bars, relocating past events (e.g. Ichimoku, pivot scripts)
If the user is aware of the behavior, can live with it, or can circumvent it
Unacceptable
Scripts using future information, strategies running on non-standard charts, scripts using real-time intrabar timeframes to generate alerts or orders
No
Unavoidable
Revision of historical feeds by data suppliers, varying starting bar on historical bars
No

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.

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.

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.

image

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

💡
LicenseID,buy,US100,sl=10,tp=20,risk=1
💡
What if my symbol is NAS100? If your broker uses NAS100 instead of 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.

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.

Implementation

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.

5. Adding a Comment

To add the comment component, ensure you are using the double " only for the entire alert message and the single ' for the individual components within the alert message.

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)+',comment="Strategy 1"', alert.freq_once_per_bar_close)

6. 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.

image

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

image
💡
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 triggers in 3 minutes for a single alert. Having more than 15 alerts in that period will result in your alerts being paused automatically.
image

7. Putting it all Together

By transforming the syntax to include multiple parameters, making the symbol dynamic so that the generated symbol in the alert is based on the ticker for which the alert is created, and incorporating dynamic stop loss and take profit levels with multiple alerts triggering to various license IDs, we have the following:

💡
Caveat It is not necessary to include all intermediate components in your setup. Utilise on the ones that are relevant to your needs, such as dynamic stop loss and take profit levels.
//@version=5
indicator("EMA", overlay=true)

ema20 = ta.ema(close,20)
ema50 = ta.ema(close,50)
plot(ema20, color=color.new(color.blue, 5))
plot(ema50, color=color.new(color.red, 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, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Buy', textcolor=color.new(color.white, 0)) //plotting up arrow when buy/long conditions met 
plotshape(short, style=shape.labeldown, location=location.abovebar, color=color.new(#046ff9, 0), size=size.large, text='PineConnector \n Sell', textcolor=color.new(color.white, 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)

Next →

Syntax