Code: Select all
//@version=5
indicator("RSI Bull_Div Alert MTF")
enable_tf1 = true
enable_tf2 = true
enable_tf3 = true
alert_tf1 = true
alert_tf2 = true
alert_tf3 = true
tf1_col = color.blue
tf2_col = color.yellow
tf3_col = color.green
timeframe1 = "15"
timeframe2 = "30"
timeframe3 = "60"
lookback = 90
lengthRSI = 14
// ---------------------------------------------------------------------------------------------- //
cutLastDigit(str) =>
s = str + ';'
r = str.replace_all(s, '1;', '')
if r != s
[r, 1]
else
r := str.replace_all(s, '2;', '')
if r != s
[r, 2]
else
r := str.replace_all(s, '3;', '')
if r != s
[r, 3]
else
r := str.replace_all(s, '4;', '')
if r != s
[r, 4]
else
r := str.replace_all(s, '5;', '')
if r != s
[r, 5]
else
r := str.replace_all(s, '6;', '')
if r != s
[r, 6]
else
r := str.replace_all(s, '7;', '')
if r != s
[r, 7]
else
r := str.replace_all(s, '8;', '')
if r != s
[r, 8]
else
r := str.replace_all(s, '9;', '')
if r != s
[r, 9]
else
r := str.replace_all(s, '0;', '')
if r != s
[r, 0]
strToNumInt(str) =>
integer = 0 // integer part of the number
s_new = str
position = 0.0 // handled position of the number.
sign = 1 // sign of the number. 1.0 is PLUS and -1.0 is MINUS.
for i = 0 to 30 by 1
[s, digit] = cutLastDigit(s_new) // here we'll cut the digits by one from the string till the string is empty.
integer += digit * int(math.pow(10, position)) // it's just a regular digit.
position += 1
if s == ''
break
s_new := s // If we are here, then there are more digits in the string. Let's handle the next one!
s_new
sign * integer // We've exited from the loop. Build the returning value.
calculateTimeDividedBy(res) =>
timeDividiedBy = time(timeframe.period)
if strToNumInt(res) < 1440
timeDividiedBy := strToNumInt(res) * 60 * 1000
timeDividiedBy
for i = 1 to 50 by 1
if res == str.tostring(i) + 'D' or res == 'D'
timeDividiedBy := i * 1 * 86400000
break
else if res == str.tostring(i) + 'W' or res == 'W'
timeDividiedBy := i * 7 * 86400000
break
else if res == str.tostring(i) + 'M' or res == 'M'
timeDividiedBy := i * 30 * 86400000
break
timeDividiedBy
tf1_isNewPeriod = ta.change(time(timeframe1))
tf2_isNewPeriod = ta.change(time(timeframe2))
tf3_isNewPeriod = ta.change(time(timeframe3))
tf1_multiplier = calculateTimeDividedBy(timeframe1) / calculateTimeDividedBy(timeframe.period)
tf2_multiplier = calculateTimeDividedBy(timeframe2) / calculateTimeDividedBy(timeframe.period)
tf3_multiplier = calculateTimeDividedBy(timeframe3) / calculateTimeDividedBy(timeframe.period)
//////////////////////////////////////////////////////////////
rsi = ta.rsi(close, lengthRSI)
len = 14 //input(14, minval=1, title="RSI Length")
ob = 70 //input(defval=70, title="Overbought", type=input.integer, minval=0, maxval=100)
os = 30 //input(defval=30, title="Oversold", type=input.integer, minval=0, maxval=100)
hline(50, title='Fifty-Line', color=color.gray, linestyle=hline.style_solid)
seventy = hline(ob, color=color.gray, linestyle=hline.style_dashed)
thirty = hline(os, color=color.gray, linestyle=hline.style_dashed)
fill(thirty, seventy, color.new(color.purple, 90))
pl_rsi = plot(rsi, title='RSI Oscillator', color=color.new(color.purple, 0), linewidth=1)
// Inputs
scalePercentage = input.int(100, "Vertical %", step = 10, maxval = 100)
lookBack = input.int(100, "Last Bars to Look", minval = 2, step = 20)
scaleFactor = 100 / scalePercentage
//plot(volume, color = color.orange, title="Volume", style=plot.style_columns, transp=0)
hi_limit = ta.highest(rsi, lookBack)
lo_limit = ta.lowest(rsi, lookBack)
high_div =hi_limit * scaleFactor
low_div = lo_limit * scaleFactor
plot(high_div, "High", #00000000)
plot(low_div, "Low", #00000000)
/////////////////////////////////////
// Find Divergence
///////////////////////////////////
find_divergence(price_close, oscillator, lookback) =>
highest_bar = math.abs(ta.highestbars(oscillator, lookback)) // Finds bar with highest value in last X bars
lowest_bar = math.abs(ta.lowestbars(oscillator, lookback)) // Finds bar with lowest value in last X bars
// Defining variable
max_price = float(na)
max_osc = float(na)
min_price = float(na)
min_osc = float(na)
pivoth = bool(na)
pivotl = bool(na)
divbear = bool(na)
divbull = bool(na)
// If bar with lowest / highest is current bar, use it's value
max_price := highest_bar == 0 ? price_close : na(max_price[1]) ? price_close : max_price[1]
max_osc := highest_bar == 0 ? oscillator : na(max_osc[1]) ? oscillator : max_osc[1]
min_price := lowest_bar == 0 ? price_close : na(min_price[1]) ? price_close : min_price[1]
min_osc := lowest_bar == 0 ? oscillator : na(min_osc[1]) ? oscillator : min_osc[1]
// Compare high of current bar being examined with previous bar's high
// If curr bar high is higher than the max bar high in the lookback window range
if price_close > max_price // we have a new high
max_price := price_close // change variable "max" to use current bar's high value
max_price
if oscillator > max_osc // we have a new high
max_osc := oscillator // change variable "max_rsi" to use current bar's RSI value
max_osc
if price_close < min_price // we have a new low
min_price := price_close // change variable "min" to use current bar's low value
min_price
if oscillator < min_osc // we have a new low
min_osc := oscillator // change variable "min_rsi" to use current bar's RSI value
min_osc
// Finds pivot point with at least 2 right candles with lower value
pivoth := max_osc == max_osc[2] and max_osc[2] != max_osc[3] ? true : na
pivotl := min_osc == min_osc[2] and min_osc[2] != min_osc[3] ? true : na
// Detects divergences between price and indicator with 1 candle delay so it filters out repeating divergences
if max_price[1] > max_price[2] and oscillator[1] < max_osc and oscillator <= oscillator[1]
divbear := true
divbear
if min_price[1] < min_price[2] and oscillator[1] > min_osc and oscillator >= oscillator[1]
divbull := true
divbull
[divbull, divbear]
[tf1_divbull, tf1_divbear] = request.security(syminfo.ticker, timeframe1, find_divergence(close[barstate.isrealtime ? 1 : 0], rsi, lookback))
[tf2_divbull, tf2_divbear] = request.security(syminfo.ticker, timeframe2, find_divergence(close[barstate.isrealtime ? 1 : 0], rsi, lookback))
[tf3_divbull, tf3_divbear] = request.security(syminfo.ticker, timeframe3, find_divergence(close[barstate.isrealtime ? 1 : 0], rsi, lookback))
////////////////////////////
// Draw Labels
/////////////////////////
if enable_tf1 and tf1_isNewPeriod
tf1_divergence = tf1_divbear ? label.new(bar_index - 1 * tf1_multiplier, high_div, timeframe1, color=barstate.islast and not barstate.isconfirmed ? color.new(tf1_col, 80) : tf1_col, textcolor=color.black, style=label.style_label_down, yloc=yloc.price, size=size.normal) : tf1_divbull ? label.new(bar_index - 1 * tf1_multiplier, low_div, timeframe1, color=barstate.islast and not barstate.isconfirmed ? color.new(tf1_col, 80) : tf1_col, textcolor=color.black, style=label.style_label_up, yloc=yloc.price, size=size.normal) : na
if enable_tf2 and tf2_isNewPeriod
tf2_divergence = tf2_divbear ? label.new(bar_index - 1 * tf2_multiplier, high_div+10, timeframe2, color=barstate.islast and not barstate.isconfirmed ? color.new(tf2_col, 80) : tf2_col, textcolor=color.black, style=label.style_label_down, yloc=yloc.price, size=size.normal) : tf2_divbull ? label.new(bar_index - 1 * tf2_multiplier, low_div-10, timeframe2, color=barstate.islast and not barstate.isconfirmed ? color.new(tf2_col, 80) : tf2_col, textcolor=color.black, style=label.style_label_up, yloc=yloc.price, size=size.normal) : na
if enable_tf3 and tf3_isNewPeriod
tf3_divergence = tf3_divbear ? label.new(bar_index - 1 * tf3_multiplier, high_div+20, timeframe3, color=barstate.islast and not barstate.isconfirmed ? color.new(tf3_col, 80) : tf3_col, textcolor=color.black, style=label.style_label_down, yloc=yloc.price, size=size.normal) : tf3_divbull ? label.new(bar_index - 1 * tf3_multiplier, low_div-20, timeframe3, color=barstate.islast and not barstate.isconfirmed ? color.new(tf3_col, 80) : tf3_col, textcolor=color.black, style=label.style_label_up, yloc=yloc.price, size=size.normal) : na
//////////////////////////
// Create Alerts
///////////////////////
if alert_tf1 and tf1_isNewPeriod
if tf1_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if tf1_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if alert_tf2 and tf2_isNewPeriod
if tf2_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)
if tf2_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)
if alert_tf3 and tf3_isNewPeriod
if tf3_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe3, alert.freq_once_per_bar_close)
if tf3_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe3, alert.freq_once_per_bar_close)
Code: Select all
if alert_tf1 and tf1_isNewPeriod and (time > time_close(timeframe1)-(time_close-time))
if alert_tf2 and tf2_isNewPeriod and (time > time_close(timeframe2)-(time_close-time))
if alert_tf3 and tf3_isNewPeriod and (time > time_close(timeframe3)-(time_close-time))
Code: Select all
//@version=5
indicator("RSI Bull_Div Alert MTF")
enable_tf1 = true
enable_tf2 = true
enable_tf3 = true
alert_tf1 = true
alert_tf2 = true
alert_tf3 = true
tf1_col = color.blue
tf2_col = color.yellow
tf3_col = color.green
timeframe1 = "15"
timeframe2 = "30"
timeframe3 = "60"
lookback = 90
lengthRSI = 14
// ---------------------------------------------------------------------------------------------- //
cutLastDigit(str) =>
s = str + ';'
r = str.replace_all(s, '1;', '')
if r != s
[r, 1]
else
r := str.replace_all(s, '2;', '')
if r != s
[r, 2]
else
r := str.replace_all(s, '3;', '')
if r != s
[r, 3]
else
r := str.replace_all(s, '4;', '')
if r != s
[r, 4]
else
r := str.replace_all(s, '5;', '')
if r != s
[r, 5]
else
r := str.replace_all(s, '6;', '')
if r != s
[r, 6]
else
r := str.replace_all(s, '7;', '')
if r != s
[r, 7]
else
r := str.replace_all(s, '8;', '')
if r != s
[r, 8]
else
r := str.replace_all(s, '9;', '')
if r != s
[r, 9]
else
r := str.replace_all(s, '0;', '')
if r != s
[r, 0]
strToNumInt(str) =>
integer = 0 // integer part of the number
s_new = str
position = 0.0 // handled position of the number.
sign = 1 // sign of the number. 1.0 is PLUS and -1.0 is MINUS.
for i = 0 to 30 by 1
[s, digit] = cutLastDigit(s_new) // here we'll cut the digits by one from the string till the string is empty.
integer += digit * int(math.pow(10, position)) // it's just a regular digit.
position += 1
if s == ''
break
s_new := s // If we are here, then there are more digits in the string. Let's handle the next one!
s_new
sign * integer // We've exited from the loop. Build the returning value.
calculateTimeDividedBy(res) =>
timeDividiedBy = time(timeframe.period)
if strToNumInt(res) < 1440
timeDividiedBy := strToNumInt(res) * 60 * 1000
timeDividiedBy
for i = 1 to 50 by 1
if res == str.tostring(i) + 'D' or res == 'D'
timeDividiedBy := i * 1 * 86400000
break
else if res == str.tostring(i) + 'W' or res == 'W'
timeDividiedBy := i * 7 * 86400000
break
else if res == str.tostring(i) + 'M' or res == 'M'
timeDividiedBy := i * 30 * 86400000
break
timeDividiedBy
tf1_isNewPeriod = ta.change(time(timeframe1))
tf2_isNewPeriod = ta.change(time(timeframe2))
tf3_isNewPeriod = ta.change(time(timeframe3))
tf1_multiplier = calculateTimeDividedBy(timeframe1) / calculateTimeDividedBy(timeframe.period)
tf2_multiplier = calculateTimeDividedBy(timeframe2) / calculateTimeDividedBy(timeframe.period)
tf3_multiplier = calculateTimeDividedBy(timeframe3) / calculateTimeDividedBy(timeframe.period)
//////////////////////////////////////////////////////////////
rsi = ta.rsi(close, lengthRSI)
len = 14 //input(14, minval=1, title="RSI Length")
ob = 70 //input(defval=70, title="Overbought", type=input.integer, minval=0, maxval=100)
os = 30 //input(defval=30, title="Oversold", type=input.integer, minval=0, maxval=100)
hline(50, title='Fifty-Line', color=color.gray, linestyle=hline.style_solid)
seventy = hline(ob, color=color.gray, linestyle=hline.style_dashed)
thirty = hline(os, color=color.gray, linestyle=hline.style_dashed)
fill(thirty, seventy, color.new(color.purple, 90))
pl_rsi = plot(rsi, title='RSI Oscillator', color=color.new(color.purple, 0), linewidth=1)
// Inputs
scalePercentage = input.int(100, "Vertical %", step = 10, maxval = 100)
lookBack = input.int(100, "Last Bars to Look", minval = 2, step = 20)
scaleFactor = 100 / scalePercentage
//plot(volume, color = color.orange, title="Volume", style=plot.style_columns, transp=0)
hi_limit = ta.highest(rsi, lookBack)
lo_limit = ta.lowest(rsi, lookBack)
high_div =hi_limit * scaleFactor
low_div = lo_limit * scaleFactor
plot(high_div, "High", #00000000)
plot(low_div, "Low", #00000000)
/////////////////////////////////////
// Find Divergence
///////////////////////////////////
find_divergence(price_close, oscillator, lookback) =>
highest_bar = math.abs(ta.highestbars(oscillator, lookback)) // Finds bar with highest value in last X bars
lowest_bar = math.abs(ta.lowestbars(oscillator, lookback)) // Finds bar with lowest value in last X bars
// Defining variable
max_price = float(na)
max_osc = float(na)
min_price = float(na)
min_osc = float(na)
pivoth = bool(na)
pivotl = bool(na)
divbear = bool(na)
divbull = bool(na)
// If bar with lowest / highest is current bar, use it's value
max_price := highest_bar == 0 ? price_close : na(max_price[1]) ? price_close : max_price[1]
max_osc := highest_bar == 0 ? oscillator : na(max_osc[1]) ? oscillator : max_osc[1]
min_price := lowest_bar == 0 ? price_close : na(min_price[1]) ? price_close : min_price[1]
min_osc := lowest_bar == 0 ? oscillator : na(min_osc[1]) ? oscillator : min_osc[1]
// Compare high of current bar being examined with previous bar's high
// If curr bar high is higher than the max bar high in the lookback window range
if price_close > max_price // we have a new high
max_price := price_close // change variable "max" to use current bar's high value
max_price
if oscillator > max_osc // we have a new high
max_osc := oscillator // change variable "max_rsi" to use current bar's RSI value
max_osc
if price_close < min_price // we have a new low
min_price := price_close // change variable "min" to use current bar's low value
min_price
if oscillator < min_osc // we have a new low
min_osc := oscillator // change variable "min_rsi" to use current bar's RSI value
min_osc
// Finds pivot point with at least 2 right candles with lower value
pivoth := max_osc == max_osc[2] and max_osc[2] != max_osc[3] ? true : na
pivotl := min_osc == min_osc[2] and min_osc[2] != min_osc[3] ? true : na
// Detects divergences between price and indicator with 1 candle delay so it filters out repeating divergences
if max_price[1] > max_price[2] and oscillator[1] < max_osc and oscillator <= oscillator[1]
divbear := true
divbear
if min_price[1] < min_price[2] and oscillator[1] > min_osc and oscillator >= oscillator[1]
divbull := true
divbull
[divbull, divbear]
[tf1_divbull, tf1_divbear] = request.security(syminfo.ticker, timeframe1, find_divergence(close[barstate.isrealtime ? 1 : 0], rsi, lookback))
[tf2_divbull, tf2_divbear] = request.security(syminfo.ticker, timeframe2, find_divergence(close[barstate.isrealtime ? 1 : 0], rsi, lookback))
[tf3_divbull, tf3_divbear] = request.security(syminfo.ticker, timeframe3, find_divergence(close[barstate.isrealtime ? 1 : 0], rsi, lookback))
////////////////////////////
// Draw Labels
/////////////////////////
if enable_tf1 and tf1_isNewPeriod
tf1_divergence = tf1_divbear ? label.new(bar_index - 1 * tf1_multiplier, high_div, timeframe1, color=barstate.islast and not barstate.isconfirmed ? color.new(tf1_col, 80) : tf1_col, textcolor=color.black, style=label.style_label_down, yloc=yloc.price, size=size.normal) : tf1_divbull ? label.new(bar_index - 1 * tf1_multiplier, low_div, timeframe1, color=barstate.islast and not barstate.isconfirmed ? color.new(tf1_col, 80) : tf1_col, textcolor=color.black, style=label.style_label_up, yloc=yloc.price, size=size.normal) : na
if enable_tf2 and tf2_isNewPeriod
tf2_divergence = tf2_divbear ? label.new(bar_index - 1 * tf2_multiplier, high_div+10, timeframe2, color=barstate.islast and not barstate.isconfirmed ? color.new(tf2_col, 80) : tf2_col, textcolor=color.black, style=label.style_label_down, yloc=yloc.price, size=size.normal) : tf2_divbull ? label.new(bar_index - 1 * tf2_multiplier, low_div-10, timeframe2, color=barstate.islast and not barstate.isconfirmed ? color.new(tf2_col, 80) : tf2_col, textcolor=color.black, style=label.style_label_up, yloc=yloc.price, size=size.normal) : na
if enable_tf3 and tf3_isNewPeriod
tf3_divergence = tf3_divbear ? label.new(bar_index - 1 * tf3_multiplier, high_div+20, timeframe3, color=barstate.islast and not barstate.isconfirmed ? color.new(tf3_col, 80) : tf3_col, textcolor=color.black, style=label.style_label_down, yloc=yloc.price, size=size.normal) : tf3_divbull ? label.new(bar_index - 1 * tf3_multiplier, low_div-20, timeframe3, color=barstate.islast and not barstate.isconfirmed ? color.new(tf3_col, 80) : tf3_col, textcolor=color.black, style=label.style_label_up, yloc=yloc.price, size=size.normal) : na
//////////////////////////
// Create Alerts
///////////////////////
if alert_tf1 and tf1_isNewPeriod and (time > time_close(timeframe1)-(time_close-time))
if tf1_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if tf1_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if alert_tf2 and tf2_isNewPeriod and (time > time_close(timeframe2)-(time_close-time))
if tf2_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)
if tf2_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)
if alert_tf3 and tf3_isNewPeriod and (time > time_close(timeframe3)-(time_close-time))
if tf3_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe3, alert.freq_once_per_bar_close)
if tf3_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe3, alert.freq_once_per_bar_close)
Code: Select all
//////////////
// Debugging
label l_dbg = label(na)
if barstate.islast
label.delete(l_dbg[1])
dbg_txt = "tf1_isNewPeriod: " + str.tostring(tf1_isNewPeriod) + "\ntime: " + str.tostring(time) + "\ntimeframe1: " + str.tostring(timeframe1) + "\ntime_close(timeframe1): " + str.tostring(time_close(timeframe1)) + "\n\ntime_close: " + str.tostring(time_close) + "\ntime_close-time: " + str.tostring(time_close-time) + "\n\n(time > time_close(timeframe1)): " + str.tostring(time > time_close(timeframe1)) + "\n\n(time > time_close(timeframe1))-(time_close-time)): " + str.tostring(time > (time_close(timeframe1)-(time_close-time))) + "\n\ntf1_isNewPeriod and (time > time_close(timeframe1))-(time_close-time)): " + str.tostring(tf1_isNewPeriod and (time > (time_close(timeframe1)-(time_close-time))))
l_dbg := label.new(bar_index+10,low_div,text=dbg_txt, color=color.blue, textcolor=color.white, style=label.style_none, yloc=yloc.price, size=size.large)
Code: Select all
//////////////////////////
// Create Alerts
///////////////////////
if alert_tf1 and tf1_isNewPeriod and (time >= time_close(timeframe1)-(time_close-time))
if tf1_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if tf1_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if alert_tf2 and tf2_isNewPeriod and (time >= time_close(timeframe2)-(time_close-time))
if tf2_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)
if tf2_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)
if alert_tf3 and tf3_isNewPeriod and (time >= time_close(timeframe3)-(time_close-time))
if tf3_divbull
alert(syminfo.ticker + ' Bullish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe3, alert.freq_once_per_bar_close)
if tf3_divbear
alert(syminfo.ticker + ' Bearish Divergence TESTING - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe3, alert.freq_once_per_bar_close)