Previous Days Ranges
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © syntaxgeek

//@version=5
indicator(title="Previous Days Ranges", shorttitle="PDR", overlay=true)

// todo
// * add better breakout and retest detection
// * have mid range price lines draw only when necessary to reduce eye strain
// * alerts for key level breakouts like phod and plod

// <inputs>
i_daySession = input.session(title="Regular Session", defval="0930-1600")
i_ethSession = input.session(title="Extended Session", defval="1600-2000")
i_showPriceTargetLabels = input.bool(title="Show Price Target Labels?", defval=true)
i_showEntries = input.bool(true, "Show potential breakouts.")
// i_alertBreakoutsOnly = input.bool(false, "Alert only on breakouts (not price ticks)")
i_showRangeLevels = input.string("none", "Show Range Levels?", options=["fib", "percentage", "none"])
// </inputs>

// <funcs>

// f_SessionHigh() returns the highest price during the specified 
// session, optionally corrected for the given time zone.
// Returns 'na' when the session hasn't started or isn't on the chart.
f_SessionHigh(sessionTime, sessionTimeZone=syminfo.timezone) =>
    insideSession = not na(time(timeframe.period, sessionTime, sessionTimeZone))
    var float sessionHighPrice = na

    if insideSession and not insideSession[1]
        sessionHighPrice := high
    else if insideSession
        sessionHighPrice := math.max(sessionHighPrice, high)
    
    sessionHighPrice
    
// f_SessionLow() returns the lowest price during the given session,
// optionally corrected for the specified time zone.
// Returns 'na' when the session hasn't started or isn't on the chart.
f_SessionLow(sessionTime, sessionTimeZone=syminfo.timezone) =>
    insideSession = not na(time(timeframe.period, sessionTime, sessionTimeZone))
    var float sessionLowPrice = na

    if insideSession and not insideSession[1]
        sessionLowPrice := low
    else if insideSession
        sessionLowPrice := math.min(sessionLowPrice, low)
    
    sessionLowPrice

// f_DrawPriceTargetLabel() draws new price label flag at right of price data
// requires re-execution to keep label right justified of price data
f_DrawPriceTargetLabel(fromPrice, level, name, col) => 
    if i_showPriceTargetLabels
        var lbl = label.new(bar_index, fromPrice + level, style=label.style_label_lower_left, text=name, color=col, textcolor=color.white)
        label.set_xy(lbl, bar_index + 2, fromPrice + level)

f_RenderBreakoutLabel(yloc, labelStyle) =>
    lbl = label.new(bar_index, na)
    label.set_color(lbl, color.green)
    label.set_textcolor(lbl, color.green)
    label.set_text(lbl, "Breakout")//\n Wait for Retest")
    label.set_yloc(lbl, yloc)
    label.set_style(lbl, labelStyle)
    label.set_size(lbl, size.tiny)

f_RenderBreakoutRetestLabel(message, yloc, color, labelStyle) =>
    lbl = label.new(bar_index, na)
    label.set_color(lbl, color)
    label.set_textcolor(lbl, color.white)
    label.set_text(lbl, message)
    label.set_yloc(lbl, yloc)
    label.set_style(lbl, labelStyle)
    label.set_size(lbl, size.tiny)

f_OverPrevDayHigh(pdh) => close >= pdh
f_UnderPrevDayLow(pdl) => close <= pdl

f_RenderPercentageHigh(pdh) => f_OverPrevDayHigh(pdh) and i_showRangeLevels == "percentage" and session.ismarket
f_RenderPercentageLow(pdl) => f_UnderPrevDayLow(pdl) and i_showRangeLevels == "percentage" and session.ismarket
f_RenderFibHigh(pdh) => f_OverPrevDayHigh(pdh) and i_showRangeLevels == "fib" and session.ismarket
f_RenderFibLow(pdl) => f_UnderPrevDayLow(pdl) and i_showRangeLevels == "fib" and session.ismarket

f_CalculatePDRPercentage(price, priceRange, multi) =>
     price + (priceRange * multi)

// </funcs>

// <vars>

v_ethStockSessHigh = f_SessionHigh(i_ethSession)
v_ethStockSessLow = f_SessionLow(i_ethSession)
v_prevDayHigh = request.security(syminfo.tickerid, 'D', high[1], lookahead = barmerge.lookahead_on)
v_prevDayLow = request.security(syminfo.tickerid, 'D', low[1], lookahead = barmerge.lookahead_on)
v_pdrRange = v_prevDayHigh - v_prevDayLow
v_prevDayMid = v_prevDayHigh - (v_pdrRange / 2)
v_pdrRangeMidToHigh = v_prevDayHigh - v_prevDayMid
v_pdrRangeMidToLow = v_prevDayMid - v_prevDayLow

// fib range based levels
v_levelHighFib1 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 0.236)
v_levelHighFib2 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 0.382)
v_levelHighFib3 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 0.5)
v_levelHighFib4 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 0.618)
v_levelHighFib5 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 0.786)
v_levelLowFib1 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -0.236)
v_levelLowFib2 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -0.382)
v_levelLowFib3 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -0.5)
v_levelLowFib4 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -0.618)
v_levelLowFib5 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -0.786)

// percentage range based levels
v_levelHighPer1 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 0.5)
v_levelHighPer2 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 1)
v_levelHighPer3 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 1.5)
v_levelHighPer4 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 2)
v_levelHighPer5 = f_CalculatePDRPercentage(v_prevDayHigh, v_pdrRange, 2.5)
v_levelLowPer1 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -0.5)
v_levelLowPer2 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -1)
v_levelLowPer3 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -1.5)
v_levelLowPer4 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -2)
v_levelLowPer5 = f_CalculatePDRPercentage(v_prevDayLow, v_pdrRange, -2.5)

// fib mid range based levels
v_levelMidHighFib1 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.236)
v_levelMidHighFib2 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.382)
v_levelMidHighFib3 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.5)
v_levelMidHighFib4 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.618)
v_levelMidHighFib5 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.786)
v_levelMidLowFib1 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.236)
v_levelMidLowFib2 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.382)
v_levelMidLowFib3 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.5)
v_levelMidLowFib4 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.618)
v_levelMidLowFib5 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.786)

// percentage mid range based levels
v_levelMidHighPer1 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.25)
v_levelMidHighPer2 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.5)
v_levelMidHighPer3 = f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToHigh, 0.75)
v_levelMidLowPer1 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.25)
v_levelMidLowPer2 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.5)
v_levelMidLowPer3 =  f_CalculatePDRPercentage(v_prevDayMid, v_pdrRangeMidToLow, -0.75)

var v_inBreakout = false
bool v_prevDayHighBreakOut = (low[2] < v_prevDayHigh and close[2] > v_prevDayHigh and low[1] > v_prevDayHigh and close[1] > v_prevDayHigh and close > low[1] and  low > v_prevDayHigh)  and session.ismarket
bool v_prevDayLowBreakOut =  (high[2] > v_prevDayLow and close[2] < v_prevDayLow and high[1] < v_prevDayLow and close[1] < v_prevDayLow   and close < high[1] and high < v_prevDayLow)  and session.ismarket
bool v_prevDayHighCross = (ta.cross(close, v_prevDayHigh)) or (v_prevDayHighBreakOut) //not i_alertBreakoutsOnly and ... i_alertBreakoutsOnly and 
bool v_prevDayLowCross =  (ta.cross(close, v_prevDayLow)) or (v_prevDayLowBreakOut) //not i_alertBreakoutsOnly and ... i_alertBreakoutsOnly and 
bool v_isPrevDayHighRetest = close[1] > v_prevDayHigh and low <= v_prevDayHigh and close >= v_prevDayHigh
bool v_isPrevDayLowRetest  = close[1] < v_prevDayLow and high >= v_prevDayLow and close <= v_prevDayLow
bool v_isFailedRetest = v_inBreakout and ((close[1] > v_prevDayHigh and close < v_prevDayHigh) or (close[1] < v_prevDayLow and close > v_prevDayLow))

// </vars>

// <plots>

if (i_showEntries and session.ismarket)
    if (v_prevDayHighBreakOut)
        f_RenderBreakoutLabel(yloc.abovebar, label.style_triangledown)
        v_inBreakout := true
        
    if (v_prevDayLowBreakOut)
        f_RenderBreakoutLabel(yloc.belowbar, label.style_triangleup)
        v_inBreakout := true
        
    // if v_inBreakout and (v_isPrevDayHighRetest or v_isPrevDayLowRetest)
    //     f_RenderBreakoutRetestLabel("Retest", yloc.abovebar,  color.green, label.style_label_down)
    //     v_inBreakout := false
        
    // if v_inBreakout and v_isFailedRetest
    //     f_RenderBreakoutRetestLabel("Failed Retest", yloc.abovebar, color.red, label.style_label_down)
    //     v_inBreakout := false

if (session.ismarket)
    f_DrawPriceTargetLabel(v_prevDayHigh, 0, "PDH", color.red)
    f_DrawPriceTargetLabel(v_prevDayMid, 0, "PDM", color.gray)
    f_DrawPriceTargetLabel(v_prevDayLow, 0, "PDL", color.green)
    f_DrawPriceTargetLabel(v_ethStockSessHigh, 0, "EH", color.new(color.purple, 50))
    f_DrawPriceTargetLabel(v_ethStockSessLow, 0, "EL", color.new(color.yellow, 50))

    if (f_RenderPercentageHigh(v_prevDayHigh))
        f_DrawPriceTargetLabel(v_levelHighPer5, 0, 'PDH 250%', color.red)
        f_DrawPriceTargetLabel(v_levelHighPer4, 0, 'PDH 200%', color.red)
        f_DrawPriceTargetLabel(v_levelHighPer3, 0, 'PDH 150%', color.red)
        f_DrawPriceTargetLabel(v_levelHighPer2, 0, 'PDH 100%', color.red)
        f_DrawPriceTargetLabel(v_levelHighPer1, 0, 'PDH 50%', color.red)

    if (f_RenderPercentageLow(v_prevDayLow))
        f_DrawPriceTargetLabel(v_levelLowPer5, 0, 'PDL 250%', color.red)
        f_DrawPriceTargetLabel(v_levelLowPer4, 0, 'PDL 200%', color.red)
        f_DrawPriceTargetLabel(v_levelLowPer3, 0, 'PDL 150%', color.red)
        f_DrawPriceTargetLabel(v_levelLowPer2, 0, 'PDL 100%', color.red)
        f_DrawPriceTargetLabel(v_levelLowPer1, 0, 'PDL 50%', color.red)

    if (f_RenderFibHigh(v_prevDayHigh))
        f_DrawPriceTargetLabel(v_levelHighFib5, 0, 'PDH FIB 78.6%', color.red)
        f_DrawPriceTargetLabel(v_levelHighFib4, 0, 'PDH FIB 61.8%', color.red)
        f_DrawPriceTargetLabel(v_levelHighFib3, 0, 'PDH FIB 50%', color.red)
        f_DrawPriceTargetLabel(v_levelHighFib2, 0, 'PDH FIB 38.2%', color.red)
        f_DrawPriceTargetLabel(v_levelHighFib1, 0, 'PDH FIB 23.6%', color.red)
    
    if (f_RenderFibLow(v_prevDayLow))
        f_DrawPriceTargetLabel(v_levelLowFib1, 0, 'PDL FIB -23.6%', color.green)
        f_DrawPriceTargetLabel(v_levelLowFib2, 0, 'PDL FIB -38.2%', color.green)
        f_DrawPriceTargetLabel(v_levelLowFib3, 0, 'PDL FIB -50%', color.green)
        f_DrawPriceTargetLabel(v_levelLowFib4, 0, 'PDL FIB -61.8%', color.green)
        f_DrawPriceTargetLabel(v_levelLowFib5, 0, 'PDL FIB -78.6%', color.green)

if (i_showRangeLevels == "percentage" and session.ismarket)
    f_DrawPriceTargetLabel(v_levelMidHighPer3, 0, "PDMH 75%", color.red)
    f_DrawPriceTargetLabel(v_levelMidHighPer2, 0, "PDMH 50%", color.red)
    f_DrawPriceTargetLabel(v_levelMidHighPer1, 0, "PDMH 25%", color.red)
    f_DrawPriceTargetLabel(v_levelMidLowPer1, 0, "PDMH 25%", color.green)
    f_DrawPriceTargetLabel(v_levelMidLowPer2, 0, "PDMH 50%", color.green)
    f_DrawPriceTargetLabel(v_levelMidLowPer3, 0, "PDMH 75%", color.green)

if (i_showRangeLevels == "fib" and session.ismarket)
    f_DrawPriceTargetLabel(v_levelMidHighFib5, 0, 'PDMH FIB 78.6%', color.red)
    f_DrawPriceTargetLabel(v_levelMidHighFib4, 0, 'PDMH FIB 61.8%', color.red)
    f_DrawPriceTargetLabel(v_levelMidHighFib3, 0, 'PDMH FIB 50%', color.red)
    f_DrawPriceTargetLabel(v_levelMidHighFib2, 0, 'PDMH FIB 38.2%', color.red)
    f_DrawPriceTargetLabel(v_levelMidHighFib1, 0, 'PDMH FIB 23.6%', color.red)
    f_DrawPriceTargetLabel(v_levelMidLowFib1, 0, 'PDML FIB -23.6%', color.green)
    f_DrawPriceTargetLabel(v_levelMidLowFib2, 0, 'PDML FIB -38.2%', color.green)
    f_DrawPriceTargetLabel(v_levelMidLowFib3, 0, 'PDML FIB -50%', color.green)
    f_DrawPriceTargetLabel(v_levelMidLowFib4, 0, 'PDML FIB -61.8%', color.green)
    f_DrawPriceTargetLabel(v_levelMidLowFib5, 0, 'PDML FIB -78.6%', color.green)

// previous days rth levels
plot(session.ismarket ? v_prevDayHigh : na, title='PDH', color=color.red, linewidth=2, style=plot.style_cross)
plot(session.ismarket ? v_prevDayMid : na, title='PDM', color=color.gray, linewidth=2, style=plot.style_cross)
plot(session.ismarket ? v_prevDayLow : na, title='PDL', color=color.green, linewidth=2, style=plot.style_cross)

// previous days eth levels
plot(session.ismarket or session.ispremarket ? v_ethStockSessHigh : na, title='EH', color=color.new(color.purple, 50), style=plot.style_circles)
plot(session.ismarket or session.ispremarket ? v_ethStockSessLow : na, title='EL', color=color.new(color.yellow, 50), style=plot.style_circles)

// percentage levels from previous days high/low range
plot(f_RenderPercentageHigh(v_prevDayHigh) ? v_levelHighPer5 : na, title='PDH 250%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageHigh(v_prevDayHigh) ? v_levelHighPer4 : na, title='PDH 200%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageHigh(v_prevDayHigh) ? v_levelHighPer3 : na, title='PDH 150%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageHigh(v_prevDayHigh) ? v_levelHighPer2 : na, title='PDH 100%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageHigh(v_prevDayHigh) ? v_levelHighPer1 : na, title='PDH 50%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageLow(v_prevDayLow) ? v_levelLowPer1 : na, title='PDL -50%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageLow(v_prevDayLow) ? v_levelLowPer2 : na, title='PDL -100%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageLow(v_prevDayLow) ? v_levelLowPer3 : na, title='PDL -150%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageLow(v_prevDayLow) ? v_levelLowPer4 : na, title='PDL -200%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderPercentageLow(v_prevDayLow) ? v_levelLowPer5 : na, title='PDL -250%', color=color.green, linewidth=1, style=plot.style_cross)

// fib levels from previous days high/low range
plot(f_RenderFibHigh(v_prevDayHigh) ? v_levelHighFib5 : na, title='PDH FIB 78.6%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderFibHigh(v_prevDayHigh) ? v_levelHighFib4 : na, title='PDH FIB 61.8%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderFibHigh(v_prevDayHigh) ? v_levelHighFib3 : na, title='PDH FIB 50%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderFibHigh(v_prevDayHigh) ? v_levelHighFib2 : na, title='PDH FIB 38.2%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderFibHigh(v_prevDayHigh) ? v_levelHighFib1 : na, title='PDH FIB 23.6%', color=color.red, linewidth=1, style=plot.style_cross)
plot(f_RenderFibLow(v_prevDayLow) ? v_levelLowFib1 : na, title='PDL FIB -23.6%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderFibLow(v_prevDayLow) ? v_levelLowFib2 : na, title='PDL FIB -38.2%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderFibLow(v_prevDayLow) ? v_levelLowFib3 : na, title='PDL FIB -50%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderFibLow(v_prevDayLow) ? v_levelLowFib4 : na, title='PDL FIB -61.8%', color=color.green, linewidth=1, style=plot.style_cross)
plot(f_RenderFibLow(v_prevDayLow) ? v_levelLowFib5 : na, title='PDL FIB -78.6%', color=color.green, linewidth=1, style=plot.style_cross)

// percentage levels from previous days high/low mid range
plot(i_showRangeLevels == "percentage" and session.ismarket ? v_levelMidHighPer3 : na, title='PDMH 75%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "percentage" and session.ismarket ? v_levelMidHighPer2 : na, title='PDMH 50%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "percentage" and session.ismarket ? v_levelMidHighPer1 : na, title='PDMH 25%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "percentage" and session.ismarket ? v_levelMidLowPer1 : na,  title='PDML -25%', color=color.green, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "percentage" and session.ismarket ? v_levelMidLowPer2 : na,  title='PDML -50%', color=color.green, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "percentage" and session.ismarket ? v_levelMidLowPer3 : na,  title='PDML -75%', color=color.green, linewidth=1, style=plot.style_cross)

// fib levels from previous days high/low mid range
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidHighFib5 : na, title='PDMH FIB 78.6%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidHighFib4 : na, title='PDMH FIB 61.8%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidHighFib3 : na, title='PDMH FIB 50%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidHighFib2 : na, title='PDMH FIB 38.2%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidHighFib1 : na, title='PDMH FIB 23.6%', color=color.red, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidLowFib1 : na,  title='PDML FIB -23.6%', color=color.green, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidLowFib2 : na,  title='PDML FIB -38.2%', color=color.green, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidLowFib3 : na,  title='PDML FIB -50%', color=color.green, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidLowFib4 : na,  title='PDML FIB -61.8%', color=color.green, linewidth=1, style=plot.style_cross)
plot(i_showRangeLevels == "fib" and session.ismarket ? v_levelMidLowFib5 : na,  title='PDML FIB -78.6%', color=color.green, linewidth=1, style=plot.style_cross)

// </plots>

// <alerts>
// tbd
// </alerts>