CH-I: Trend - Higher Timeframe Body
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Coffeehouse-Analytics

//@version=5
indicator("CH-I: Trend - Higher Timeframe Bars", "CH-I High TF Bars", overlay=true, max_lines_count = 500, max_boxes_count=500)

AUTO_TIMEFRAME_TOOLTIP = "When the Auto option is selected, the timeframe of the indicator is chosen automatically based on the chart timeframe. The Timeframe dropdown is ignored. The automated timeframes are: \n

 '1 day' for any chart timeframes below '1 day' \n

 '1 week' for any timeframes starting from '1 day' up to '1 week' \n

 '1 month' for any timeframes starting from '1 week' up to '1 month' \n

 '3 months' for any timeframes starting from '1 month' up to '3 months' \n

 '12 months' for any timeframes above '3 months'"

HLR = "High/Low Range"
TR = "True Range"
HAR = "Heikin Ashi Range"

txtBorderSolid = "Solid"
txtBorderDashed = "Dashed"
txtBorderDotted = "Dotted"

txtUseHighLow = "High/Low"
txtUseOpenClose = "Open/Close"

txtWickTranspLight = "Transparent"
txtWickTranspDark = "Not Transparent"

txtWickStyleSolid = "Solid"
txtWickStyleDotted = "Dotted"
txtWickStyleDashed = "Dashed"
txtWickStyleArrowLeft = "Arrow Left"
txtWickStyleArrowRight = "Arrow Right"
txtWickStyleArrowBoth = "Arrow Both"

DEFAULT_RESOLUTION = "1M"
DEFAULT_COLOR_GROWTH = color.rgb(0, 150, 136, 80)
DEFAULT_COLOR_FALL = color.rgb(244, 67, 54, 80)
DEFAULT_BORDER_WIDTH = 0
DEFAULT_BORDER_STYLE = txtBorderSolid
DEFAULT_CANDLE_USAGE = txtUseHighLow
DEFAULT_WICK_TRANSP = 0
DEFAULT_WICK_STYLE = txtWickStyleSolid
DEFAULT_WICK_WIDTH = 1
DEFAULT_CALCULATION_METHOD = HLR
DEFAULT_AUTO_RESOLUTION = true

var prev_bar_index = bar_index

draw_box(left, right, topBody, bottomBody, diff, color_growth, color_fall, border_growth, border_fall, width_border, style_border) =>
    drawed_box = box.new(left, topBody, right, bottomBody, border_width = width_border, border_style = style_border)
    if diff < 0
        box.set_border_color(drawed_box, border_fall)
        box.set_bgcolor(drawed_box, color_fall)
    else
        box.set_border_color(drawed_box, border_growth)
        box.set_bgcolor(drawed_box, color_growth)
    drawed_box
    
draw_line(left, right, topWick, bottomWick, diff, color_growth, color_fall, style_line, width_line) =>
    drawed_line = line.new(left, topWick, right, bottomWick, style = style_line, width = width_line)
    if diff < 0
        line.set_color(drawed_line, color_fall)
    else
        line.set_color(drawed_line, color_growth)
    drawed_line

select_auto_resolution() =>
     timeframe.isseconds ? '120':
     timeframe.isminutes ? '1440':
     timeframe.isdaily ? 'W':
     timeframe.isweekly ? 'M':
     timeframe.ismonthly and timeframe.multiplier < 3 ? '3M': '12M'

auto_resolution = input(DEFAULT_AUTO_RESOLUTION, title="AutoTimeframe", tooltip=AUTO_TIMEFRAME_TOOLTIP, group = "General")
resolution_input = input.timeframe(DEFAULT_RESOLUTION, title="Timeframe", group = "General")
resolution = auto_resolution == true ? select_auto_resolution() : resolution_input

color_growth = input(DEFAULT_COLOR_GROWTH, title="Color Growth / Fall", inline = "Colors", group = "General")
color_fall = input(DEFAULT_COLOR_FALL, title="", inline = "Colors", group = "General")

calculation_method = input.string(DEFAULT_CALCULATION_METHOD, "Bar Style", options = [HLR, TR, HAR], group = "Bar Body")
ohlc_Usage = input.string(DEFAULT_CANDLE_USAGE, "Calculation From", options = [txtUseHighLow, txtUseOpenClose], group = "Bar Body")

width_border = input.int(DEFAULT_BORDER_WIDTH, "Width", minval = 0, group = "Bar Border")
style_border = input.string(DEFAULT_BORDER_STYLE, "Style", options = [txtBorderSolid, txtBorderDashed, txtBorderDotted], group = "Bar Border")

width_Wicks = input.int(DEFAULT_WICK_WIDTH, "Width", minval = 0, maxval = 9, group = "Bar Wick")
style_Wicks = input.string(DEFAULT_WICK_STYLE, "Style", options = [txtWickStyleSolid, txtWickStyleDotted], group = "Bar Wick")
transp_Wicks = input.int(DEFAULT_WICK_TRANSP, "Transparency", minval = 0, maxval = 100, group = "Bar Wick")

show_Wicks = width_Wicks != 0

use_OpenClose = ohlc_Usage == txtUseOpenClose

style_Wick = switch style_Wicks
    txtWickStyleSolid => line.style_solid
    txtWickStyleDotted => line.style_dotted
    txtWickStyleDashed => line.style_dashed
    txtWickStyleArrowLeft => line.style_arrow_left
    txtWickStyleArrowRight => line.style_arrow_right
    txtWickStyleArrowBoth => line.style_arrow_both

border_styl = style_border == txtBorderSolid ? line.style_solid : style_border == txtBorderDashed ? line.style_dashed : line.style_dotted

color_border_growth = color.rgb(color.r(color_growth), color.g(color_growth), color.b(color_growth), 0)
color_border_fall = color.rgb(color.r(color_fall), color.g(color_fall), color.b(color_fall), 0)

color_wick_growth = color.rgb(color.r(color_growth), color.g(color_growth), color.b(color_growth), transp_Wicks)
color_wick_fall = color.rgb(color.r(color_fall), color.g(color_fall), color.b(color_fall), transp_Wicks)

[previous_high, previous_low, previous_close, previous_open, previous_prev_close] = request.security(syminfo.tickerid, resolution, [high[1], low[1], close[1], open[1], close[2]], lookahead=barmerge.lookahead_on)
[current_high, current_low, current_close, current_open, prev_close] = request.security(syminfo.tickerid, resolution, [high, low, close, open, close[1]])

sec_open = barstate.islast ? current_open : previous_open
sec_close = barstate.islast ? current_close : previous_close
sec_high = barstate.islast ? current_high : previous_high
sec_prev_close = barstate.islast ? prev_close : previous_prev_close
sec_low = barstate.islast ? current_low : previous_low

sec_ocMax = math.max(sec_open, sec_close)
sec_ocMin = math.min(sec_open, sec_close)

diff = barstate.islast ? current_close - current_open : previous_close - previous_open
left = prev_bar_index
right =  barstate.islast ? bar_index : bar_index[1]

[ashi_open, ashi_high, ashi_low, ashi_close] = request.security(ticker.heikinashi(syminfo.tickerid), resolution, [open, high, low, close])
float topBody = na
float bottomBody = na
float topWick = na
float bottomWick = na

if calculation_method == HLR
    topBody := use_OpenClose ? sec_ocMax : sec_high
    bottomBody := use_OpenClose ? sec_ocMin : sec_low
    topWick := sec_high
    bottomWick := sec_low
else if calculation_method == TR
    topBody := use_OpenClose ? math.max(sec_ocMax, sec_prev_close) : math.max(sec_high, sec_prev_close)
    bottomBody := use_OpenClose ? math.min(sec_ocMin, sec_prev_close) : math.min(sec_low, sec_prev_close)
    topWick := math.max(sec_high, sec_prev_close)
    bottomWick := math.min(sec_low, sec_prev_close)
else if calculation_method == HAR
    topBody := use_OpenClose ? math.max(ashi_open, ashi_close) : ashi_high
    bottomBody := use_OpenClose ? math.min(ashi_open, ashi_close) : ashi_low
    topWick := ashi_high
    bottomWick := ashi_low

is_new_period = ta.change(time(resolution))

if is_new_period
    prev_bar_index := bar_index

var box prev_box = na
var line prev_topWick = na
var line prev_bottomWick = na

bar_Line = left + math.floor((right - left) / 2)

if is_new_period and not barstate.isrealtime
    draw_box(left, right, topBody, bottomBody, diff, color_growth, color_fall, color_border_growth, color_border_fall, width_border, border_styl)
    if show_Wicks
        draw_line(bar_Line, bar_Line, topBody, topWick, diff, color_wick_growth, color_wick_fall, style_Wick, width_Wicks)
        draw_line(bar_Line, bar_Line, bottomBody, bottomWick, diff, color_wick_growth, color_wick_fall, style_Wick, width_Wicks)

if barstate.islast
    if is_new_period
        prev_box := na
        prev_topWick := na
        prev_bottomWick := na
    else
        box.delete(prev_box)
        line.delete(prev_topWick)
        line.delete(prev_bottomWick)
        prev_box := draw_box(left, right, topBody, bottomBody, diff, color_growth, color_fall, color_border_growth, color_border_fall, width_border, border_styl)
        if show_Wicks
            prev_topWick := draw_line(bar_Line, bar_Line, topBody, topWick, diff, color_wick_growth, color_wick_fall, style_Wick, width_Wicks)
            prev_bottomWick := draw_line(bar_Line, bar_Line, bottomBody, bottomWick, diff, color_wick_growth, color_wick_fall, style_Wick, width_Wicks)
