Ah sorry, my apologies, I only included some code snippets to illustrate what I was trying to do rather than the whole code block - which is why it wouldn't compile. I have included a full compiled block below.
Code: Select all
//@version=5
indicator("My script")
enable_tf1 = true
enable_tf2 = true
alert_tf1 = true
alert_tf2 = true
tf1_col = color.blue
tf2_col = color.purple
timeframe1 = "60"
timeframe2 = "240"
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))
tf1_multiplier = calculateTimeDividedBy(timeframe1) / calculateTimeDividedBy(timeframe.period)
tf2_multiplier = calculateTimeDividedBy(timeframe2) / calculateTimeDividedBy(timeframe.period)
rsi = ta.rsi(close, lengthRSI)
/////////////////////////////////////
// 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))
////////////////////////////
// Draw Labels
/////////////////////////
if enable_tf1 and tf1_isNewPeriod
tf1_divergence = tf1_divbear ? label.new(bar_index - 1 * tf1_multiplier, 90, '3', 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, 10, '3', 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, 90, '3', 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, 10, '3', 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
//////////////////////////
// Create Alerts
///////////////////////
if alert_tf1 and tf1_isNewPeriod and barstate.isconfirmed
if tf1_divbull
alert(syminfo.ticker + ' Bullish Divergence - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if tf1_divbear
alert(syminfo.ticker + ' Bearish Divergence - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe1, alert.freq_once_per_bar_close)
if alert_tf2 and tf2_isNewPeriod and barstate.isconfirmed
if tf2_divbull
alert(syminfo.ticker + ' Bullish Divergence - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)
if tf2_divbear
alert(syminfo.ticker + ' Bearish Divergence - Price: ' + str.tostring(close) + ' - Timeframe: ' + timeframe2, alert.freq_once_per_bar_close)