//This emonstrates how to create a Discord bot using JSON webhooks and TradingView alerts generated by Pine Script.
// Resources
// Discord Webhook Guide: https://birdie0.github.io/discord-webhooks-guide/discord_webhook.html
// Decimal Color Converter: https://www.mathsisfun.com/hexadecimal-decimal-colors.html
// TradingView Table Blog Post: https://www.tradingview.com/blog/en/introducing-pine-tables-24604/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// @version=4
study("Discord Alerts")
// Get user input
botName = input(title="Bot Name", type=input.string, defval="TradingView", tooltip="The display name for this webhook bot")
avatarURL = input(title="Avatar URL", type=input.string, defval="https://pbs.twimg.com/profile_images/1418656582888525833/p4fZd3KR.jpg", tooltip="Your preferred Avatar image URL")
iconURL = input(title="Icon URL", type=input.string, defval="https://theartoftrading.com/files/discord/zentradingcircle.png", tooltip="Your preferred message icon image URL")
titleURL = input(title="Title URL", type=input.string, defval="https://www.tradingview.com/chart/", tooltip="Where you want the title of the message to link to")
message = input(title="Message", type=input.string, defval="", tooltip="Optional message to add before the role tag & embed info")
role = input(title="Role ID", type=input.string, defval="", tooltip="The role ID you want to ping when this message is sent to discord (optional)")
embedColor = input(title="Embed Color", type=input.string, defval="", tooltip="Your embed color (decimal color only - not HEX or RGB!)")
volatility = input(title="Volatility Alerts?", type=input.bool, defval=true, tooltip="Turns on/off intraday volatility alerts")
// Declare constant variables
var ROLE_ID = role == "" ? "" : " (<@&" + role + ">)"
var ICON1_URL = syminfo.type == "forex" ? ("https://theartoftrading.com/files/discord/flags/" + syminfo.basecurrency + ".png") : iconURL
var ICON2_URL = syminfo.type == "forex" ? ("https://theartoftrading.com/files/discord/flags/" + syminfo.currency + ".png") : ""
var MARKET = syminfo.type == "forex" or syminfo.type == "crypto" ? syminfo.basecurrency : syminfo.ticker
// Get market data to send to discord
mktChange = (change(close) / close[1]) * 100
mktRSI = rsi(close, 14)
// Custom function to truncate (cut) excess decimal places
truncate(_number, _decimalPlaces) =>
_factor = pow(10, _decimalPlaces)
int(_number * _factor) / _factor
// Custom function to convert pips into whole numbers
atr = atr(14)
toWhole(_number) =>
_return = atr < 1.0 ? (_number / syminfo.mintick) / (10 / syminfo.pointvalue) : _number
_return := atr >= 1.0 and atr < 100.0 and syminfo.currency == "JPY" ? _return * 100 : _return
// Generate discord embed JSON
getDiscordEmbedJSON(_color, _author, _title, _url, _icon_url, _icon2_url, _footer, _description) =>
botTxt = "\"username\":\"" + botName + "\",\"avatar_url\":\"" + avatarURL + "\","
tagTxt = message == "" and role == "" ? "" : ("\"content\":\"" + (message == "" ? "" : message + " ") + ROLE_ID + "\",")
returnString = "{" + botTxt + tagTxt + "\"embeds\":[{\"title\":\""+_title+"\",\"url\":\""+_url+"\",\"color\":"+
_color+",\"description\":\""+_description+"\",\"author\":{\"name\":\""+_author+
"\",\"url\":\""+_url+"\",\"icon_url\":\""+_icon_url+"\"},\"footer\":{\"text\":\""+_footer+"\",\"icon_url\":\""+_icon2_url+"\"}}]}"
// Determine if we have a new bar starting - if so, send our Discord webhook alert
if barstate.isconfirmed
timeframe = (timeframe.isintraday ? timeframe.period + " minute" : timeframe.isdaily ? "Daily" : timeframe.isweekly ? "Weekly" : timeframe.ismonthly ? "Monthly" : timeframe.period) + " timeframe"
update = syminfo.ticker + " ended " + (mktChange > 0 ? "up +" : "down ") + tostring(truncate(mktChange,2)) + "% on " + timeframe + " (RSI = " + tostring(truncate(mktRSI,2)) + ")"
gainLoss = toWhole(open - close)
footer = "Price: " + tostring(close) + " (" + (gainLoss > 0 ? "+" : "") + tostring(gainLoss) + " pips)"
gainColor = (embedColor != "" ? embedColor : (mktChange > 0 ? "65280" : "16711680"))
content = getDiscordEmbedJSON(gainColor, "Market Update", syminfo.ticker, titleURL, ICON1_URL, ICON2_URL, footer, update)
alert(content, alert.freq_once_per_bar)
// Check if we have high intraday volatility - if so, send our Discord webhook alert
if abs(mktChange) >= 10 and volatility
timeframe = (timeframe.isintraday ? timeframe.period + " minute" : timeframe.isdaily ? "Daily" : timeframe.isweekly ? "Weekly" : timeframe.ismonthly ? "Monthly" : timeframe.period) + " timeframe"
update = syminfo.ticker + " is " + (mktChange > 0 ? "up +" : "down ") + tostring(truncate(mktChange,2)) + "% [" + tostring(close) + "] on " + timeframe + " (RSI = " + tostring(truncate(mktRSI,2)) + ")"
gainLoss = toWhole(open - close)
footer = "Price: " + tostring(close) + " (" + (gainLoss > 0 ? "+" : "") + tostring(gainLoss) + " pips)"
gainColor = (embedColor != "" ? embedColor : (mktChange > 0 ? "65280" : "16711680"))
content = getDiscordEmbedJSON(gainColor, "High Volatility Alert", syminfo.ticker, titleURL, ICON1_URL, ICON2_URL, footer, update)
alert(content, alert.freq_once_per_bar)
// Prepare table
var table myTable = table.new(position.middle_right, 1, 1, border_width=1)
f_fillCell(_table, _column, _row, _title, _value, _bgcolor, _txtcolor) =>
_cellText = _title + "\n" + _value
table.cell(_table, _column, _row, _cellText, bgcolor=_bgcolor, text_color=_txtcolor)
// Draw table
if barstate.islast
f_fillCell(myTable, 0, 0, "Market:", MARKET + " (" + syminfo.type + ")", color.new(color.black,0), color.white)
Overview
Discord Alerts calculates percentage price change, a 14-period RSI, and a 14-period ATR, then formats those values into an embed with a bot name, avatar, icons, title link, optional message, and optional role mention. Forex symbols can use currency-flag icons, while other markets use a custom icon. A toggle turns intraday volatility alerts on or off. It draws in a separate pane and does not place trades.
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
This indicator plots a TTM Squeeze momentum oscillator in a separate pane. It compares a Bollinger Band offset to a Keltner Channel offset and marks the zero line white when the difference is non-negative and black when the bands are inside the channel. A line
Calculates dynamic modeling values by applying a mathematical logistic differential equation to price change over a specified lookback length. It measures price momentum relative to the recent high-low price range. The script plots positive and negative logist
MACD-V is a volatility-normalized momentum indicator based on research by Alex Spiroglou. It calculates the standard MACD histogram and normalizes it by dividing by the Average True Range (ATR). Plotted in a separate pane as a colored histogram, it includes us
This indicator detects a Bollinger Band squeeze when the bands sit inside Keltner Channels, marking low volatility. It plots red dots during a squeeze and green dots when the bands are outside, in a separate pane. An optional histogram shows momentum as the cl
This indicator generates trade entry signals and target levels optimized for 1-hour timeframes, designed for external signal extraction. It calculates 7-period and 16-period EMAs alongside 10-period RSI and ATR filters. Long signals occur when the fast EMA cro
The Bubbles Indicator measures volatility squeezes and expansion bursts using Bollinger Bands combined with a sinusoid oscillator and RSI divergence. It processes price data through scaled Bollinger Bands to highlight volatility changes while confirming trend