Recursive Auto-Pitchfork [Trendoscope]
// This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © Trendoscope Pty Ltd
//                                       ░▒             
//                                  ▒▒▒   ▒▒      
//                              ▒▒▒▒▒     ▒▒      
//                      ▒▒▒▒▒▒▒░     ▒     ▒▒          
//                  ▒▒▒▒▒▒           ▒     ▒▒          
//             ▓▒▒▒       ▒        ▒▒▒▒▒▒▒▒▒▒▒  
//   ▒▒▒▒▒▒▒▒▒▒▒ ▒        ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒         
//   ▒  ▒       ░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░        
//   ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒▒▒▒▒▒▒         
//   ▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒                       
//    ▒▒▒▒▒         ▒▒▒▒▒▒▒                            
//                 ▒▒▒▒▒▒▒▒▒                           
//                ▒▒▒▒▒ ▒▒▒▒▒                          
//               ░▒▒▒▒   ▒▒▒▒▓      ████████╗██████╗ ███████╗███╗   ██╗██████╗  ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗
//              ▓▒▒▒▒     ▒▒▒▒      ╚══██╔══╝██╔══██╗██╔════╝████╗  ██║██╔══██╗██╔═══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝
//              ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒        ██║   ██████╔╝█████╗  ██╔██╗ ██║██║  ██║██║   ██║███████╗██║     ██║   ██║██████╔╝█████╗ 
//             ▒▒▒▒▒       ▒▒▒▒▒       ██║   ██╔══██╗██╔══╝  ██║╚██╗██║██║  ██║██║   ██║╚════██║██║     ██║   ██║██╔═══╝ ██╔══╝  
//            ▒▒▒▒▒         ▒▒▒▒▒      ██║   ██║  ██║███████╗██║ ╚████║██████╔╝╚██████╔╝███████║╚██████╗╚██████╔╝██║     ███████╗
//             ▒▒             ▒                        
//@version=5
indicator("Recursive Auto-Pitchfork [Trendoscope]", "RAPF [Trendoscope]", overlay = true, max_lines_count=500)
import HeWhoMustNotBeNamed/DrawingTypes/2 as dr
import HeWhoMustNotBeNamed/DrawingMethods/2
import HeWhoMustNotBeNamed/ZigzagTypes/5 as zg
import HeWhoMustNotBeNamed/ZigzagMethods/6
import HeWhoMustNotBeNamed/PitchforkTypes/2 as p
import HeWhoMustNotBeNamed/PitchforkMethods/2
import HeWhoMustNotBeNamed/utils/1 as ut

// import HeWhoMustNotBeNamed/Logger/1 as l
// var logger = l.Logger.new(minimumLevel = 'DEBUG')
// logger.init()

theme = input.string('Dark', title='Theme', options=['Light', 'Dark'], group='Generic Settings',
         tooltip='Chart theme settings. Line and label colors are generted based on the theme settings. If dark theme is selected, '+
         'lighter colors are used and if light theme is selected, darker colors are used.')
zigzagLength = input.int(13, step=5, minval=3, title='Length', group='Zigzag', tooltip='Zigzag length for level 0 zigzag')
depth = input.int(50, "Depth", step=25, maxval=500, group='Zigzag', tooltip='Zigzag depth refers to max number of pivots to show on chart')
useRealTimeBars = input.bool(true, 'Use Real Time Bars', group='Zigzag', tooltip = 'If enabled real time bars are used for calculation. Otherwise, only confirmed bars are used')

typeTooltip = 'Handle Type' +
                 '\n\andrews - Pivot A' +
                 '\n\tschiff - X of Pivot A and y from median of Pivot A and B' +
                 '\n\tmschiff - X and Y are median of Pivot A and Pivot B' +
             '\n\nNeck Type' +
                 '\n\tmedian - median of Pivot B and Pivot C' +
                 '\n\tinside - Pivot C'

pitchforkType = input.string("andrews", "Type", ["andrews", "schiff", "mschiff"], group="Pitchfork", inline="t")
neckType = input.string('median', '', ['median', 'inside'], group="Pitchfork", inline="t", tooltip=typeTooltip)

handle = pitchforkType=='andrews'?'regular': pitchforkType
inside = neckType == 'inside'

ratioFrom = input.float(0.25, 'Ratio', minval=0.0, maxval=0.5, group='Pitchfork', inline='r')
ratioTo = input.float(1, '', minval=0.5, maxval=1.618, group='Pitchfork', inline='r', tooltip='Range of ratio for which drawing pitchfork is allowed')
useConfirmedPivot = input.bool(true, 'Use Confirmed Pivots', group="Pitchfork", tooltip="If set to true, uses last confirmed pivot and ignores the current moving pivot")

includeRatio1 = input.bool(false, '',  inline='r1', group='Forks')
ratio1 = input.float(0.236, '', inline='r1', group='Forks')
color1 = input.color(#f77c80, '', inline='r1', group='Forks')

includeRatio2 = input.bool(false, '', inline='r1', group='Forks')
ratio2 = input.float(0.382, '', inline='r1', group='Forks')
color2 = input.color(#ffb74d, '', inline='r1', group='Forks')

includeRatio3 = input.bool(true, '',  inline='r2', group='Forks')
ratio3 = input.float(0.500, '', inline='r2', group='Forks')
color3 = input.color(#fff176, '', inline='r2', group='Forks')

includeRatio4 = input.bool(false, '', inline='r2', group='Forks')
ratio4 = input.float(0.618, '', inline='r2', group='Forks')
color4 = input.color(#81c784, '', inline='r2', group='Forks')

includeRatio5 = input.bool(false, '',  inline='r3', group='Forks')
ratio5 = input.float(0.786, '', inline='r3', group='Forks')
color5 = input.color(#42bda8, '', inline='r3', group='Forks')

includeRatio6 = input.bool(false, '', inline='r3', group='Forks')
ratio6 = input.float(0.886, '', inline='r3', group='Forks')
color6 = input.color(#4dd0e1, '', inline='r3', group='Forks')

includeRatio7 = input.bool(true, '',  inline='r4', group='Forks')
ratio7 = input.float(1.000, '', inline='r4', group='Forks')
color7 = input.color(#5b9cf6, '', inline='r4', group='Forks')

includeRatio8 = input.bool(false, '', inline='r4', group='Forks')
ratio8 = input.float(1.130, '', inline='r4', group='Forks')
color8 = input.color(#9575cd, '', inline='r4', group='Forks')

includeRatio9 = input.bool(false, '',  inline='r5', group='Forks')
ratio9 = input.float(1.272, '', inline='r5', group='Forks')
color9 = input.color(#ba68c8, '', inline='r5', group='Forks')

includeRatio10 = input.bool(false, '', inline='r5', group='Forks')
ratio10 = input.float(1.382, '', inline='r5', group='Forks')
color10 = input.color(#f06292, '', inline='r5', group='Forks')

includeRatio11 = input.bool(false, '',  inline='r6', group='Forks')
ratio11 = input.float(1.618, '', inline='r6', group='Forks')
color11 = input.color(#faa1a4, '', inline='r6', group='Forks')

includeRatio12 = input.bool(false, '', inline='r6', group='Forks')
ratio12 = input.float(2.000, '', inline='r6', group='Forks')
color12 = input.color(#4caf50, '', inline='r6', group='Forks')

extend = input.bool(true, "Extend", group="Display", tooltip = "Extend fork lines to right")
fill = input.bool(true, "Fill", group="Display", inline='f')
transparency = input.int(95, "Transparency", group="Display", inline='f', tooltip = "Fill Forkline with background color")

offset = useRealTimeBars? 0 : 1

indicators = matrix.new<float>()
indicatorNames = array.new<string>()

themeColors = ut.getColors(theme)
var zg.Zigzag zigzag = zg.Zigzag.new(zigzagLength, depth, offset)
zigzag.calculate(array.from(high, low), indicators, indicatorNames)

startIndex = useConfirmedPivot? 1:0

includes = array.from(includeRatio1, includeRatio2, includeRatio3, includeRatio4, includeRatio5, includeRatio6,
                         includeRatio7, includeRatio8, includeRatio9, includeRatio10, includeRatio11, includeRatio12)
ratios = array.from(ratio1, ratio2, ratio3, ratio4, ratio5, ratio6, ratio7, ratio8, ratio9, ratio10, ratio11, ratio12)
colors = array.from(color1, color2, color3, color4, color5, color6, color7, color8, color9, color10, color11, color12)

array<p.Fork> forks = array.new<p.Fork>()
for [i, include] in includes
	if(include)
		forks.push(p.Fork.new(ratios.get(i), colors.get(i), include))

p.PitchforkProperties properties = p.PitchforkProperties.new(forks, handle, inside)
p.PitchforkDrawingProperties dProperties = p.PitchforkDrawingProperties.new(extend, fill, transparency)

if(barstate.islast)
    var array<p.Pitchfork> pitchforks = array.new<p.Pitchfork>()
    pitchforks.clear()
    mlzigzag = zigzag
    while(mlzigzag.zigzagPivots.size() >= 3+startIndex)
        lineColor = themeColors.pop()
        themeColors.unshift(lineColor)

        p3 = mlzigzag.zigzagPivots.get(startIndex)
        p3Point = p3.point
        p2Point = mlzigzag.zigzagPivots.get(startIndex+1).point
        p1Point = mlzigzag.zigzagPivots.get(startIndex+2).point

        if (p3.ratio >= ratioFrom and p3.ratio <= ratioTo and p3Point.bar - p1Point.bar <500)
            dr.LineProperties lProperties = dr.LineProperties.new(color=lineColor)
            p.Pitchfork pitchFork = p.Pitchfork.new(p1Point, p2Point, p3Point, properties, dProperties, lProperties)
            drawing = pitchFork.createDrawing()
            drawing.draw()
            pitchforks.push(pitchFork)
        mlzigzag := mlzigzag.nextlevel()