MTF 24-hour Volume [Anan]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Mohamed3nan
/////////////////////////////////////////////////
//        /\                                   //
//       /  \     _ __     __ _   _ __         //
//      / /\ \   | '_ \   / _` | | '_ \        //
//     / ____ \  | | | | | (_| | | | | |       //
//    /_/    \_\ |_| |_|  \__,_| |_| |_|       //
/////////////////////////////////////////////////

//@version=5
indicator("MTF 24-hour Volume [Anan]", "MTF 24H Vol [Anan]", format=format.volume)

// built-in indicator: 24-hour Volume 
ma(source, length, type) =>
    switch type
        "SMA" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        "SMMA (RMA)" => ta.rma(source, length)
        "WMA" => ta.wma(source, length)
        "VWMA" => ta.vwma(source, length)


priceTooltip = "If the symbol's volume is expressed in base units, it is multiplied by this value to convert it into a price."
price = input.source(close, "Price Source", tooltip = priceTooltip)
currencyInput = input.string(title = "Target Currency", defval="Default", options=["Default", "USD", "EUR", "CAD", "JPY", "GBP", "HKD", "CNY", "NZD", "RUB"])
currency = currencyInput == "Default" ? "" : currencyInput

volTypeInput = input.string("SMA", title="MA Type", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group="MA Settings")
volLengthInput = input.int(14, title="MA Length", group="MA Settings")


msIn24h = 24 * 60 * 60 * 1000

maxBufferSize = switch
    timeframe.isminutes or timeframe.isseconds => 24 * 60
    timeframe.isdaily => 24 * 60 / 5
    => 24
    
cumVolTF = switch
    timeframe.isminutes or timeframe.isseconds => "1"
    timeframe.isdaily => "5"
    => "60"

cum24hVol(s) =>
    src = s
    
    if bar_index == 0
        // Creating a buffer of 'maxBufferSize+1' for 'src' and 'time' to avoid the 'max_bars_back' error
        src := src[maxBufferSize+1] * time[maxBufferSize+1] * 0
        
    var cumSum = 0.
    var int firstBarTimeIndex = na
    
    if na(firstBarTimeIndex) // 24H have not elapsed yet
        sum = 0.
        for i = 0 to maxBufferSize
            if (time - time[i]) >= msIn24h
                firstBarTimeIndex := bar_index - i + 1
                break
            sum += src[i]
        cumSum := sum
    else
        cumSum += nz(src)
        for i = firstBarTimeIndex to bar_index
            if (time - time[bar_index - i]) < msIn24h
                firstBarTimeIndex := i
                break
            cumSum -= nz(src[bar_index - i])
    cumSum

if syminfo.volumetype == "tick" and syminfo.type == "crypto"
    runtime.error("Can't calculate volume. There is no delivery of physical goods or securities with CFDs.")
expr = syminfo.volumetype == "quote" ? volume : price * volume
vol24h = request.security(syminfo.tickerid, cumVolTF, cum24hVol(expr), currency = currency)
volMA = ma(vol24h, volLengthInput, volTypeInput)

plot(vol24h, title = "24H Volume",color = price>price[1]?color.new(color.teal,50):color.new(color.red,50),  style = plot.style_histogram)
plot(volMA, "Volume MA", color=color.gray)

// built-in indicator: 24-hour Volume 

// Anan MTF

group_candle = 'Time Frames'
check_1 = input.bool(true, '', inline='ln1', group=group_candle)
mtf_1 = input.timeframe(title='', defval='', inline='ln1', group=group_candle)
check_2 = input.bool(true, '', inline='ln1', group=group_candle)
mtf_2 = input.timeframe(title='', defval='60', inline='ln1', group=group_candle)
check_3 = input.bool(true, '', inline='ln2', group=group_candle)
mtf_3 = input.timeframe(title='', defval='240', inline='ln2', group=group_candle)
check_4 = input.bool(true, '', inline='ln2', group=group_candle)
mtf_4 = input.timeframe(title='', defval='1D', inline='ln2', group=group_candle)

group_stat = 'Options'
show_1 = input.bool(true, 'Volume Change by currency', inline='#1', group=group_stat)
show_2 = input.bool(true, 'Volume Change %', inline='#2', group=group_stat)
show_3 = input.bool(true, 'Volume MA Change %', inline='#3', group=group_stat)

group_pos = 'Table Position & Size & Colors'
string i_tableYpos = input.string('top', '↕', inline='01', group=group_pos, options=['top', 'middle', 'bottom'])
string i_tableXpos = input.string('right', '↔', inline='01', group=group_pos, options=['left', 'center', 'right'], tooltip='Position on the chart.')
int i_tableRowHeight = input.int(0, '|', inline='02', group=group_pos, minval=0, maxval=100)
int i_tableColWidth = input.int(0, '—', inline='02', group=group_pos, minval=0, maxval=100, tooltip='0-100. Use 0 to auto-size height and width.')
string i_textSize = input.string('Small', 'Table Text Size', options=['Auto', 'Tiny', 'Small', 'Normal', 'Large', 'Huge'], group=group_pos)
string textSize = i_textSize == 'Auto' ? size.auto : i_textSize == 'Tiny' ? size.tiny : i_textSize == 'Small' ? size.small : i_textSize == 'Normal' ? size.normal : i_textSize == 'Large' ? size.large : size.huge
row_col = input.color(color.blue, 'Headers', inline='03', group=group_pos)
col_col = input.color(color.blue, ' ', inline='03', group=group_pos)
poscol = input.color(color.green, 'Bull Color', inline='04', group=group_pos)
neutralcolor = input.color(color.gray, 'Neutral Color', inline='04', group=group_pos)
negcol = input.color(color.red, 'Bear Color', inline='04', group=group_pos)
////////////////////////////////////////////////////////////

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.

res_to_str(res) =>
    str = res
    if strToNumInt(str) < 60
        str += 'm'
        str
    else if strToNumInt(str) >= 60 and strToNumInt(str) <= 1440
        str := str.tostring(strToNumInt(str) / 60) + 'h'
        str
    else if str == ''
        if strToNumInt(timeframe.period) < 60
            str := 'Chart:' + timeframe.period + 'm'
            str
        else if strToNumInt(timeframe.period) >= 60 and strToNumInt(timeframe.period) <= 1440
            str := 'Chart:' + str.tostring(strToNumInt(timeframe.period) / 60) + 'h'
            str
        else
            str := 'Chart:' + timeframe.period
            str
    else
        str
    str

///////////////// 

chg(src) =>
    change = ta.change(src)
    change

chg_perc(src) =>
    change_percentage = ta.roc(src, 1)
    change_percentage

calcRatingStatus(value) =>
    str.tostring(value, '#.##') + '%'

calcRatingStatusVol(value) =>
    str.tostring(value, format.volume)
    
poscond(value) =>
    poscondition = value > 0
    poscondition

negcond(value) =>
    negcondition = value < 0
    negcondition

//////////////////////////////////////////////////////////////////////////
f_addCell(_table, _column, _row, _cellTitle, _textColor, _bgColor) =>
    table.cell(_table, _column, _row, _cellTitle, text_color=_textColor, bgcolor=_bgColor, text_size=textSize, width=i_tableColWidth, height=i_tableRowHeight)

var table anan = table.new(i_tableYpos + '_' + i_tableXpos, 5, 4, border_width=3)
if barstate.islast and check_1
    f_addCell(anan, 1, 0, res_to_str(mtf_1), col_col, color.new(col_col, 80))
if barstate.islast and check_2
    f_addCell(anan, 2, 0, res_to_str(mtf_2), col_col, color.new(col_col, 80))
if barstate.islast and check_3
    f_addCell(anan, 3, 0, res_to_str(mtf_3), col_col, color.new(col_col, 80))
if barstate.islast and check_4
    f_addCell(anan, 4, 0, res_to_str(mtf_4), col_col, color.new(col_col, 80))

indicator_1_1  = request.security(syminfo.tickerid, mtf_1, chg(vol24h))
indicator_1_2  = request.security(syminfo.tickerid, mtf_2, chg(vol24h))
indicator_1_3  = request.security(syminfo.tickerid, mtf_3, chg(vol24h))
indicator_1_4  = request.security(syminfo.tickerid, mtf_4, chg(vol24h))

if barstate.islast and show_1
    f_addCell(anan, 0, 1, 'Vol. Chg '+ "("+syminfo.currency+")", row_col, color.new(row_col, 80))
    if show_1 and check_1
        f_addCell(anan, 1, 1, calcRatingStatusVol(indicator_1_1), poscond(indicator_1_1) ? poscol : negcond(indicator_1_1) ? negcol : color.gray, color.new(poscond(indicator_1_1) ? poscol : negcond(indicator_1_1) ? negcol : color.gray, 80))
    if show_1 and check_2
        f_addCell(anan, 2, 1, calcRatingStatusVol(indicator_1_2), poscond(indicator_1_2) ? poscol : negcond(indicator_1_2) ? negcol : color.gray, color.new(poscond(indicator_1_2) ? poscol : negcond(indicator_1_2) ? negcol : color.gray, 80))
    if show_1 and check_3
        f_addCell(anan, 3, 1, calcRatingStatusVol(indicator_1_3), poscond(indicator_1_3) ? poscol : negcond(indicator_1_3) ? negcol : color.gray, color.new(poscond(indicator_1_3) ? poscol : negcond(indicator_1_3) ? negcol : color.gray, 80))
    if show_1 and check_4
        f_addCell(anan, 4, 1, calcRatingStatusVol(indicator_1_4), poscond(indicator_1_4) ? poscol : negcond(indicator_1_4) ? negcol : color.gray, color.new(poscond(indicator_1_4) ? poscol : negcond(indicator_1_4) ? negcol : color.gray, 80))

indicator_2_1  = request.security(syminfo.tickerid, mtf_1, chg_perc(vol24h))
indicator_2_2  = request.security(syminfo.tickerid, mtf_2, chg_perc(vol24h))
indicator_2_3  = request.security(syminfo.tickerid, mtf_3, chg_perc(vol24h))
indicator_2_4  = request.security(syminfo.tickerid, mtf_4, chg_perc(vol24h))

if barstate.islast and show_2
    f_addCell(anan, 0, 2, 'Vol. Chg (%)', row_col, color.new(row_col, 80))
    if show_2 and check_1
        f_addCell(anan, 1, 2, calcRatingStatus(indicator_2_1), poscond(indicator_2_1) ? poscol : negcond(indicator_2_1) ? negcol : color.gray, color.new(poscond(indicator_2_1) ? poscol : negcond(indicator_2_1) ? negcol : color.gray, 80))
    if show_2 and check_2
        f_addCell(anan, 2, 2, calcRatingStatus(indicator_2_2), poscond(indicator_2_2) ? poscol : negcond(indicator_2_2) ? negcol : color.gray, color.new(poscond(indicator_2_2) ? poscol : negcond(indicator_2_2) ? negcol : color.gray, 80))
    if show_2 and check_3
        f_addCell(anan, 3, 2, calcRatingStatus(indicator_2_3), poscond(indicator_2_3) ? poscol : negcond(indicator_2_3) ? negcol : color.gray, color.new(poscond(indicator_2_3) ? poscol : negcond(indicator_2_3) ? negcol : color.gray, 80))
    if show_2 and check_4
        f_addCell(anan, 4, 2, calcRatingStatus(indicator_2_4), poscond(indicator_2_4) ? poscol : negcond(indicator_2_4) ? negcol : color.gray, color.new(poscond(indicator_2_4) ? poscol : negcond(indicator_2_4) ? negcol : color.gray, 80))

indicator_3_1  = request.security(syminfo.tickerid, mtf_1, chg_perc(ma(vol24h, volLengthInput, volTypeInput)))
indicator_3_2  = request.security(syminfo.tickerid, mtf_2, chg_perc(ma(vol24h, volLengthInput, volTypeInput)))
indicator_3_3  = request.security(syminfo.tickerid, mtf_3, chg_perc(ma(vol24h, volLengthInput, volTypeInput)))
indicator_3_4  = request.security(syminfo.tickerid, mtf_4, chg_perc(ma(vol24h, volLengthInput, volTypeInput)))

if barstate.islast and show_3
    f_addCell(anan, 0, 3, "Vol."+ volTypeInput + "(" + str.tostring(volLengthInput)+ ")Chg (%)", row_col, color.new(row_col, 80))
    if show_3 and check_1
        f_addCell(anan, 1, 3, calcRatingStatus(indicator_3_1), poscond(indicator_3_1) ? poscol : negcond(indicator_3_1) ? negcol : color.gray, color.new(poscond(indicator_3_1) ? poscol : negcond(indicator_3_1) ? negcol : color.gray, 80))
    if show_3 and check_2
        f_addCell(anan, 2, 3, calcRatingStatus(indicator_3_2), poscond(indicator_3_2) ? poscol : negcond(indicator_3_2) ? negcol : color.gray, color.new(poscond(indicator_3_2) ? poscol : negcond(indicator_3_2) ? negcol : color.gray, 80))
    if show_3 and check_3
        f_addCell(anan, 3, 3, calcRatingStatus(indicator_3_3), poscond(indicator_3_3) ? poscol : negcond(indicator_3_3) ? negcol : color.gray, color.new(poscond(indicator_3_3) ? poscol : negcond(indicator_3_3) ? negcol : color.gray, 80))
    if show_3 and check_4
        f_addCell(anan, 4, 3, calcRatingStatus(indicator_3_4), poscond(indicator_3_4) ? poscol : negcond(indicator_3_4) ? negcol : color.gray, color.new(poscond(indicator_3_4) ? poscol : negcond(indicator_3_4) ? negcol : color.gray, 80))
