Multi Oscillators Price Levels
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © noop42

//@version=5
indicator(title='Multi Oscillators Price Levels', shorttitle='MOPL', overlay=true)

// Input parameters
src = input(close, title='Source')
src_ind = input.string(title='Source indicator', defval='RSI', options=['Stochastic RSI', 'Stochastic CCI', 'RSI', 'CCI'], group='Options')
custom_timeframe = input.timeframe(title='Timeframe', defval='', group='Options')

// Drawing options
show_sup = input.bool(title='Show supports', defval=true, group='Drawings')
show_res = input.bool(title='Show resistances', defval=true, group='Drawings')
lines_width = input.int(title='Lines width', defval=10 , group='Drawings')
sup_src = input.source(title='Draw supports on', defval=low, group='Drawings')
res_src = input.source(title='Draw resistances on', defval=high, group='Drawings')
extend_level = input.string('None', title='Extend levels', options=['Right', 'Left', 'Both', 'None'], group='Drawings')
sup_col = input.color(title='Supports color', defval=#34eb3a70, group='Drawings')
res_col = input.color(title='Resistances color', defval=#eb473170, group='Drawings')

// Indicators
smoothKD = input.int(3, 'K & D smoothing', minval=1, group='Stoch RSI/CCI')
lengthStoch = input.int(14, 'Stochastic Length', minval=1, group='Stoch RSI/CCI')
stoch_low = input.int(20, title='Stoch Oversold Level', group='Stoch RSI/CCI')
stoch_high = input.int(80, title='Stoch Overbought Level', group='Stoch RSI/CCI')

lengthRSI = input.int(14, 'RSI Length', minval=1, group='RSI / Stoch RSI')
rsi_low = input.int(30, title='RSI Oversold Level', group='RSI')
rsi_high = input.int(70, title='RSI Overbought Level', group='RSI')

lengthCCI = input.int(20, 'CCI Length', minval=1, group='CCI')
cci_low = input.int(-100, title='CCI Oversold Level', group='CCI')
cci_high = input.int(100, title='CCI Overbought Level', group='CCI')

// Indicators Data
rsi_tf = request.security(syminfo.tickerid, custom_timeframe, ta.rsi(src, lengthRSI))
cci_tf = request.security(syminfo.tickerid, custom_timeframe, ta.cci(src, lengthCCI))

stoch_k_tf = request.security(syminfo.tickerid, custom_timeframe, ta.sma(ta.stoch(rsi_tf, rsi_tf, rsi_tf, lengthStoch), smoothKD))
stoch_d_tf = request.security(syminfo.tickerid, custom_timeframe, ta.sma(stoch_k_tf, smoothKD))

stock_k_cci_tf = request.security(syminfo.tickerid, custom_timeframe, ta.sma(ta.stoch(cci_tf, cci_tf, cci_tf, lengthStoch), smoothKD))
stoch_d_cci_tf = request.security(syminfo.tickerid, custom_timeframe, ta.sma(stock_k_cci_tf, smoothKD))

avgscci = (stock_k_cci_tf + stoch_d_cci_tf ) / 2
avgsrsi = (stoch_k_tf + stoch_d_tf) / 2

// Extreme zones
srsi_ob = avgsrsi > stoch_high
srsi_os = avgsrsi < stoch_low

scci_ob = avgscci > stoch_high
scci_os = avgscci < stoch_low

rsiob = rsi_tf > rsi_high
rsios = rsi_tf < rsi_low

cciob = cci_tf > cci_high
ccios = cci_tf < cci_low

// Indicator signal selection
ob = src_ind == 'RSI' ? rsiob : src_ind == 'CCI' ? cciob : src_ind == 'Stochastic RSI' ? srsi_ob : scci_ob
os = src_ind == 'RSI' ? rsios : src_ind == 'CCI' ? ccios : src_ind == 'Stochastic RSI' ? srsi_os : scci_os

// Price lines
sup_final_src = request.security(syminfo.tickerid, custom_timeframe, sup_src)
res_final_src = request.security(syminfo.tickerid, custom_timeframe, res_src)

var support = sup_final_src
var resistance = res_final_src

//Set current levels
support := os and not os[1] ? sup_final_src : support
resistance := ob and not ob[1] ? res_final_src : resistance

// Update current levels
support := (os and os[1]) and (sup_final_src < support) ? sup_final_src : support
resistance := (ob and ob[1]) and (res_final_src > resistance) ? res_final_src : resistance

ext = extend_level == "Right" ? extend.right : extend_level == "Left" ? extend.left : extend_level == "Both" ? extend.both : extend.none

var line sup = na
var line res = na
var int sup_offset = 0
var int res_offset = 0

// Draw current 
if show_sup and (not os) and os[1]
    sup := line.new(bar_index[1], support, bar_index, support, extend=ext, color=sup_col, width=lines_width)
else
    line.set_x2(sup, line.get_x2(sup) +1)
if show_res and (not ob) and ob[1]
    res := line.new(bar_index[1], resistance, bar_index, resistance, extend=ext, color=res_col, width=lines_width)
else
    line.set_x2(res, line.get_x2(res) +1)
    

