High-Low Index
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © LonesomeTheBlue

//@version=5
indicator("High Low Index", explicit_plot_zorder = true)
timeFrame = input.timeframe(defval = 'D', title = "Time Frame", group = "Setup")
length = input.int(defval = 22, title = "Length", minval = 1, group = "Setup")
source = input.string(defval = "High/Low", title = "Source", options = ["High/Low", "Close"], group = "Setup")
smoothLength = input.int(defval = 10, title = "Smoothing Length", minval = 1, group = "Setup")
showRecordHighPercent = input.bool(defval = true, title = "Record High Percent", group = "Setup")
showTable= input.bool(defval = true, title = "Show Table", inline = "table", group = "Setup")
textsize = input.string(defval = size.small, title = " |  Text Size", options = [size.tiny, size.small, size.normal], inline = "table", group = "Setup")
ShowExchange = input.bool(defval = false, title = "Show Exchange Info in the Table", group = "Setup")
showEma = input.bool(defval = true, title = "EMA", inline = "ema", group = "Setup")
emaLength = input.int(defval = 10, title = " |  Length", minval = 1, inline = "ema", group = "Setup")
symbol1 = input.string(defval = "BINANCE:BTCUSDT", group = "Symbols")
symbol2 = input.string(defval = "BINANCE:XRPUSDT", group = "Symbols")
symbol3 = input.string(defval = "BINANCE:BCHUSDT", group = "Symbols")
symbol4 = input.string(defval = "BINANCE:LTCUSDT", group = "Symbols")
symbol5 = input.string(defval = "BINANCE:BNBUSDT", group = "Symbols")
symbol6 = input.string(defval = "BINANCE:EOSUSDT", group = "Symbols")
symbol7 = input.string(defval = "BINANCE:XTZUSDT", group = "Symbols")
symbol8 = input.string(defval = "BINANCE:ETHUSDT", group = "Symbols")
symbol9 = input.string(defval = "BINANCE:XMRUSDT", group = "Symbols")
symbol10 = input.string(defval = "BINANCE:XLMUSDT", group = "Symbols")
symbol11 = input.string(defval = "BINANCE:ADAUSDT", group = "Symbols")
symbol12 = input.string(defval = "BINANCE:TRXUSDT", group = "Symbols")
symbol13 = input.string(defval = "BINANCE:DASHUSDT", group = "Symbols")
symbol14 = input.string(defval = "BINANCE:ETCUSDT", group = "Symbols")
symbol15 = input.string(defval = "BINANCE:OMGUSDT", group = "Symbols")
symbol16 = input.string(defval = "BINANCE:NEOUSDT", group = "Symbols")
symbol17 = input.string(defval = "BINANCE:ATOMUSD", group = "Symbols")
symbol18 = input.string(defval = "BINANCE:IOTAUSDT", group = "Symbols")
symbol19 = input.string(defval = "BINANCE:ALGOUSDT", group = "Symbols")
symbol20 = input.string(defval = "BINANCE:ONTUSDT", group = "Symbols")
symbol21 = input.string(defval = "BINANCE:FTTUSDT", group = "Symbols")
symbol22 = input.string(defval = "BINANCE:DOGEUSDT", group = "Symbols")
symbol23 = input.string(defval = "BINANCE:BATUSDT", group = "Symbols")
symbol24 = input.string(defval = "BINANCE:ZECUSDT", group = "Symbols")
symbol25 = input.string(defval = "BINANCE:VETUSDT", group = "Symbols")
symbol26 = input.string(defval = "BINANCE:SCUSDT", group = "Symbols")
symbol27 = input.string(defval = "BINANCE:ZILUSDT", group = "Symbols")
symbol28 = input.string(defval = "BINANCE:QTUMUSDT", group = "Symbols")
symbol29 = input.string(defval = "BINANCE:THETAUSDT", group = "Symbols")
symbol30 = input.string(defval = "BINANCE:LSKUSDT", group = "Symbols")
symbol31 = input.string(defval = "BINANCE:HOTUSDT", group = "Symbols")
symbol32 = input.string(defval = "BINANCE:REPUSDT", group = "Symbols")
symbol33 = input.string(defval = "BINANCE:WAVESUSDT", group = "Symbols")
symbol34 = input.string(defval = "BINANCE:BTSUSDT", group = "Symbols")
symbol35 = input.string(defval = "BINANCE:HBARUSDT", group = "Symbols")
symbol36 = input.string(defval = "BINANCE:ICXUSDT", group = "Symbols")
symbol37 = input.string(defval = "BINANCE:RVNUSDT", group = "Symbols")
symbol38 = input.string(defval = "BINANCE:NANOUSDT", group = "Symbols")
symbol39 = input.string(defval = "BINANCE:SOLUSDT", group = "Symbols")
symbol40 = input.string(defval = "BINANCE:BTCUSDTPERP", group = "Symbols")

HighsLows = array.new_int(40, 0)
getHighLow(length)=>
    highest_ = ta.highest(length)[1]
    lowest_ = ta.lowest(length)[1]
    int ret = 0
    if na(highest_)
        ret := 2
    else
        bool h_ = ((source == "High/Low" ? high : close) > highest_)
        bool l_ = ((source == "High/Low" ? low : close)  < lowest_)
        ret := h_ ? 1 : l_ ? -1 : 0
    ret
    
getHLindexForTheSymbol(symbol, timeFrame, length, index)=>
    highlow = request.security(symbol, timeFrame, getHighLow(length), ignore_invalid_symbol = true)
    array.set(HighsLows, index, na(highlow) ? 2 : highlow)
    
getHLindexForTheSymbol(symbol1, timeFrame, length, 0)
getHLindexForTheSymbol(symbol2, timeFrame, length, 1)
getHLindexForTheSymbol(symbol3, timeFrame, length, 2)
getHLindexForTheSymbol(symbol4, timeFrame, length, 3)
getHLindexForTheSymbol(symbol5, timeFrame, length, 4)
getHLindexForTheSymbol(symbol6, timeFrame, length, 5)
getHLindexForTheSymbol(symbol7, timeFrame, length, 6)
getHLindexForTheSymbol(symbol8, timeFrame, length, 7)
getHLindexForTheSymbol(symbol9, timeFrame, length, 8)
getHLindexForTheSymbol(symbol10, timeFrame, length, 9)

getHLindexForTheSymbol(symbol11, timeFrame, length, 10)
getHLindexForTheSymbol(symbol12, timeFrame, length, 11)
getHLindexForTheSymbol(symbol13, timeFrame, length, 12)
getHLindexForTheSymbol(symbol14, timeFrame, length, 13)
getHLindexForTheSymbol(symbol15, timeFrame, length, 14)
getHLindexForTheSymbol(symbol16, timeFrame, length, 15)
getHLindexForTheSymbol(symbol17, timeFrame, length, 16)
getHLindexForTheSymbol(symbol18, timeFrame, length, 17)
getHLindexForTheSymbol(symbol19, timeFrame, length, 18)
getHLindexForTheSymbol(symbol20, timeFrame, length, 19)

getHLindexForTheSymbol(symbol21, timeFrame, length, 20)
getHLindexForTheSymbol(symbol22, timeFrame, length, 21)
getHLindexForTheSymbol(symbol23, timeFrame, length, 22)
getHLindexForTheSymbol(symbol24, timeFrame, length, 23)
getHLindexForTheSymbol(symbol25, timeFrame, length, 24)
getHLindexForTheSymbol(symbol26, timeFrame, length, 25)
getHLindexForTheSymbol(symbol27, timeFrame, length, 26)
getHLindexForTheSymbol(symbol28, timeFrame, length, 27)
getHLindexForTheSymbol(symbol29, timeFrame, length, 28)
getHLindexForTheSymbol(symbol30, timeFrame, length, 29)

getHLindexForTheSymbol(symbol31, timeFrame, length, 30)
getHLindexForTheSymbol(symbol32, timeFrame, length, 31)
getHLindexForTheSymbol(symbol33, timeFrame, length, 32)
getHLindexForTheSymbol(symbol34, timeFrame, length, 33)
getHLindexForTheSymbol(symbol35, timeFrame, length, 34)
getHLindexForTheSymbol(symbol36, timeFrame, length, 35)
getHLindexForTheSymbol(symbol37, timeFrame, length, 36)
getHLindexForTheSymbol(symbol38, timeFrame, length, 37)
getHLindexForTheSymbol(symbol39, timeFrame, length, 38)
getHLindexForTheSymbol(symbol40, timeFrame, length, 39)

highs = 0
total = 0
for x = 0 to 39
    highs += (array.get(HighsLows, x) == 1 ? 1 : 0)
    total += (array.get(HighsLows, x) == 1 or array.get(HighsLows, x) == -1 ? 1 : 0)

// calculate & show Record High Percent / High Low Index / EMA
var float RecordHighPercent = 50
RecordHighPercent := total == 0 ? RecordHighPercent : 100 * highs / total
HighLowIndex = ta.sma(RecordHighPercent, smoothLength)
hline0 = hline(0, linestyle = hline.style_dotted)
hline50 = hline(50, linestyle = hline.style_dotted)
hline100 = hline(100, linestyle = hline.style_dotted)
fill(hline0, hline50, color = color.rgb(255, 0, 0, 75))
fill(hline50, hline100, color = color.rgb(0, 255, 0, 75))
plot(showRecordHighPercent ? RecordHighPercent : na, color = showRecordHighPercent ? #9598a1 : na)
plot(showEma ? ta.ema(HighLowIndex, emaLength) : na, color = showEma ? color.red : na)
plot(HighLowIndex, color = color.blue, linewidth = 2)

removeexchange(string [] symbols)=>
    for x = 0 to array.size(symbols) - 1
        array.set(symbols, x, array.get(str.split(array.get(symbols, x), ':'), 1))

// Keep symbol names in an array
var symbols = array.from(
 symbol1, symbol2, symbol3, symbol4, symbol5, symbol6, symbol7, symbol8, symbol9, symbol10, 
 symbol11, symbol12, symbol13, symbol14, symbol15, symbol16, symbol17, symbol18, symbol19, symbol20, 
 symbol21, symbol22, symbol23, symbol24, symbol25, symbol26, symbol27, symbol28, symbol29, symbol30, 
 symbol31, symbol32, symbol33, symbol34, symbol35, symbol36, symbol37, symbol38, symbol39, symbol40)

// remove Exchange from the symbols
if barstate.isfirst and not ShowExchange 
    removeexchange(symbols)   

// show the table
if barstate.islast and showTable
    
    var Table = table.new(position=position.bottom_left, columns=5, rows=8, frame_color=color.gray, frame_width=1, border_width=1, border_color=color.black)
    index = 0
    for c = 0 to 4
        for r = 0 to 7
            bcolor = array.get(HighsLows, index) == 1 ? color.lime : array.get(HighsLows, index) == -1 ? color.red : array.get(HighsLows, index) == 2 ? color.black : color.gray
            tcolor = array.get(HighsLows, index) == 1 ? color.black : array.get(HighsLows, index) == -1 ? color.white : array.get(HighsLows, index) == 2 ? color.gray : color.black
            table.cell(table_id=Table, column=c, row=r, text=array.get(symbols, index), bgcolor=bcolor, text_color = tcolor, text_size=textsize)
            index += 1
