Any Screener (Multiple)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/

// ╔═══════════════════════════════════════════════════════════╗
// ║  Author & Developer : © dg_factor [18.07.2023, Istanbul]  ║
// ╚═══════════════════════════════════════════════════════════╝

//@version=5
indicator("Any Screener (Multiple)", overlay=true)

// ╔═══════════════════════════════════════════════════════════════════════════╗
// ║                          SECTION 1 : INDICATORS                           ║
// ╚═══════════════════════════════════════════════════════════════════════════╝
//{
// ╠═════════════════════════════════ Inputs ══════════════════════════════════╣

// Tooltips
string tt_per = 
  "When the percentage is 0.0,\n" + 
  "OTT is disabled and the signals are generated by the crossing of the closing price and the selected moving average."
string tt_osc = 
  "This option disables sequential signals in the same direction.\n" +
  "ON : The Scanner shows how many bars have passed since the direction changed.\n" +
  "OFF : The Scanner shows how many bars have passed since the last signal."
string tt_volt =
  "BANDWIDTH and REGRESSION have been normalized. (For all time chart)" 
//
string gr_ott = "╠═══════════════ OTT ═══════════════╣"
mov_type = input.string(title="Type", defval="VAR", options=["SMA", "EMA", "EVWMA", "HULL", "VAR"], group=gr_ott) 
ott_len  = input.int(title="Length ", defval=50, group=gr_ott)
ott_per  = input.float(title="Percent ", defval=2.5, group=gr_ott, tooltip=tt_per)
ott_sign = input.bool(title="Show Signals", defval=false, group=gr_ott)
string gr_sar = "╠══════════════ PSAR ════════════════╣"
sar_start = input.float(title="Start ", defval=0.02, group=gr_sar)
sar_inc   = input.float(title="Increment ", defval=0.02, group=gr_sar)
sar_max   = input.float(title="Max", defval=0.2, group=gr_sar)
sar_sign  = input.bool(title="Show Signals", defval=false, group=gr_sar)
string gr_osc = "╠════════════ OSCILLATOR ════════════╣"
osc_type = input.string(title="Type", defval="MFI", options=["MFI", "RSI", "STOCH"], group=gr_osc)
osc_len  = input.int(title="Length ", defval=14, group=gr_osc)
osc_os   = input.int(title="Over Sold", defval=30, group=gr_osc)
osc_ob   = input.int(title="Over Bought", defval=70, group=gr_osc)
osc_pyr  = input.bool(title="Avoid Pyramiding", defval=true, group=gr_osc, tooltip=tt_osc)
osc_sign = input.bool(title="Show Signals", defval=false, group=gr_osc)
string gr_volt = "╠══════════ VOLATILITY & TREND ══════════╣"
volt_type = input.string(title="Type", defval="REG-N", options=["ADX", "BBW-N", "REG-N"], group=gr_volt, tooltip=tt_volt)
volt_len  = input.int(title="Length ", defval=14, group=gr_volt)
//

// ╠════════════════════════════════ Functions ════════════════════════════════╣

// Hull Moving Average [HULL]
f_hull(series float x, series int y) =>
    a = y == 1 ? 1 : y / 2
    b = 2 * ta.wma(x, a) - ta.wma(x, y)
    r = ta.wma(b, math.round(math.sqrt(y)))
//

// Elastic Volume Weighted Moving Average [EVWMA]
f_evwma(series float x, series int y) =>
    a = ta.sma(x, y)
    b = math.sum(volume, y)
    r = 0.0, r := na(r[1]) ? a : nz(r[1]) * (b - volume) / b + volume * x / b
//

// Variable Index Dynamic Adaptive Moving Average [VAR]
f_var(series float x, series int y) =>
    a = ta.sma(x, y)
    b = math.abs(ta.change(x, 9))
    c = math.sum(math.abs(ta.change(x)), 9)
    d = c != 0 ? b / c : 0
    e = 2 / (y + 1)
    r = 0.0, r := na(r[1]) ? a : d * e * (x - nz(r[1])) + nz(r[1])
//

// Moving Average 
f_mov(simple string x, series float y, simple int z) =>
      x == "SMA"   ? ta.sma(y, z)  : 
      x == "EMA"   ? ta.ema(y, z)  : 
      x == "EVWMA" ? f_evwma(y, z) : 
      x == "HULL"  ? f_hull(y, z)  : 
      x == "VAR"   ? f_var(y, z)   : na 
//

// Optimized Trend Tracker
f_ott(series float x, series float y) =>
    a = y / 100
    b = x * a, c = x - b, d = x + b
    c := c > nz(c[1]) or x < nz(c[1]) ? c : nz(c[1])
    d := d < nz(d[1]) or x > nz(d[1]) ? d : nz(d[1])
    e = 0.0, e := x > nz(e[1]) ? c : x < nz(e[1]) ? d : nz(e[1]) 
    f = 1 + a / 2
    g = 1 - a / 2
    h = x > e ? e * f : e * g
    r = nz(h[2])
//

// Oscillator
f_osc(simple string x, simple int y) =>
      x == "MFI"   ? ta.mfi(hlc3, y)  : 
      x == "RSI"   ? ta.rsi(close, y) : 
      x == "STOCH" ? ta.stoch(close, high, low, y) : na
//

// Volatility
f_volt(simple string x, simple int y) =>
    [_, _, a] = ta.dmi(y, y)
    b = ta.bbw(close, y, 2)
    c = math.sqrt(ta.sma(math.pow(close - ta.linreg(close, y, 0), 2), y))
    r = 
      x == "ADX" ? a : 
      x == "BBW-N" ? (b - ta.min(b)) / (ta.max(b) - ta.min(b)) * 100 : 
      x == "REG-N" ? (c - ta.min(c)) / (ta.max(c) - ta.min(c)) * 100 : 
      na 
//

// ╠═══════════════════════════════════ Out ═══════════════════════════════════╣

// Return
_sup   = f_mov(mov_type, close, ott_len)
_ott   = f_ott(_sup, ott_per)
_sar   = ta.sar(sar_start, sar_inc, sar_max)
_osc   = f_osc(osc_type, osc_len)
osc_l  = ta.crossover(_osc, osc_os)
osc_s  = ta.crossunder(_osc, osc_ob)
osc_bl = ta.barssince(osc_l) < ta.barssince(osc_s)
osc_bs = ta.barssince(osc_l) > ta.barssince(osc_s)
_volt  = f_volt(volt_type, volt_len)

// ╠════════════════════════════ Data For Screener ════════════════════════════╣

// Long Conditions
long_1 = ott_per != 0.0 ? ta.crossover(_sup, _ott) : ta.crossover(close, _sup)
long_2 = ta.crossover(close, _sar)
long_3 = not osc_pyr ? osc_l : ta.cum(osc_l ? 1 : na) == 1 or osc_bl and (osc_bs[1] or not osc_bl[1])

// Short Conditions
short_1 = ott_per != 0.0 ? ta.crossunder(_sup, _ott) : ta.crossunder(close, _sup)
short_2 = ta.crossunder(close, _sar)
short_3 = not osc_pyr ? osc_s : ta.cum(osc_s ? 1 : na) == 1 or osc_bs and (osc_bl[1] or not osc_bs[1])

// Text Only
text_only = _volt

// Titles are required for the table
string title_1 = ott_per != 0.0 ? "OTT" : mov_type
string title_2 = "PSAR"
string title_3 = osc_type
string title_4 = volt_type

// ╠══════════════════════════════ Plot Signals ═══════════════════════════════╣

sl = shape.triangleup,  ss = shape.triangledown, 
ll = location.belowbar, ls = location.abovebar, 
sz = size.tiny, cl = #00bb00, cs = #bb0000

plotshape(ott_sign ? ott_per != 0.0 and long_1  : na, "OTT Long",  sl, ll, cl, text="OTT\nLong",  textcolor=cl, size=sz)
plotshape(ott_sign ? ott_per != 0.0 and short_1 : na, "OTT Short", ss, ls, cs, text="OTT\nShort", textcolor=cs, size=sz)
plotshape(ott_sign ? ott_per == 0.0 and long_1  : na, "MA Long",  sl, ll, cl, text="MA\nLong",  textcolor=cl, size=sz)
plotshape(ott_sign ? ott_per == 0.0 and short_1 : na, "MA Short", ss, ls, cs, text="MA\nShort", textcolor=cs, size=sz)
plotshape(sar_sign ? long_2  : na, "PSAR Long",  sl, ll, cl, text="PSAR\nLong",  textcolor=cl, size=sz)
plotshape(sar_sign ? short_2 : na, "PSAR Short", ss, ls, cs, text="PSAR\nShort", textcolor=cs, size=sz)
plotshape(osc_sign ? long_3  : na, "OSC Long",  sl, ll, cl, text="OSC\nLong",  textcolor=cl, size=sz)
plotshape(osc_sign ? short_3 : na, "OSC Short", ss, ls, cs, text="OSC\nShort", textcolor=cs, size=sz)
//}
// ╔═══════════════════════════════════════════════════════════════════════════╗
// ║                           SECTION 2 : SCREENER                            ║
// ╚═══════════════════════════════════════════════════════════════════════════╝
//{
// The "SCREENER" section has been prepared in a way that can adapt to the variables defined above.
// Delete the Section 1 and code your own conditions and titles : 
// (long_1, short_1, long_2, short_2, long_3, short_3, text_only) & (title_1, title_2, title_3, title_4)

// ╠═════════════════════════════════ Inputs ══════════════════════════════════╣

string gr_sc = "╠═════════════ SCREENER ═════════════╣"
tb_sh = input.bool(title="Show Table", defval=true, group=gr_sc)
sh_pr = input.bool(title="Show Prefix", defval=false, group=gr_sc)
tb_ps = input.string(title="Position   ", options=["Left", "Right", "Center"], defval="Right", group=gr_sc, inline="p")
tb_sz = input.string(title="Text Size ", options=["Auto", "Small", "Normal", "Large"], defval="Normal", group=gr_sc, inline="s")
col_s = input.color(title="Colours   ", defval=#00a5ba, group=gr_sc, inline="c")    // Symbol
col_u = input.color(title="", defval=#00bb00, group=gr_sc, inline="c")              // Up (Long)
col_d = input.color(title="", defval=#bb0000, group=gr_sc, inline="c")              // Down (Short)
col_n = input.color(title="", defval=#686868, group=gr_sc, inline="c")              // Neutral

string gr_sy = "╠═════════════ SYMBOLS ══════════════╣"
s01 = input.symbol(title="Symbol 01", inline="01", group=gr_sy, defval="BINANCE:BTCUSDT")
s02 = input.symbol(title="Symbol 02", inline='02', group=gr_sy, defval='BINANCE:ETHUSDT')
s03 = input.symbol(title="Symbol 03", inline="03", group=gr_sy, defval="BINANCE:BNBUSDT")
s04 = input.symbol(title="Symbol 04", inline="04", group=gr_sy, defval="BINANCE:ADAUSDT")
s05 = input.symbol(title="Symbol 05", inline="05", group=gr_sy, defval="BINANCE:AVAXUSDT")
s06 = input.symbol(title="Symbol 06", inline="06", group=gr_sy, defval="BINANCE:CHZUSDT")
s07 = input.symbol(title="Symbol 07", inline="07", group=gr_sy, defval="BINANCE:DOGEUSDT")
s08 = input.symbol(title="Symbol 08", inline="08", group=gr_sy, defval="BINANCE:SOLUSDT")
s09 = input.symbol(title="Symbol 09", inline="09", group=gr_sy, defval="BINANCE:TRXUSDT")
s10 = input.symbol(title="Symbol 10", inline="10", group=gr_sy, defval="BINANCE:XRPUSDT")
s11 = input.symbol(title="Symbol 11", inline='11', group=gr_sy, defval='NASDAQ:AAPL')
s12 = input.symbol(title="Symbol 12", inline='12', group=gr_sy, defval='NASDAQ:TSLA')
s13 = input.symbol(title="Symbol 13", inline='13', group=gr_sy, defval='NASDAQ:AMZN')
s14 = input.symbol(title="Symbol 14", inline='14', group=gr_sy, defval='NASDAQ:GOOGL')
s15 = input.symbol(title="Symbol 15", inline='15', group=gr_sy, defval='NASDAQ:NVDA')

// You can obtain various time frame results by defining inputs equal to the number of symbols to be used in the security function.
string x00 = timeframe.period  

// ╠════════════════════════════════ Functions ════════════════════════════════╣

f_data(series bool x, series bool y) =>
    r1 = 0, r1 := x ? 1 : y ? -1 : r1[1]                // direction
    r2 = ta.barssince(r1 != nz(r1[1]))                  // barssince
    r3 = r1 == 1 ? col_u : r1 == -1 ? col_d : col_n     // color
    [r1, r2, r3]
//

f_screener() =>
    [x1, y1, z1] = f_data(long_1, short_1)
    [x2, y2, z2] = f_data(long_2, short_2)
    [x3, y3, z3] = f_data(long_3, short_3)
    t = text_only
    [x1, x2, x3, y1, y2, y3, z1, z2, z3, t]
//

// Yön, Bar
f_text(int x, int y) =>
    r1 = "     "
    r2 = str.tostring(y)
    r3 = x == 1 ? r1 + "▲ [" + r2 + "]" : x == -1 ? r1 + "▼ [" + r2 + "]" : r1 + "■ [" + r2 + "]" 
//

f_prefix(simple string x) =>
    r = sh_pr ? x : str.substring(x, str.pos(x, ':') + 1)
//

f_size(simple string x) =>
      x == "Small"  ? size.small  : 
      x == "Normal" ? size.normal : 
      x == "Large"  ? size.large  : size.auto
//

f_position(simple string x) =>
      x == "Left"   ? position.top_left   : 
      x == "Right"  ? position.top_right  : position.top_center
//

// ╠════════════════════════════════ Variables ════════════════════════════════╣

[a01, b01, c01, d01, e01, f01, g01, h01, i01, j01] = request.security(s01, x00, f_screener())
[a02, b02, c02, d02, e02, f02, g02, h02, i02, j02] = request.security(s02, x00, f_screener())
[a03, b03, c03, d03, e03, f03, g03, h03, i03, j03] = request.security(s03, x00, f_screener())
[a04, b04, c04, d04, e04, f04, g04, h04, i04, j04] = request.security(s04, x00, f_screener())
[a05, b05, c05, d05, e05, f05, g05, h05, i05, j05] = request.security(s05, x00, f_screener())
[a06, b06, c06, d06, e06, f06, g06, h06, i06, j06] = request.security(s06, x00, f_screener())
[a07, b07, c07, d07, e07, f07, g07, h07, i07, j07] = request.security(s07, x00, f_screener())
[a08, b08, c08, d08, e08, f08, g08, h08, i08, j08] = request.security(s08, x00, f_screener())
[a09, b09, c09, d09, e09, f09, g09, h09, i09, j09] = request.security(s09, x00, f_screener())
[a10, b10, c10, d10, e10, f10, g10, h10, i10, j10] = request.security(s10, x00, f_screener())
[a11, b11, c11, d11, e11, f11, g11, h11, i11, j11] = request.security(s11, x00, f_screener())
[a12, b12, c12, d12, e12, f12, g12, h12, i12, j12] = request.security(s12, x00, f_screener())
[a13, b13, c13, d13, e13, f13, g13, h13, i13, j13] = request.security(s13, x00, f_screener())
[a14, b14, c14, d14, e14, f14, g14, h14, i14, j14] = request.security(s14, x00, f_screener())
[a15, b15, c15, d15, e15, f15, g15, h15, i15, j15] = request.security(s15, x00, f_screener())

// ╠═════════════════════════════════ Return ══════════════════════════════════╣

i1_t01 = f_text(a01, d01), i2_t01 = f_text(b01, e01), i3_t01 = f_text(c01, f01), i4_t01 = str.tostring(j01, "#.##")  
i1_t02 = f_text(a02, d02), i2_t02 = f_text(b02, e02), i3_t02 = f_text(c02, f02), i4_t02 = str.tostring(j02, "#.##")  
i1_t03 = f_text(a03, d03), i2_t03 = f_text(b03, e03), i3_t03 = f_text(c03, f03), i4_t03 = str.tostring(j03, "#.##")  
i1_t04 = f_text(a04, d04), i2_t04 = f_text(b04, e04), i3_t04 = f_text(c04, f04), i4_t04 = str.tostring(j04, "#.##")  
i1_t05 = f_text(a05, d05), i2_t05 = f_text(b05, e05), i3_t05 = f_text(c05, f05), i4_t05 = str.tostring(j05, "#.##")  
i1_t06 = f_text(a06, d06), i2_t06 = f_text(b06, e06), i3_t06 = f_text(c06, f06), i4_t06 = str.tostring(j06, "#.##")  
i1_t07 = f_text(a07, d07), i2_t07 = f_text(b07, e07), i3_t07 = f_text(c07, f07), i4_t07 = str.tostring(j07, "#.##")  
i1_t08 = f_text(a08, d08), i2_t08 = f_text(b08, e08), i3_t08 = f_text(c08, f08), i4_t08 = str.tostring(j08, "#.##")  
i1_t09 = f_text(a09, d09), i2_t09 = f_text(b09, e09), i3_t09 = f_text(c09, f09), i4_t09 = str.tostring(j09, "#.##")  
i1_t10 = f_text(a10, d10), i2_t10 = f_text(b10, e10), i3_t10 = f_text(c10, f10), i4_t10 = str.tostring(j10, "#.##")  
i1_t11 = f_text(a11, d11), i2_t11 = f_text(b11, e11), i3_t11 = f_text(c11, f11), i4_t11 = str.tostring(j11, "#.##")  
i1_t12 = f_text(a12, d12), i2_t12 = f_text(b12, e12), i3_t12 = f_text(c12, f12), i4_t12 = str.tostring(j12, "#.##")  
i1_t13 = f_text(a13, d13), i2_t13 = f_text(b13, e13), i3_t13 = f_text(c13, f13), i4_t13 = str.tostring(j13, "#.##")  
i1_t14 = f_text(a14, d14), i2_t14 = f_text(b14, e14), i3_t14 = f_text(c14, f14), i4_t14 = str.tostring(j14, "#.##")  
i1_t15 = f_text(a15, d15), i2_t15 = f_text(b15, e15), i3_t15 = f_text(c15, f15), i4_t15 = str.tostring(j15, "#.##")  

// ╠═══════════════════════════════ Info Panel ════════════════════════════════╣

string sp = "     "
var table tb = table.new(position=f_position(tb_ps), columns=6, rows=20)
f_print(x, y, z, p, q) =>
    table.cell(tb, x, y+1, q, text_color=z, text_halign=p == "" ? text.align_left : text.align_center, text_size=f_size(tb_sz))
if barstate.islast and tb_sh

    f_print(0, -1, col_s, "", ""), f_print(0, 0, col_s, "", "")    
    f_print(1, -1, col_s, "", ""), f_print(1, 0, col_s, "c", sp + title_1)
    f_print(2, -1, col_s, "", ""), f_print(2, 0, col_s, "c", sp + title_2)
    f_print(3, -1, col_s, "", ""), f_print(3, 0, col_s, "c", sp + title_3)
    f_print(4, -1, col_s, "", ""), f_print(4, 0, col_s, "c", sp + title_4)

    f_print(0, 1,  col_s, "", f_prefix(s01)), f_print(1, 1,  g01, "", i1_t01)
    f_print(0, 2,  col_s, "", f_prefix(s02)), f_print(1, 2,  g02, "", i1_t02)
    f_print(0, 3,  col_s, "", f_prefix(s03)), f_print(1, 3,  g03, "", i1_t03)
    f_print(0, 4,  col_s, "", f_prefix(s04)), f_print(1, 4,  g04, "", i1_t04)
    f_print(0, 5,  col_s, "", f_prefix(s05)), f_print(1, 5,  g05, "", i1_t05)
    f_print(0, 6,  col_s, "", f_prefix(s06)), f_print(1, 6,  g06, "", i1_t06)
    f_print(0, 7,  col_s, "", f_prefix(s07)), f_print(1, 7,  g07, "", i1_t07)
    f_print(0, 8,  col_s, "", f_prefix(s08)), f_print(1, 8,  g08, "", i1_t08)
    f_print(0, 9,  col_s, "", f_prefix(s09)), f_print(1, 9,  g09, "", i1_t09)
    f_print(0, 10, col_s, "", f_prefix(s10)), f_print(1, 10, g10, "", i1_t10)
    f_print(0, 11, col_s, "", f_prefix(s11)), f_print(1, 11, g11, "", i1_t11)
    f_print(0, 12, col_s, "", f_prefix(s12)), f_print(1, 12, g12, "", i1_t12)
    f_print(0, 13, col_s, "", f_prefix(s13)), f_print(1, 13, g13, "", i1_t13)
    f_print(0, 14, col_s, "", f_prefix(s14)), f_print(1, 14, g14, "", i1_t14)
    f_print(0, 15, col_s, "", f_prefix(s15)), f_print(1, 15, g15, "", i1_t15)

    f_print(2, 1,  h01, "", i2_t01), f_print(3, 1,  i01, "", i3_t01), f_print(4, 1,  col_n, "", sp + i4_t01)
    f_print(2, 2,  h02, "", i2_t02), f_print(3, 2,  i02, "", i3_t02), f_print(4, 2,  col_n, "", sp + i4_t02)
    f_print(2, 3,  h03, "", i2_t03), f_print(3, 3,  i03, "", i3_t03), f_print(4, 3,  col_n, "", sp + i4_t03)
    f_print(2, 4,  h04, "", i2_t04), f_print(3, 4,  i04, "", i3_t04), f_print(4, 4,  col_n, "", sp + i4_t04)
    f_print(2, 5,  h05, "", i2_t05), f_print(3, 5,  i05, "", i3_t05), f_print(4, 5,  col_n, "", sp + i4_t05)
    f_print(2, 6,  h06, "", i2_t06), f_print(3, 6,  i06, "", i3_t06), f_print(4, 6,  col_n, "", sp + i4_t06)
    f_print(2, 7,  h07, "", i2_t07), f_print(3, 7,  i07, "", i3_t07), f_print(4, 7,  col_n, "", sp + i4_t07)
    f_print(2, 8,  h08, "", i2_t08), f_print(3, 8,  i08, "", i3_t08), f_print(4, 8,  col_n, "", sp + i4_t08)
    f_print(2, 9,  h09, "", i2_t09), f_print(3, 9,  i09, "", i3_t09), f_print(4, 9,  col_n, "", sp + i4_t09)
    f_print(2, 10, h10, "", i2_t10), f_print(3, 10, i10, "", i3_t10), f_print(4, 10, col_n, "", sp + i4_t10)
    f_print(2, 11, h11, "", i2_t11), f_print(3, 11, i11, "", i3_t11), f_print(4, 11, col_n, "", sp + i4_t11)
    f_print(2, 12, h12, "", i2_t12), f_print(3, 12, i12, "", i3_t12), f_print(4, 12, col_n, "", sp + i4_t12)
    f_print(2, 13, h13, "", i2_t13), f_print(3, 13, i13, "", i3_t13), f_print(4, 13, col_n, "", sp + i4_t13)
    f_print(2, 14, h14, "", i2_t14), f_print(3, 14, i14, "", i3_t14), f_print(4, 14, col_n, "", sp + i4_t14)
    f_print(2, 15, h15, "", i2_t15), f_print(3, 15, i15, "", i3_t15), f_print(4, 15, col_n, "", sp + i4_t15)
//}
// ╠══════════════════════════════════ Bitti ══════════════════════════════════╣

plotshape(barstate.isfirst, "@ dg_factor", color=#13172200, editable=false)