HTF Tool 2
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © SamRecio
//

//@version=5
indicator("HTF Tool 2", shorttitle = "[HTF2]", overlay = true, max_boxes_count = 500, max_lines_count = 500)

//General Inputs
tf = input.timeframe("15", title = "Higher Timeframe", tooltip = "Timeframe must be...\n|Greater-than or Equal-to|\nthe Current Chart Timeframe.")
up_color = input.color(color.rgb(0,230,118,70), title = "        Up Color", inline = "2")
down_color = input.color(color.rgb(230,30,50,70), title = "        Down Color", inline = "2")

//HTF MA Inputs
ma_tog = input.bool(true, title = "", group = "HTF Moving Average", inline = "1" )
len = input.int(13, minval = 1, title  = "HTF MA ➡", group = "HTF Moving Average", inline = "1")
ma_type = input.string("EMA", title = "", options = ["EMA","SMA"], group = "HTF Moving Average", inline = "1")
ma_col = input.color(color.rgb(251,192,45), title = "", group = "HTF Moving Average", inline = "1" )


//Lvl 1 Inputs
lvl1_tog = input.bool(false, title = "Lvl 1    ➡ ", group = "measurments", inline = "1", tooltip = "How levels are drawn:\nGreen Candle = High(0.00) to Low(1.00)\nRed Candle = Low(0.00) to High(1.00)")
in_lvl_1 = input.float(0.382, step = 0.01, title = "", group = "measurments", inline = "1")
lvl1_style = input.string(". . .", title = "", options = ["___","- - -",". . ."], group = "measurments", inline = "1")
lvl1_color = input.color(color.white,title = "", group = "measurments", inline = "1")
//Lvl 2 Inputs
lvl2_tog = input.bool(true, title = "Lvl 2    ➡ ", group = "measurments", inline = "2")
in_lvl_2 = input.float(0.5, title = "", step = 0.01, group = "measurments", inline = "2")
lvl2_style = input.string("- - -", title = "", options = ["___","- - -",". . ."], group = "measurments", inline = "2")
lvl2_color = input.color(color.white,title = "", group = "measurments", inline = "2")
//Lvl 3 Inputs
lvl3_tog = input.bool(false, title = "Lvl 3    ➡ ", group = "measurments", inline = "3")
in_lvl_3 = input.float(0.618, title = "", step = 0.01, group = "measurments", inline = "3")
lvl3_style = input.string(". . .", title = "", options = ["___","- - -",". . ."], group = "measurments", inline = "3")
lvl3_color = input.color(color.white,title = "", group = "measurments", inline = "3")
//Lvl Settings
lvl_extend = input.int(10, title = "Extend Levels", tooltip = "# of bars to extend levels past the current bar.\nNote: Value can be negative.")
lb = input.int(30, maxval = 120, minval = 1, title = "Number of HTF Bars to Display:", tooltip = "MinVal = 1\nMaxVal = 120")

//Check for Same TF to make bars clear
tf_check = timeframe.period == tf
//Check for HTF
if timeframe.in_seconds(tf) < timeframe.in_seconds(timeframe.period)
    runtime.error("Please use a HIGHER Timeframe.")
//UD type to store candle box and line data, for easy access later
type candle
    box body
    line high_wick
    line low_wick

//red/green/gray coloring function
rg(_open,_close,_color1,_color2,_color3) =>
    _close > _open?_color1:
     _close < _open?_color2:
     _color3
///
//Candle Drawing Function
draw_candle(_o,_h,_l,_c,_left,_right,_rcolor,_gcolor,_ncolor) =>
    top = math.max(_o,_c)
    bot = math.min(_o,_c)
    mid = math.round(math.avg(_left,_right))
    rg_color = rg(_o,_c,_gcolor,_rcolor,_ncolor)
    candle.new(box.new(_left,top,_right,bot,bgcolor = tf_check?na:rg_color,border_color = tf_check?na:color.new(rg_color,0)),
         line.new(mid,top,mid,_h, color = tf_check?na:color.new(rg_color,0)),
         line.new(mid,bot,mid,_l, color = tf_check?na:color.new(rg_color,0)))

//Line style translation Function
linestyle(_input) =>
    _input == "___"?line.style_solid:
     _input == "- - -"?line.style_dashed:
     _input == ". . ."?line.style_dotted:
     na

///
//The ticking of the clock
new_tf = timeframe.change(tf)
//
//Necessary Candle Data
last_open = ta.valuewhen(new_tf,open,1)
last_left = ta.valuewhen(new_tf,bar_index,1) 
current_open = ta.valuewhen(new_tf,open,0)
current_left = ta.valuewhen(new_tf,bar_index,0) 
 
//HTF High/Low Tracking
//Is easier than using Highest/Lowest and it works flawlessly.
var float h = na
var float l = na
if new_tf
    h := high 
    l := low
if low < l
    l := low
if high > h
    h := high
///////////////////////

//Lvl function for switching level placement depending on bar direction
lvl(_lvl) =>
    close>current_open?h-_lvl:l+_lvl  

//Lvl Calc
var lvls = array.new_line(na)
rng = h-l
lvl1 = lvl(in_lvl_1*rng)
lvl2 = lvl(in_lvl_2*rng)
lvl3 = lvl(in_lvl_3*rng)

//Draw Historic Candles on New TF
//and Lvls on historic bars
var candle_array = array.new<candle>(na)
var mid_array = array.new_int(na)
if new_tf
    array.push(candle_array,draw_candle(last_open,h[1],l[1],close[1],last_left,bar_index-1,down_color,up_color,color.new(color.gray,70)))
    array.push(mid_array,math.round(math.avg(last_left,bar_index-1)))
if new_tf and lvl1_tog    
    array.push(lvls,line.new(last_left,lvl1[1],bar_index-1,lvl1[1], style = linestyle(lvl1_style), color = lvl1_color))
if new_tf and lvl2_tog 
    array.push(lvls,line.new(last_left,lvl2[1],bar_index-1,lvl2[1], style = linestyle(lvl2_style), color = lvl2_color))
if new_tf and lvl3_tog     
    array.push(lvls,line.new(last_left,lvl3[1],bar_index-1,lvl3[1], style = linestyle(lvl3_style), color = lvl3_color))


//Lvl Line Management (Dynamic deletion)
lb_bi = ta.valuewhen(new_tf,bar_index,lb-1) //lookback bar_index
if array.size(lvls) > 0 
    for i = array.size(lvls) - 1 to 0
        lx = array.get(lvls,i)
        lx_left = line.get_x1(lx)
        lx_lvl = line.get_y1(lx)
        cross = (lx_lvl >= close[1] and lx_lvl < close) or (lx_lvl  <= close[1] and lx_lvl > close) or (lx_lvl < math.max(open,close) and lx_lvl > math.min(open,close))
        toofar = lx_left < lb_bi
        if cross or toofar
            line.delete(lx)
            array.remove(lvls,i)
        line.set_x2(lx,bar_index+lvl_extend) 

//Drawing live candle
live_candle = draw_candle(current_open,h,l,close,current_left,bar_index,down_color,up_color,color.new(color.gray,70))
box.delete(live_candle.body[1])
line.delete(live_candle.high_wick[1])
line.delete(live_candle.low_wick[1])

//Deleting HTF bars past the lookback number
if array.size(candle_array) > lb-1
    box.delete(array.get(candle_array,0).body)
    line.delete(array.get(candle_array,0).high_wick)
    line.delete(array.get(candle_array,0).low_wick)
    array.remove(candle_array,0)


//Live Levels
var ll1 = line.new(na,na,na,na, style = linestyle(lvl1_style), color = lvl1_color)
var ll2 = line.new(na,na,na,na, style = linestyle(lvl2_style), color = lvl2_color)
var ll3 = line.new(na,na,na,na, style = linestyle(lvl3_style), color = lvl3_color)

//Setting Live LVL Values
if lvl1_tog 
    line.set_xy1(ll1,current_left,lvl1)
    line.set_xy2(ll1,bar_index+lvl_extend,lvl1)
if lvl2_tog 
    line.set_xy1(ll2,current_left,lvl2)
    line.set_xy2(ll2,bar_index+lvl_extend,lvl2)
if lvl3_tog 
    line.set_xy1(ll3,current_left,lvl3)
    line.set_xy2(ll3,bar_index+lvl_extend,lvl3)

//MOVING AVERAGE STUFF
//close array(for SMA)
var close_array = array.new_float(na)
if new_tf 
    array.push(close_array,close[1])
if new_tf and array.size(close_array) > len
    array.remove(close_array,0)
//Calculating Historic MA values to append to the historic MA
k = 2/(len + 1)
var float ma = na
if new_tf and ma_type == "EMA"
    ma := (close[1]*k) + (nz(ma[1])*(1-k))
if new_tf and ma_type == "SMA"
    ma := array.avg(close_array)
//Initiating variables fo draw the mas
var ma_array = array.new_line(na)
last_mid = array.size(mid_array)>1?array.get(mid_array,array.size(mid_array)-1):na
prev_last_mid = array.size(mid_array)>1?array.get(mid_array,array.size(mid_array)-2):na
//Adds a line to the MA every new bar
if new_tf and ma_tog
    array.push(ma_array,line.new(prev_last_mid,ma[1],last_mid,ma, width = 2, color = ma_col))
if array.size(ma_array) > lb-1
    line.delete(array.get(ma_array,0))
    array.remove(ma_array,0)
//Tip of the MA
//Calculating Averages
htf_sma = array.size(close_array) > 0?((array.sum(close_array) - array.get(close_array,0))+close)/len:na
htf_ema = (close*k) + (nz(ma[1])*(1-k))
htf_ma = ma_type == "EMA"?htf_ema:htf_sma
//Drawing the Tip
if ma_tog
    live_line = line.new(last_mid,ma,bar_index,htf_ma, width = 2, color = ma_col)
    line.delete(live_line[1])
//Plotting for values
plot(ma_tog?htf_ma:na,show_last = 1, title = "HTF_MA",editable = false, display = ma_tog?display.price_scale + display.status_line:display.none, color = ma_col)
