Dual Dynamic Fibonacci Retracement — Long and Short Duration
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © StockJustice

//@version=5
indicator("Dual Dynamic Fibonacci Retracement Levels", shorttitle="Fib Levels", overlay=true)

// User-defined input for the lookback period
lookbackPeriod = input.int(title="Lookback Period", defval=50, minval=1)

// Calculate pivot high and pivot low
pivotHigh = ta.highest(high, lookbackPeriod)
pivotLow = ta.lowest(low, lookbackPeriod)

// Calculate the mid point
midPoint = (pivotHigh + pivotLow) / 2

// Determine trading position: above or below mid point
aboveMid = close > midPoint
belowMid = close < midPoint

// Calculate Fibonacci retracement levels based on trading position
level_236 = aboveMid ? pivotHigh - 0.236 * (pivotHigh - pivotLow) : pivotLow + 0.236 * (pivotHigh - pivotLow)
level_382 = aboveMid ? pivotHigh - 0.382 * (pivotHigh - pivotLow) : pivotLow + 0.382 * (pivotHigh - pivotLow)
level_50 = aboveMid ? pivotHigh - 0.5 * (pivotHigh - pivotLow) : pivotLow + 0.5 * (pivotHigh - pivotLow)
level_618 = aboveMid ? pivotHigh - 0.618 * (pivotHigh - pivotLow) : pivotLow + 0.618 * (pivotHigh - pivotLow)
level_786 = aboveMid ? pivotHigh - 0.786 * (pivotHigh - pivotLow) : pivotLow + 0.786 * (pivotHigh - pivotLow)
level_100 = aboveMid ? pivotLow : pivotHigh

// Find the last bar where a new pivot high or low was found
var int pivotBar = na
if high == pivotHigh or low == pivotLow
    pivotBar := bar_index

// Only plot the lines at the last pivot bar
var line l_236 = na
var line l_382 = na
var line l_50 = na
var line l_618 = na
var line l_786 = na
var line l_100 = na

// Define shift as a function of the lookback period
shift = input(0, title = "Left Line: Shift Left (Negative) or Right (Positive)")
extend = input(0, title = "Right Line: Shift Left (Negative) or Right (Positive)")

if not na(pivotBar)
    if na(l_236)
        l_236 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_236, x2=bar_index + extend, y2=level_236, color=color.red, width=1)
    else
        line.delete(l_236)
        l_236 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_236, x2=bar_index + extend, y2=level_236, color=color.red, width=1)
    if na(l_382)
        l_382 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_382, x2=bar_index + extend, y2=level_382, color=color.orange, width=1)
    else
        line.delete(l_382)
        l_382 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_382, x2=bar_index + extend, y2=level_382, color=color.orange, width=1)
    if na(l_50)
        l_50 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_50, x2=bar_index + extend, y2=level_50, color=color.yellow, width=1)
    else
        line.delete(l_50)
        l_50 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_50, x2=bar_index + extend, y2=level_50, color=color.yellow, width=1)
    if na(l_618)
        l_618 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_618, x2=bar_index + extend, y2=level_618, color=color.green, width=1)
    else
        line.delete(l_618)
        l_618 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_618, x2=bar_index + extend, y2=level_618, color=color.green, width=1)
    if na(l_786)
        l_786 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_786, x2=bar_index + extend, y2=level_786, color=color.blue, width=1)
    else
        line.delete(l_786)
        l_786 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_786, x2=bar_index + extend, y2=level_786, color=color.blue, width=1)
    if na(l_100)
        l_100 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_100, x2=bar_index + extend, y2=level_100, color=color.purple, width=1)
    else
        line.delete(l_100)
        l_100 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_100, x2=bar_index + extend, y2=level_100, color=color.purple, width=1)


// Variable for the "0" level line
var line l_0 = na

// Inside the if bar_index == pivotBar block
if not na(pivotBar)
    // Add these lines to plot the "0" level
    if na(l_0)
        l_0 := line.new(x1=bar_index - lookbackPeriod + shift, y1=aboveMid ? pivotHigh : pivotLow, x2=bar_index + extend, y2=aboveMid ? pivotHigh : pivotLow, color=color.white, width=1)
    else
        line.delete(l_0)
        l_0 := line.new(x1=bar_index - lookbackPeriod + shift, y1=aboveMid ? pivotHigh : pivotLow, x2=bar_index + extend, y2=aboveMid ? pivotHigh : pivotLow, color=color.white, width=1)




// User input to toggle the plotting of 0.114 and 0.886 levels
plotExtraLevels = input.bool(title="Plot 0.114 and 0.886 levels?", defval=false)

// Calculate additional Fibonacci retracement levels
level_114 = aboveMid ? pivotHigh - 0.114 * (pivotHigh - pivotLow) : pivotLow + 0.114 * (pivotHigh - pivotLow)
level_886 = aboveMid ? pivotHigh - 0.886 * (pivotHigh - pivotLow) : pivotLow + 0.886 * (pivotHigh - pivotLow)

// Initialize lines for the new levels
var line l_114 = na
var line l_886 = na

if not na(pivotBar) and plotExtraLevels
    // Add lines for the new levels
    if na(l_114)
        l_114 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_114, x2=bar_index + extend, y2=level_114, color=color.fuchsia, width=1)
    else
        line.delete(l_114)
        l_114 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_114, x2=bar_index + extend, y2=level_114, color=color.fuchsia, width=1)
    if na(l_886)
        l_886 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_886, x2=bar_index + extend, y2=level_886, color=color.fuchsia, width=1)
    else
        line.delete(l_886)
        l_886 := line.new(x1=bar_index - lookbackPeriod + shift, y1=level_886, x2=bar_index + extend, y2=level_886, color=color.fuchsia, width=1)





















// User input to toggle the plotting of the second set of levels
plotSecondSet = input.bool(false, title="Plot second set of levels?")


// User-defined input for the second lookback period
lookbackPeriod2 = input.int(title="Lookback Period 2", defval=14, minval=1)

// Define shift as a function of the lookback period
shift2 = input(0, title = "Second Left Line: Shift Left (Negative) or Right (Positive)")
extend2 = input(30, title = "Second Right Line: Shift Left (Negative) or Right (Positive)")

var float pivotHigh2 = na
var float pivotLow2 = na

// Calculate pivot high and pivot low for second set
if plotSecondSet
    pivotHigh2 := ta.highest(high, lookbackPeriod2)
    pivotLow2 := ta.lowest(low, lookbackPeriod2)

// Calculate the mid point for second set
midPoint2 = (pivotHigh2 + pivotLow2) / 2

// Determine trading position: above or below mid point for second set
aboveMid2 = close > midPoint2
belowMid2 = close < midPoint2

// Calculate Fibonacci retracement levels based on trading position for second set
level_236_2 = aboveMid2 ? pivotHigh2 - 0.236 * (pivotHigh2 - pivotLow2) : pivotLow2 + 0.236 * (pivotHigh2 - pivotLow2)
level_382_2 = aboveMid2 ? pivotHigh2 - 0.382 * (pivotHigh2 - pivotLow2) : pivotLow2 + 0.382 * (pivotHigh2 - pivotLow2)
level_50_2 = aboveMid2 ? pivotHigh2 - 0.5 * (pivotHigh2 - pivotLow2) : pivotLow2 + 0.5 * (pivotHigh2 - pivotLow2)
level_618_2 = aboveMid2 ? pivotHigh2 - 0.618 * (pivotHigh2 - pivotLow2) : pivotLow2 + 0.618 * (pivotHigh2 - pivotLow2)
level_786_2 = aboveMid2 ? pivotHigh2 - 0.786 * (pivotHigh2 - pivotLow2) : pivotLow2 + 0.786 * (pivotHigh2 - pivotLow2)
level_100_2 = aboveMid2 ? pivotLow2 : pivotHigh2

// Find the last bar where a new pivot high or low was found for second set
var int pivotBar2 = na
if high == pivotHigh2 or low == pivotLow2
    pivotBar2 := bar_index

// Initialize lines for second set
var line l_236_2 = na
var line l_382_2 = na
var line l_50_2 = na
var line l_618_2 = na
var line l_786_2 = na
var line l_100_2 = na

// Plotting lines for second set
if not na(pivotBar2)
    if na(l_236_2)
        l_236_2 := line.new(x1=bar_index + shift2, y1=level_236_2, x2=bar_index + extend2, y2=level_236_2, color=color.red, width=1)
    else
        line.delete(l_236_2)
        l_236_2 := line.new(x1=bar_index + shift2, y1=level_236_2, x2=bar_index + extend2, y2=level_236_2, color=color.red, width=1)
    if na(l_382_2)
        l_382_2 := line.new(x1=bar_index + shift2, y1=level_382_2, x2=bar_index + extend2, y2=level_382_2, color=color.orange, width=1)
    else
        line.delete(l_382_2)
        l_382_2 := line.new(x1=bar_index + shift2, y1=level_382_2, x2=bar_index + extend2, y2=level_382_2, color=color.orange, width=1)
    if na(l_50_2)
        l_50_2 := line.new(x1=bar_index + shift2, y1=level_50_2, x2=bar_index + extend2, y2=level_50_2, color=color.yellow, width=1)
    else
        line.delete(l_50_2)
        l_50_2 := line.new(x1=bar_index + shift2, y1=level_50_2, x2=bar_index + extend2, y2=level_50_2, color=color.yellow, width=1)
    if na(l_618_2)
        l_618_2 := line.new(x1=bar_index + shift2, y1=level_618_2, x2=bar_index + extend2, y2=level_618_2, color=color.green, width=1)
    else
        line.delete(l_618_2)
        l_618_2 := line.new(x1=bar_index + shift2, y1=level_618_2, x2=bar_index + extend2, y2=level_618_2, color=color.green, width=1)
    if na(l_786_2)
        l_786_2 := line.new(x1=bar_index + shift2, y1=level_786_2, x2=bar_index + extend2, y2=level_786_2, color=color.blue, width=1)
    else
        line.delete(l_786_2)
        l_786_2 := line.new(x1=bar_index + shift2, y1=level_786_2, x2=bar_index + extend2, y2=level_786_2, color=color.blue, width=1)
    if na(l_100_2)
        l_100_2 := line.new(x1=bar_index + shift2, y1=level_100_2, x2=bar_index + extend2, y2=level_100_2, color=color.purple, width=1)
    else
        line.delete(l_100_2)
        l_100_2 := line.new(x1=bar_index + shift2, y1=level_100_2, x2=bar_index + extend2, y2=level_100_2, color=color.purple, width=1)

// Variable for the "0" level line for the second set
var line l_0_2 = na

// Inside the if bar_index == pivotBar2 block
if not na(pivotBar2)
    // Add these lines to plot the "0" level for the second set
    if na(l_0_2)
        l_0_2 := line.new(x1=bar_index + shift2, y1=aboveMid2 ? pivotHigh2 : pivotLow2, x2=bar_index + extend2, y2=aboveMid2 ? pivotHigh2 : pivotLow2, color=color.white, width=1)
    else
        line.delete(l_0_2)
        l_0_2 := line.new(x1=bar_index + shift2, y1=aboveMid2 ? pivotHigh2 : pivotLow2, x2=bar_index + extend2, y2=aboveMid2 ? pivotHigh2 : pivotLow2, color=color.white, width=1)


// User input to toggle the plotting of 0.114 and 0.886 levels for second set

plotExtraLevels2 = input(false, title="Plot 0.114 and 0.886 levels for second set?") 

// Calculate additional Fibonacci retracement levels for second set
level_114_2 = aboveMid2 ? pivotHigh2 - 0.114 * (pivotHigh2 - pivotLow2) : pivotLow2 + 0.114 * (pivotHigh2 - pivotLow2)
level_886_2 = aboveMid2 ? pivotHigh2 - 0.886 * (pivotHigh2 - pivotLow2) : pivotLow2 + 0.886 * (pivotHigh2 - pivotLow2)

// Initialize lines for the new levels for second set
var line l_114_2 = na
var line l_886_2 = na

if not na(pivotBar2) and plotExtraLevels2
    if na(l_114_2)
        l_114_2 := line.new(x1=bar_index + shift2, y1=level_114_2, x2=bar_index + extend2, y2=level_114_2, color=color.fuchsia, width=1)
    else
        line.delete(l_114_2)
        l_114_2 := line.new(x1=bar_index + shift2, y1=level_114_2, x2=bar_index + extend2, y2=level_114_2, color=color.fuchsia, width=1)
    if na(l_886_2)
        l_886_2 := line.new(x1=bar_index + shift2, y1=level_886_2, x2=bar_index + extend2, y2=level_886_2, color=color.fuchsia, width=1)
    else
        line.delete(l_886_2)
        l_886_2 := line.new(x1=bar_index + shift2, y1=level_886_2, x2=bar_index + extend2, y2=level_886_2, color=color.fuchsia, width=1)
