rsi_stoch_bb_divs.pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © dolan_0x
//@version=4
study(title="RSI/Stoch/BB/Divs (Brahim)", shorttitle="RSI/Stoch Signal", overlay=true)
// Divergences
prd = input(defval = 5, title = "Pivot Period", minval = 1, maxval = 50)
source = input(defval = "Close", title = "Source for Pivot Points", options = ["Close", "High/Low"])
searchdiv = input(defval = "Regular", title = "Divergence Type", options = ["Regular", "Hidden", "Regular/Hidden"])
showindis = input(defval = "Full", title = "Show Indicator Names", options = ["Full", "First Letter", "Don't Show"])
showlimit = input(1, title="Minimum Number of Divergence", minval = 1, maxval = 11)
maxpp = input(defval = 10, title = "Maximum Pivot Points to Check", minval = 1, maxval = 20)
maxbars = input(defval = 100, title = "Maximum Bars to Check", minval = 30, maxval = 200)
shownum = input(defval = true, title = "Show Divergence Number")
showlast = input(defval = false, title = "Show Only Last Divergence")
dontconfirm = input(defval = false, title = "Don't Wait for Confirmation")
showlines = input(defval = true, title = "Show Divergence Lines")
showpivot = input(defval = false, title = "Show Pivot Points")
calcmacd = input(defval = true, title = "MACD")
calcmacda = input(defval = true, title = "MACD Histogram")
calcrsi = input(defval = true, title = "RSI")
calcstoc = input(defval = true, title = "Stochastic")
calccci = input(defval = false, title = "CCI")
calcmom = input(defval = false, title = "Momentum")
calcobv = input(defval = false, title = "OBV")
calcvwmacd = input(false, title = "VWmacd")
calccmf = input(false, title = "Chaikin Money Flow")
calcmfi = input(false, title = "Money Flow Index")
calcext = input(false, title = "Check External Indicator")
externalindi = input(defval = close, title = "External Indicator")
pos_reg_div_col = input(defval = color.yellow, title = "Positive Regular Divergence")
neg_reg_div_col = input(defval = color.navy, title = "Negative Regular Divergence")
pos_hid_div_col = input(defval = color.lime, title = "Positive Hidden Divergence")
neg_hid_div_col = input(defval = color.red, title = "Negative Hidden Divergence")
pos_div_text_col = input(defval = color.black, title = "Positive Divergence Text Color")
neg_div_text_col = input(defval = color.white, title = "Negative Divergence Text Color")
reg_div_l_style_ = input(defval = "Solid", title = "Regular Divergence Line Style", options = ["Solid", "Dashed", "Dotted"])
hid_div_l_style_ = input(defval = "Dashed", title = "Hdden Divergence Line Style", options = ["Solid", "Dashed", "Dotted"])
reg_div_l_width = input(defval = 2, title = "Regular Divergence Line Width", minval = 1, maxval = 5)
hid_div_l_width = input(defval = 1, title = "Hidden Divergence Line Width", minval = 1, maxval = 5)
showmas = input(defval = false, title = "Show MAs 50 & 200", inline = "ma12")
cma1col = input(defval = color.lime, title = "", inline = "ma12")
cma2col = input(defval = color.red, title = "", inline = "ma12")
plot(showmas ? sma(close, 50) : na, color = showmas ? cma1col : na)
plot(showmas ? sma(close, 200) : na, color = showmas ? cma2col: na)
// set line styles
var reg_div_l_style = reg_div_l_style_ == "Solid" ? line.style_solid :
reg_div_l_style_ == "Dashed" ? line.style_dashed :
line.style_dotted
var hid_div_l_style = hid_div_l_style_ == "Solid" ? line.style_solid :
hid_div_l_style_ == "Dashed" ? line.style_dashed :
line.style_dotted
// get indicators
rsi = rsi(close, 14) // RSI
[macd, signal, deltamacd] = macd(close, 12, 26, 9) // MACD
moment = mom(close, 10) // Momentum
cci = cci(close, 10) // CCI
Obv = obv // OBV
stk = sma(stoch(close, high, low, 14), 3) // Stoch
maFast = vwma(close, 12), maSlow = vwma(close, 26), vwmacd = maFast - maSlow // volume weighted macd
Cmfm = ((close-low) - (high-close)) / (high - low), Cmfv = Cmfm * volume, cmf = sma(Cmfv, 21) / sma(volume,21) // Chaikin money flow
Mfi = mfi(close, 14) // Moneyt Flow Index
// keep indicators names and colors in arrays
var indicators_name = array.new_string(11)
var div_colors = array.new_color(4)
if barstate.isfirst
// names
array.set(indicators_name, 0, showindis == "Full" ? "MACD" : "M")
array.set(indicators_name, 1, showindis == "Full" ? "Hist" : "H")
array.set(indicators_name, 2, showindis == "Full" ? "RSI" : "E")
array.set(indicators_name, 3, showindis == "Full" ? "Stoch" : "S")
array.set(indicators_name, 4, showindis == "Full" ? "CCI" : "C")
array.set(indicators_name, 5, showindis == "Full" ? "MOM" : "M")
array.set(indicators_name, 6, showindis == "Full" ? "OBV" : "O")
array.set(indicators_name, 7, showindis == "Full" ? "VWMACD" : "V")
array.set(indicators_name, 8, showindis == "Full" ? "CMF" : "C")
array.set(indicators_name, 9, showindis == "Full" ? "MFI" : "M")
array.set(indicators_name,10, showindis == "Full" ? "Extrn" : "X")
//colors
array.set(div_colors, 0, pos_reg_div_col)
array.set(div_colors, 1, neg_reg_div_col)
array.set(div_colors, 2, pos_hid_div_col)
array.set(div_colors, 3, neg_hid_div_col)
// Check if we get new Pivot High Or Pivot Low
float ph = pivothigh((source == "Close" ? close : high), prd, prd)
float pl = pivotlow((source == "Close" ? close : low), prd, prd)
plotshape(ph and showpivot, text = "H", style = shape.labeldown, color = color.new(color.white, 100), textcolor = color.red, location = location.abovebar, offset = -prd)
plotshape(pl and showpivot, text = "L", style = shape.labelup, color = color.new(color.white, 100), textcolor = color.lime, location = location.belowbar, offset = -prd)
// keep values and positions of Pivot Highs/Lows in the arrays
var int maxarraysize = 20
var ph_positions = array.new_int(maxarraysize, 0)
var pl_positions = array.new_int(maxarraysize, 0)
var ph_vals = array.new_float(maxarraysize, 0.)
var pl_vals = array.new_float(maxarraysize, 0.)
// add PHs to the array
if ph
array.unshift(ph_positions, bar_index)
array.unshift(ph_vals, ph)
if array.size(ph_positions) > maxarraysize
array.pop(ph_positions)
array.pop(ph_vals)
// add PLs to the array
if pl
array.unshift(pl_positions, bar_index)
array.unshift(pl_vals, pl)
if array.size(pl_positions) > maxarraysize
array.pop(pl_positions)
array.pop(pl_vals)
// functions to check Regular Divergences and Hidden Divergences
// function to check positive regular or negative hidden divergence
// cond == 1 => positive_regular, cond == 2=> negative_hidden
positive_regular_positive_hidden_divergence(src, cond)=>
divlen = 0
prsc = source == "Close" ? close : low
// if indicators higher than last value and close price is higher than las close
if dontconfirm or src > src[1] or close > close[1]
startpoint = dontconfirm ? 0 : 1 // don't check last candle
// we search last 15 PPs
for x = 0 to maxpp - 1
len = bar_index - array.get(pl_positions, x) + prd
// if we reach non valued array element or arrived 101. or previous bars then we don't search more
if array.get(pl_positions, x) == 0 or len > maxbars
break
if len > 5 and
((cond == 1 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(pl_vals, x))) or
(cond == 2 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(pl_vals, x))))
slope1 = (src[startpoint] - src[len]) / (len - startpoint)
virtual_line1 = src[startpoint] - slope1
slope2 = (close[startpoint] - close[len]) / (len - startpoint)
virtual_line2 = close[startpoint] - slope2
arrived = true
for y = 1 + startpoint to len - 1
if src[y] < virtual_line1 or nz(close[y]) < virtual_line2
arrived := false
break
virtual_line1 := virtual_line1 - slope1
virtual_line2 := virtual_line2 - slope2
if arrived
divlen := len
break
divlen
// function to check negative regular or positive hidden divergence
// cond == 1 => negative_regular, cond == 2=> positive_hidden
negative_regular_negative_hidden_divergence(src, cond)=>
divlen = 0
prsc = source == "Close" ? close : high
// if indicators higher than last value and close price is higher than las close
if dontconfirm or src < src[1] or close < close[1]
startpoint = dontconfirm ? 0 : 1 // don't check last candle
// we search last 15 PPs
for x = 0 to maxpp - 1
len = bar_index - array.get(ph_positions, x) + prd
// if we reach non valued array element or arrived 101. or previous bars then we don't search more
if array.get(ph_positions, x) == 0 or len > maxbars
break
if len > 5 and
((cond == 1 and src[startpoint] < src[len] and prsc[startpoint] > nz(array.get(ph_vals, x))) or
(cond == 2 and src[startpoint] > src[len] and prsc[startpoint] < nz(array.get(ph_vals, x))))
slope1 = (src[startpoint] - src[len]) / (len - startpoint)
virtual_line1 = src[startpoint] - slope1
slope2 = (close[startpoint] - nz(close[len])) / (len - startpoint)
virtual_line2 = close[startpoint] - slope2
arrived = true
for y = 1 + startpoint to len - 1
if src[y] > virtual_line1 or nz(close[y]) > virtual_line2
arrived := false
break
virtual_line1 := virtual_line1 - slope1
virtual_line2 := virtual_line2 - slope2
if arrived
divlen := len
break
divlen
// calculate 4 types of divergence if enabled in the options and return divergences in an array
calculate_divs(cond, indicator)=>
divs = array.new_int(4, 0)
array.set(divs, 0, cond and (searchdiv == "Regular" or searchdiv == "Regular/Hidden") ? positive_regular_positive_hidden_divergence(indicator, 1) : 0)
array.set(divs, 1, cond and (searchdiv == "Regular" or searchdiv == "Regular/Hidden") ? negative_regular_negative_hidden_divergence(indicator, 1) : 0)
array.set(divs, 2, cond and (searchdiv == "Hidden" or searchdiv == "Regular/Hidden") ? positive_regular_positive_hidden_divergence(indicator, 2) : 0)
array.set(divs, 3, cond and (searchdiv == "Hidden" or searchdiv == "Regular/Hidden") ? negative_regular_negative_hidden_divergence(indicator, 2) : 0)
divs
// array to keep all divergences
var all_divergences = array.new_int(44) // 11 indicators * 4 divergence = 44 elements
// set related array elements
array_set_divs(div_pointer, index)=>
for x = 0 to 3
array.set(all_divergences, index * 4 + x, array.get(div_pointer, x))
// set divergences array
array_set_divs(calculate_divs(calcmacd, macd), 0)
array_set_divs(calculate_divs(calcmacda, deltamacd), 1)
array_set_divs(calculate_divs(calcrsi, rsi), 2)
array_set_divs(calculate_divs(calcstoc, stk), 3)
array_set_divs(calculate_divs(calccci, cci), 4)
array_set_divs(calculate_divs(calcmom, moment), 5)
array_set_divs(calculate_divs(calcobv, Obv), 6)
array_set_divs(calculate_divs(calcvwmacd, vwmacd), 7)
array_set_divs(calculate_divs(calccmf, cmf), 8)
array_set_divs(calculate_divs(calcmfi, Mfi), 9)
array_set_divs(calculate_divs(calcext, externalindi), 10)
// check minimum number of divergence, if less than showlimit then delete all divergence
total_div = 0
for x = 0 to array.size(all_divergences) - 1
total_div := total_div + round(sign(array.get(all_divergences, x)))
if total_div < showlimit
array.fill(all_divergences, 0)
// keep line in an array
var pos_div_lines = array.new_line(0)
var neg_div_lines = array.new_line(0)
var pos_div_labels = array.new_label(0)
var neg_div_labels = array.new_label(0)
// remove old lines and labels if showlast option is enabled
delete_old_pos_div_lines()=>
if array.size(pos_div_lines) > 0
for j = 0 to array.size(pos_div_lines) - 1
line.delete(array.get(pos_div_lines, j))
array.clear(pos_div_lines)
delete_old_neg_div_lines()=>
if array.size(neg_div_lines) > 0
for j = 0 to array.size(neg_div_lines) - 1
line.delete(array.get(neg_div_lines, j))
array.clear(neg_div_lines)
delete_old_pos_div_labels()=>
if array.size(pos_div_labels) > 0
for j = 0 to array.size(pos_div_labels) - 1
label.delete(array.get(pos_div_labels, j))
array.clear(pos_div_labels)
delete_old_neg_div_labels()=>
if array.size(neg_div_labels) > 0
for j = 0 to array.size(neg_div_labels) - 1
label.delete(array.get(neg_div_labels, j))
array.clear(neg_div_labels)
// delete last created lines and labels until we met new PH/PV
delete_last_pos_div_lines_label(n)=>
if n > 0 and array.size(pos_div_lines) >= n
asz = array.size(pos_div_lines)
for j = 1 to n
line.delete(array.get(pos_div_lines, asz - j))
array.pop(pos_div_lines)
if array.size(pos_div_labels) > 0
label.delete(array.get(pos_div_labels, array.size(pos_div_labels) - 1))
array.pop(pos_div_labels)
delete_last_neg_div_lines_label(n)=>
if n > 0 and array.size(neg_div_lines) >= n
asz = array.size(neg_div_lines)
for j = 1 to n
line.delete(array.get(neg_div_lines, asz - j))
array.pop(neg_div_lines)
if array.size(neg_div_labels) > 0
label.delete(array.get(neg_div_labels, array.size(neg_div_labels) - 1))
array.pop(neg_div_labels)
// variables for Alerts
pos_reg_div_detected = false
neg_reg_div_detected = false
pos_hid_div_detected = false
neg_hid_div_detected = false
// to remove lines/labels until we met new // PH/PL
var last_pos_div_lines = 0
var last_neg_div_lines = 0
var remove_last_pos_divs = false
var remove_last_neg_divs = false
if pl
remove_last_pos_divs := false
last_pos_div_lines := 0
if ph
remove_last_neg_divs := false
last_neg_div_lines := 0
// draw divergences lines and labels
divergence_text_top = ""
divergence_text_bottom = ""
distances = array.new_int(0)
dnumdiv_top = 0
dnumdiv_bottom = 0
top_label_col = color.white
bottom_label_col = color.white
old_pos_divs_can_be_removed = true
old_neg_divs_can_be_removed = true
startpoint = dontconfirm ? 0 : 1 // used for don't confirm option
removed_unconfirmed_neg_div = false
removed_unconfirmed_pos_div = false
for x = 0 to 10
div_type = -1
for y = 0 to 3
if array.get(all_divergences, x * 4 + y) > 0 // any divergence?
div_type := y
if (y % 2) == 1
dnumdiv_top := dnumdiv_top + 1
top_label_col := array.get(div_colors, y)
if (y % 2) == 0
dnumdiv_bottom := dnumdiv_bottom + 1
bottom_label_col := array.get(div_colors, y)
if not array.includes(distances, array.get(all_divergences, x * 4 + y)) // line not exist ?
array.push(distances, array.get(all_divergences, x * 4 + y))
new_line = showlines ? line.new(x1 = bar_index - array.get(all_divergences, x * 4 + y),
y1 = (source == "Close" ? close[array.get(all_divergences, x * 4 + y)] :
(y % 2) == 0 ? low[array.get(all_divergences, x * 4 + y)] :
high[array.get(all_divergences, x * 4 + y)]),
x2 = bar_index - startpoint,
y2 = (source == "Close" ? close[startpoint] :
(y % 2) == 0 ? low[startpoint] :
high[startpoint]),
color = array.get(div_colors, y),
style = y < 2 ? reg_div_l_style : hid_div_l_style,
width = y < 2 ? reg_div_l_width : hid_div_l_width
)
: na
if (y % 2) == 0
if old_pos_divs_can_be_removed
old_pos_divs_can_be_removed := false
if not showlast and remove_last_pos_divs
delete_last_pos_div_lines_label(last_pos_div_lines)
last_pos_div_lines := 0
if showlast
delete_old_pos_div_lines()
array.push(pos_div_lines, new_line)
last_pos_div_lines := last_pos_div_lines + 1
remove_last_pos_divs := true
if (y % 2) == 1
if old_neg_divs_can_be_removed
old_neg_divs_can_be_removed := false
if not showlast and remove_last_neg_divs
delete_last_neg_div_lines_label(last_neg_div_lines)
last_neg_div_lines := 0
removed_unconfirmed_neg_div := true
if showlast
delete_old_neg_div_lines()
array.push(neg_div_lines, new_line)
last_neg_div_lines := last_neg_div_lines + 1
remove_last_neg_divs := true
// set variables for alerts
if y == 0
pos_reg_div_detected := true
if y == 1
neg_reg_div_detected := true
if y == 2
pos_hid_div_detected := true
if y == 3
neg_hid_div_detected := true
// get text for labels
if div_type >= 0
divergence_text_top := divergence_text_top + ((div_type % 2) == 1 ? (showindis != "Don't Show" ? array.get(indicators_name, x) + "\n" : "") : "")
divergence_text_bottom := divergence_text_bottom + ((div_type % 2) == 0 ? (showindis != "Don't Show" ? array.get(indicators_name, x) + "\n" : "") : "")
// draw labels
if showindis != "Don't Show" or shownum
if shownum and dnumdiv_top > 0
divergence_text_top := divergence_text_top + tostring(dnumdiv_top)
if shownum and dnumdiv_bottom > 0
divergence_text_bottom := divergence_text_bottom + tostring(dnumdiv_bottom)
if divergence_text_top != ""
if showlast
delete_old_neg_div_labels()
array.push(neg_div_labels,
label.new( x = bar_index,
y = max(high, high[1]),
text = divergence_text_top,
color = top_label_col,
textcolor = neg_div_text_col,
style = label.style_label_down
))
if divergence_text_bottom != ""
if showlast
delete_old_pos_div_labels()
array.push(pos_div_labels,
label.new( x = bar_index,
y = min(low, low[1]),
text = divergence_text_bottom,
color = bottom_label_col,
textcolor = pos_div_text_col,
style = label.style_label_up
))
// plotshape(pos_reg_div_detected, title= "Should Buy", location=location.belowbar, color=color.green, transp=0, style=shape.triangleup, text="BUY")
// plotshape(neg_reg_div_detected, title= "Should Sell", location=location.belowbar, color=color.red, transp=0, style=shape.triangledown, text="SELL")
// GetPipSize() =>
// syminfo.mintick * (syminfo.type == "forex" ? 10 : 1)
// take_profit_pips = 50
// stop_loss_pips = 50
// pipSize = GetPipSize()
// price_target = close + (take_profit_pips * pipSize)
// price_stop_loss = close - (stop_loss_pips * pipSize)
// long_qty = 5
// short_qty = 5
// if (pos_reg_div_detected and dnumdiv_bottom >= 4)
// long_strategy_id = "Long Entry "+tostring(bar_index)+ " ("+tostring(close)+")"
// exit_long_strategy_id = "Exit Long "+tostring(bar_index)
// strategy.entry(long_strategy_id, strategy.long, qty = long_qty) // Buy Market Order at bar close
// strategy.exit(exit_long_strategy_id,long_strategy_id,profit = take_profit_pips, loss = stop_loss_pips)
// if (neg_reg_div_detected and dnumdiv_top >= 4)
// short_strategy_id = "Short Entry "+tostring(bar_index)+ " ("+tostring(close)+")"
// exit_short_strategy_id = "Exit Short "+tostring(bar_index)
// strategy.entry(short_strategy_id, strategy.short, qty = short_qty)
// strategy.exit(exit_short_strategy_id,short_strategy_id,profit = take_profit_pips, loss = stop_loss_pips)
// Bollinger
length = input(title="Length", type=input.integer, defval=20, minval=1)
src = input(close, title="Source")
mult = input(type=input.float, defval=2.0, minval=0.001, maxval=50, title="StdDev")
offset = input(defval=10, title="Offset", type=input.integer, minval = -500, maxval = 500)
near_offset = input(defval=20, title="Near Offset", type=input.integer)
basis = sma(src, length)
dev = mult * stdev(src, length)
upper = basis + dev
lower = basis - dev
between(price, min,max) =>
is_between = price <= max and price >= min
is_between
isPriceNearLower(lower, price) =>
max = lower + near_offset
min = lower - near_offset
is_near = between(price, min, max)
is_near
isPriceNearUpper(upper, price) =>
max = upper + near_offset
min = upper - near_offset
is_near = between(price, min, max)
is_near
price_near_lower_bb = isPriceNearLower(lower, low)
price_near_upper_bb = isPriceNearUpper(upper, high)
// RSI inputs
rsi_source = input(title="RSI Source", type=input.source, defval=close)
rsi_length = input(title="RSI stoch_length", type=input.integer, defval=7)
rsi_over_bought_level = input(title="RSI Overbought Level", type=input.integer, defval=70)
rsi_over_sold_level = input(title="RSI Oversold Level", type=input.integer, defval=30)
isRSIOverBought(rsi_over_bought_level) =>
rsiValue = rsi(rsi_source, rsi_length)
is_over_bought = rsiValue >= rsi_over_bought_level
is_over_bought
isRSIOverSold(rsi_over_sold_level) =>
rsiValue = rsi(rsi_source, rsi_length)
is_over_sold = rsiValue <= rsi_over_sold_level
is_over_sold
// Stoch inputs
stoch_length = input(defval=14, minval=1, title = "Stochastic Length")
k = input(defval=1, minval=1, title = "Stochastic %K")
d = input(defval=3, minval=1, title = "Stochastic %D")
stoch_over_bought_level = input(title="RSI Overbought Level", type=input.integer, defval=80)
stoch_over_sold_level = input(title="RSI Oversold Level", type=input.integer, defval=20)
isStochOverBought(stoch_over_bought_level, k) =>
Sto = stoch (close, high, low, stoch_length)
K= sma (Sto, k)
is_over_bought = K >= stoch_over_bought_level
is_over_bought
isStochOverSold(stoch_over_sold_level, k) =>
Sto = stoch (close, high, low, stoch_length)
K= sma (Sto, k)
is_over_sold = K <= stoch_over_sold_level
is_over_sold
price_is_over_bought = isRSIOverBought(rsi_over_bought_level) and isStochOverBought(stoch_over_bought_level, k)
price_is_over_sold = isRSIOverSold(rsi_over_sold_level) and isStochOverSold(stoch_over_sold_level, k)
// All combined
should_buy() =>
conditions_met = price_is_over_sold and price_near_lower_bb and pos_reg_div_detected
conditions_met
should_sell() =>
conditions_met = price_is_over_bought and price_near_upper_bb and neg_reg_div_detected
conditions_met
plotshape(should_buy(), title= "Should Buy", location=location.belowbar, color=color.green, transp=0, style=shape.triangleup, text="BUY")
plotshape(should_sell(), title= "Should Sell", location=location.belowbar, color=color.red, transp=0, style=shape.triangledown, text="SELL")
// Plot
// plotshape(price_is_over_bought, title= "Overbought", location=location.abovebar, color=color.red, transp=0, style=shape.triangledown, text="OB")
// plotshape(price_is_over_sold, title= "Oversold", location=location.belowbar, color=color.green, transp=0, style=shape.triangleup, text="OS")
// alertcondition(price_is_over_bought or price_is_over_sold, title="Stoch Alert!", message="Stoch Alert")
Show all 534 lines