Visible Range
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © kaigouthro

import kaigouthro/hsvColor/11 as h
import kaigouthro/calc/5
import kaigouthro/font/4

//@version=5
indicator("Visible Range",'Range View',true)

//input distances
var int _d1 = input.int(5, 'Bar Distance for Viewing ', 5,50,5)
var int _d2 = input.int(20, 'Second Bar Distance Mult.', 20,50,1) * _d1 

// set line
var line  _highvisible  = na
var line  _current      = na
var line  _lowvisible   = na
var line  _rangeline    = na
var line  _highdist     = na
var line  _lowdist      = na
var line  _midpoint     = na
var label _rangeline_lb = na
var label _highdist_lb  = na
var label _lowdist_lb   = na
var linefill  _midfill  = na 

// create lines to fill 
if barstate.isfirst
    _highvisible  := line.new  (chart.left_visible_bar_time,close,chart.right_visible_bar_time,close, xloc.bar_time ,extend.left, #88888888,line.style_dotted,1)   
    _lowvisible   := line.new  (chart.left_visible_bar_time,close,chart.right_visible_bar_time,close, xloc.bar_time ,extend.left, #88888888,line.style_dotted,1)   
    _current      := line.new  (last_bar_index[10],close,last_bar_index,close                       , xloc.bar_index ,extend.right, #88888888,line.style_dotted,1)  
    _midpoint     := line.new  (last_bar_index[10],close,last_bar_index,close                       , xloc.bar_index ,extend.none, #88888888,line.style_dotted,1)  
    _rangeline    := line.new  (last_bar_index[10],close,last_bar_index,close                       )   
    _highdist     := line.new  (last_bar_index[10],close,last_bar_index,close                       )    
    _lowdist      := line.new  (last_bar_index[10],close,last_bar_index,close                       )    
    _rangeline_lb := label.new (last_bar_index ,close, '',size = size.normal                        )
    _highdist_lb  := label.new (last_bar_index ,close, '',size = size.small                         )
    _lowdist_lb   := label.new (last_bar_index ,close, '',size = size.small                         )
    _midfill      := linefill.new(_current,_midpoint,#00000000)

// force update value each calc
var _newalc        = -1
_newalc           *= -1

//get and set values
if ta.change(_newalc) and (time > chart.left_visible_bar_time)
    varip _highest    =  close
    varip _lowest     =  close
    _lefttime         =  chart.left_visible_bar_time
    _righttime        =  chart.right_visible_bar_time
    _close            =  close
    _highest          := time >=   _lefttime  ? math.max(_highest , high           ) :  close
    _lowest           := time >=   _lefttime  ? math.min(_lowest  , low            ) :  close
    _avg              = math.avg ( _highest   , _lowest )
    line.set_xy2      ( _current       ,  last_bar_index - _d1 , _close                     )  
    line.set_xy1      ( _current       ,  last_bar_index - _d2 , _close                     )  
    line.set_xy2      ( _midpoint      ,  last_bar_index - _d1 , _avg                       )  
    line.set_xy1      ( _midpoint      ,  last_bar_index - _d2 , _avg                       )  
    line.set_xy1      ( _highvisible   ,  _lefttime            , _highest                   )  
    line.set_xy2      ( _highvisible   ,  _righttime           , _highest                   )  
    line.set_xy1      ( _lowvisible    ,  _lefttime            , _lowest                    )  
    line.set_xy2      ( _lowvisible    ,  _righttime           , _lowest                    )  
    line.set_xy1      ( _rangeline     ,  last_bar_index - _d2 , _highest                   ) 
    line.set_xy2      ( _rangeline     ,  last_bar_index - _d2 , _lowest                    ) 
    line.set_xy1      ( _highdist      ,  last_bar_index - _d1 , _close                     ) 
    line.set_xy2      ( _highdist      ,  last_bar_index - _d1 , _highest                   ) 
    line.set_xy1      ( _lowdist       ,  last_bar_index - _d1 , _close                     ) 
    line.set_xy2      ( _lowdist       ,  last_bar_index - _d1 , _lowest                    ) 
    label.set_xy      ( _lowdist_lb    ,  last_bar_index - _d1 ,  math.avg(_close, _lowest ))  
    _range            = (_highest      /  _lowest        - 1   )
    _lowdif           = (_close        /  _lowest        - 1   ) 
    _highdif          = (_close        /  _highest       - 1   ) 
    _colrangeline     = h.hsv(calc.percentOfDistance(_close - _avg  , _lowest - _avg  , _highest  - _avg   ) * 120 , .8,1,1) 
    _collowdist       = h.hsv(calc.percentOfDistance(_close         , _lowest         , _highest           ) * 120 , .8,1,1) 
    _colhighdist      = h.hsv(calc.percentOfDistance(_close         , _highest        , _lowest            ) * 120 , .8,1,1) 
    linefill.set_color( _midfill, color.new(_avg > _close ? _colhighdist : _collowdist,90))
    label.set_text    ( _lowdist_lb    ,  font.uni(str.format('{0,number,#.##} % ', 100 * (_close    / _lowest  - 1 ) ), 15))
    label.set_color   ( _lowdist_lb    , _collowdist    )
    line.set_color    ( _lowdist       , _collowdist    )
    label.set_xy      ( _rangeline_lb  ,  last_bar_index - _d2  ,  math.avg(_highest, _lowest    )) 
    label.set_text    ( _rangeline_lb  ,  font.uni(str.format('{0,number,#.##} % from avg \n {1,number,#.##} % Range', 100 * (_close  / _avg  - 1 ), 100 * (_highest  / _lowest  - 1 ) ), 15))
    label.set_color   ( _rangeline_lb  , _colrangeline  )
    line.set_color    ( _rangeline     , _colrangeline  )
    label.set_xy      ( _highdist_lb   ,  last_bar_index - _d1       ,  math.avg(_close, _highest  )) 
    label.set_text    ( _highdist_lb   ,  font.uni(str.format('{0,number,#.##} %', 100 * (_close    / _highest - 1 ) ), 15))
    label.set_color   ( _highdist_lb   , _colhighdist   )
    line.set_color    ( _highdist      , _colhighdist   )
