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

//@version=5

//Thanks to code from @PineCoders Visible Chart library (PineCoders/VisibleChart/4), which is a much more comprehensive library than this, but does not include the some functions which i find useful:
//Added the following exportable functions: highest/lowest body, highest/lowest close, highest/lowest open. These allow one to anchor fibs from bodies rather than wicks
//Added a Fib Box function in the example code


//@twingall

library("BasicVisibleChart", true)

//Functions to export:

export barIsVisible() =>
    bool result = time >= chart.left_visible_bar_time and time <= chart.right_visible_bar_time

// highest close, highest open, highest body (for cases of price gapping at the high, the highest of the two)
export highestClose() => 
    var float result = na
    if barIsVisible() and close >= nz(result, close)
        result := close
    result

export highestOpen() => 
    var float result = na
    if barIsVisible() and open >= nz(result, open)
        result := open
    result

export highestBody() =>
	math.max(highestOpen(), highestClose())

// lowest close, lowest open, lowest body (for cases of price gapping at the low, the lowest of the two)
export lowestClose() => 
    var float result = na
    if barIsVisible() and close <= nz(result, close)
        result := close
    result

export lowestOpen() => 
    var float result = na
    if barIsVisible() and open <= nz(result, open)
        result := open
    result

export lowestBody() =>
	math.min(lowestOpen(), lowestClose())

//thanks to @PineCoders' VisibleChart library for the remainder of the export functions
export high() => 
    var float result = na
    if barIsVisible() and high >= nz(result, high)
        result := high
    result

export highBarTime() =>
    var float chartHigh = na
    var int   highTime  = na
    if barIsVisible() and high >= nz(chartHigh, high)
        highTime  := time
        chartHigh := high
    int result = highTime

export low() => 
    var float result = na
    if barIsVisible() and low <= nz(result, low)
        result := low
    result

export lowBarTime() =>
    var float chartLow = na
    var int   lowTime  = na
    if barIsVisible() and low <= nz(chartLow, low)
        lowTime  := time
        chartLow := low
    int result = lowTime

export open() => 
    var float result = na
    if time == chart.left_visible_bar_time
        result := open
    result

export close() => 
    var float result = na
    if barIsVisible()
        result := close
    result


//////// Example Code ////////////////

// declare variables 
//note: when pasting this into your own seperate indicator; you need to include the library name when declaring variables, i.e: // float highestBody = BasicVisibleChart.highestBody()
float highestBody = highestBody()
float lowestBody = lowestBody()
int   highTime   = highBarTime()
int   lowTime    = lowBarTime()
int   leftTime   = math.min(highTime, lowTime)
int   rightTime  = math.max(highTime, lowTime)
bool  isBull     = lowTime < highTime

//Function for Fib lines
fibLine(series color fibColor, series float fibLevel) => 
    float fibRatio = 1-(fibLevel / 100)
    float fibPrice = isBull ? lowestBody  + ((highestBody - lowestBody) * fibRatio) : 
                              highestBody - ((highestBody - lowestBody) * fibRatio)
    var line  fibLine  =  line.new(na, na, na, na, xloc.bar_time, extend.right, fibColor,  line.style_dotted,  2)
    line.set_xy1(fibLine,  leftTime,  fibPrice)
    line.set_xy2(fibLine,  rightTime, fibPrice)

// Function for Fib box: the zone of retracement
fibBox(series color fibColor, series float fibLevel_1, series float fibLevel_2) =>
    float fibRatio_1 = 1-(fibLevel_1 / 100)
    float fibPrice_1 = isBull ? lowestBody  + ((highestBody - lowestBody) * fibRatio_1) :highestBody - ((highestBody - lowestBody) * fibRatio_1)
    float fibRatio_2 = 1-(fibLevel_2 / 100)
    float fibPrice_2 = isBull ? lowestBody  + ((highestBody - lowestBody) * fibRatio_2) : highestBody - ((highestBody - lowestBody) * fibRatio_2)
    var b = box.new(na, na, na, na, xloc=xloc.bar_time, border_style=line.style_dashed, extend = extend.right, border_color=color.new(color.white,100), text_color=color.new(color.gray,70), text_halign=text.align_right)
    box.set_lefttop(b, leftTime, fibPrice_1)
    box.set_rightbottom(b, rightTime,fibPrice_2)
    box.set_bgcolor(b,  fibColor)

// Display code that only runs on the last bar but displays visuals on visible bars, wherever they might be in the dataset.
if barstate.islast
    //declare/define Fib lines and decalare/define Fib Box
	fibLine(color.new(color.blue, 30), 0) 
	fibLine(color.new(color.blue, 30), 100)
    //fibLine(color.new(color.blue, 30), 50) //midline
    fibBox(color.new(color.orange,80), 61.8, 78.6) //draws fib box showing 61.8% - 78.6% retracement