Support and Resistance Levels and Zones [Quantigenics]
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Quantigenics
//@version=5
indicator("Support and Resistance Levels and Zones [Quantigenics]",overlay = true,max_labels_count = 500,max_boxes_count = 500)

/////////////////
//Inputs////////
///////////////
hoursOffsetInput = input.float(0.0, "Timezone offset (in hours)", minval = -12.0, maxval = 14.0, step = 0.5)

PivotCalcType       = input.string( "Classic pivots",title = "Pivot Calc Type" , options = ["Classic pivots","Traditional pivots","Camarilla pivots"], tooltip = "Pivot Calculation Type.")
PivotInterval       = input.string( "Daily",title = "Pivot Interval", options = ["Daily","Weekly","Monthly","Quarterly","Yearly"], tooltip = "Choose Interval.")


SR2LevelsCalcTime   = input(defval = "00:00",title = "SR2 Levels Calc Time")
PlotZones           = input.bool(defval = true,title = "Plot Zones")
ShowGrayLines       = input.bool(defval = false,title = "Show Gray Lines")
FTPLevels           = input.bool(defval = false,title = "Show FTP Levels")
SR2Levels           = input.bool(defval = false,title = "SR2 Levels")
AdjustTheLabels     = input.string("Left","Adjust Labels",["Left","Center","Right"])
bool ShowPivotLabels             = input( defval = true,title = "Show Pivot Labels", tooltip = "Enter 1 to show text labels for the pivot levels.  Enter 0 to not show text labels."  ) 
bool ShowCurrentPeriodLabelsOnly = input( defval = true,title = "Show Current Period Labels Only", tooltip = "Enter 1 to show text labels for the current period only.  Enter 0 to show text labels for all pivot levels.")
bool ShowPriceLevelsInLabels     = input( defval = true,title = "Show Price Levels In Labels", tooltip = "Enter 1 to include the pivot price values in the text labels.  Enter 0 to not include pivot price values." ) 
bool ShowPivotIntervalInLabels   = input( defval = true,title = "Show Pivot Interval In Labels",tooltip = "Enter 1 to show the pivot interval in the text labels.  Enter 0 to not show the pivot interval." ) 

float PercentTransparency   = input( defval = 0,title = "Percent Transparency", tooltip = "Percentage Transparency.  Enter the desired percentage transparency of the text labels (0 = solid, 100 = clear)." )
R5Color                     = input( defval = color.red, title = "R5 Color", tooltip = "Enter the color to use for the R5 pivot plot and associated text label."  )
R4Color                     = input( defval = color.rgb(255, 123, 0),   title = "R4 Color",  tooltip = "Enter the color to use for the R4 pivot plot and associated text label.") 
R3Color                     = input( defval = color.rgb(255, 99, 71),   title = "R3 Color",  tooltip = "Enter the color to use for the R3 pivot plot and associated text label.") 
R2Color                     = input( defval = color.rgb(189, 105, 66),  title = "R2 Color",  tooltip = "Enter the color to use for the R2 pivot plot and associated text label.") 
R1Color                     = input( defval = color.rgb(255, 123, 0),   title = "R1 Color",  tooltip = "Enter the color to use for the R1 pivot plot and associated text label.") 

PivotColor                  = input( defval = color.rgb(30, 144, 255), title = "Pivot Color", tooltip = "Enter the color to use for the pivot point plot and associated text label." ) 
S1Color                     = input( defval = color.rgb(85, 107, 47), title = "S1 Color", tooltip = "Enter the color to use for the S1 pivot plot and associated text label.") 
S2Color                     = input( defval = color.rgb(128, 128, 0), title = "S2 Color", tooltip = "Enter the color to use for the S2 pivot plot and associated text label.") 
S3Color                     = input( defval = color.rgb(107, 142, 35), title = "S3 Color", tooltip = "Enter the color to use for the S3 pivot plot and associated text label.") 
S4Color                     = input( defval = color.rgb(55,79,47), title = "S4 Color", tooltip = "Enter the color to use for the S4 pivot plot and associated text label.") 
S5Color                     = input( defval = color.rgb(0, 128, 128), title = "S5 Color", tooltip = "Enter the color to use for the S5 pivot plot and associated text label.") 

bool ShowR5                      = input( defval = true, title = "Show R5", tooltip = "Enter 1 to plot the R5 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowR4                      = input( defval = true, title = "Show R4", tooltip = "Enter 1 to plot the R4 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowR3                      = input( defval = true, title = "Show R3", tooltip = "Enter 1 to plot the R3 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowR2                      = input( defval = true, title = "Show R2", tooltip = "Enter 1 to plot the R2 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowR1                      = input( defval = true, title = "Show R1", tooltip = "Enter 1 to plot the R1 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowPP                      = input( defval = true, title = "Show Main Pivot", tooltip = "Enter 1 to plot the pivot point level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowS1                      = input( defval = true, title = "Show S1", tooltip = "Enter 1 to plot the S1 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowS2                      = input( defval = true, title = "Show S2", tooltip = "Enter 1 to plot the S2 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowS3                      = input( defval = true, title = "Show S3", tooltip = "Enter 1 to plot the S3 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowS4                      = input( defval = true, title = "Show S4", tooltip = "Enter 1 to plot the S4 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")
bool ShowS5                      = input( defval = true, title = "Show S5", tooltip = "Enter 1 to plot the S5 pivot level and draw the associated text label (if text labels are set to show) enter 0 to not plot the pivot value.")

float TextLabelFontSize         = input(defval = 8.0,title = "Text Label Font Size", tooltip = "Enter the font size for the text labels on the lines")
var isdaily = (PivotInterval=="Daily")
///////////////////
//Used Variables//
/////////////////
var TRENDLINE_LEVEL_KEY = "TLLevel" 
var TRENDLINE_COLOR_KEY = "TLColor" 
var R5_KEY = "R5" 
var R4_KEY = "R4" 
var R3_KEY = "R3" 
var R2_KEY = "R2" 
var R1_KEY = "R1" 
var PP_KEY = "MP" 
var S1_KEY = "S1" 
var S2_KEY = "S2" 
var S3_KEY = "S3" 
var S4_KEY = "S4" 
var S5_KEY = "S5" 
var DATA_LOAD_FAIL_const = "Required data failed to load." 
type Times
    int Year
    int Month
type psarr
    Times Time
    float High
    float Low
    float Close
type PriceSeriesProvider
    int Count
    array<psarr> ps
// TokenList TokenListOfLevels = NULL 
// Vector CurrentTextLabelVector = NULL 
// Vector AllTextLabelsVector = NULL 
// Vector TrendlineVector = NULL 
// Vector TomorrowTextLabelVector = NULL 
// Dictionary DOColorDict = NULL  
// Dictionary PlotColorDict = NULL 
type Bar
    float H
    float C
    float L
    float T
var PivotsPSP = PriceSeriesProvider.new(0,array.new<psarr>(0))
var customPSP = PriceSeriesProvider.new(0,array.new<psarr>(0))

// QuotesProvider QP1 = NULL 
// ChartingHost ChartingHost1 = NULL 
var localtimezone = "GMT+"+str.tostring(hoursOffsetInput)
bool InputsAreOkay = true 
bool RealTime = false 
bool InAChart = true //todo
bool AllowTransparentPlots = true 
int DecimalPlaces = 0 
int BT = 0 
bool OkToCalc = false 
int PSPIndexOffset = 0 
string PivotIntervalString = "" 
bool PivotsPSPIsLoaded = false 

type colors
    color PPPlotColor  
    color S1PlotColor   
    color S2PlotColor   
    color S3PlotColor  
    color S4PlotColor  
    color S5PlotColor  
    color R1PlotColor   
    color R2PlotColor  
    color R3PlotColor   
    color R4PlotColor  
    color R5PlotColor  
type Boxes
    box PPBox  
    box S1Box   
    box S2Box   
    box S3Box    
    box R1Box   
    box R2Box  
    box R3Box   
type Lines
    line PPLine
    line S1Line
    line S2Line
    line S3Line
    line R1Line
    line R2Line
    line R3Line
colors PSPColor = colors.new(PivotColor,S1Color,S2Color,S3Color,S4Color,S5Color,R1Color,R2Color,R3Color,R4Color,R5Color)
colors CustomColor = colors.new(PivotColor,S1Color,S2Color,S3Color,S4Color,S5Color,R1Color,R2Color,R3Color,R4Color,R5Color)

getColor(color cl, int tr = 70)=>
    color.rgb(color.r(cl),color.g(cl),color.b(cl),transp = tr)

var ZoneColor = colors.new(getColor(PivotColor),getColor(S1Color),getColor(S2Color),getColor(S3Color),getColor(S4Color),getColor(S5Color),getColor(R1Color),getColor(R2Color),getColor(R3Color),getColor(R4Color),getColor(R5Color))
var Box = Boxes.new(na,na,na,na,na,na,na)
var Line = Lines.new(na,na,na,na,na,na,na)
var LabelS1 = label.new(0,0,"")
var LabelS2 = label.new(0,0,"")
var LabelS3 = label.new(0,0,"")
var LabelS4 = label.new(0,0,"")
var LabelS5 = label.new(0,0,"")
var LabelR1 = label.new(0,0,"")
var LabelR2 = label.new(0,0,"")
var LabelR3 = label.new(0,0,"")
var LabelR4 = label.new(0,0,"")
var LabelR5 = label.new(0,0,"")
var LabelPP = label.new(0,0,"")

type Pivots
    float S1 
    float S2 
    float S3 
    float S4 
    float S5
    float R1
    float R2 
    float R3 
    float R4 
    float R5 
    float PP
type Tom 
    float S1Tom
    float S2Tom 
    float S3Tom
    float S4Tom
    float S5Tom
    float R1Tom 
    float R2Tom 
    float R3Tom
    float R4Tom
    float R5Tom
    float PPTom 
var tom = Tom.new( 0,0,0,0,0,0,0,0,0,0,0)
var customtom = Tom.new( 0,0,0,0,0,0,0,0,0,0,0)

var pivs = Pivots.new( 0,0,0,0,0,0,0,0,0,0,0)
var customPiv = Pivots.new( 0,0,0,0,0,0,0,0,0,0,0)
int TransparencyValue = 255 
int ReuseIndex = 0 
bool TomorrowsPivotsShowing = true

/////////////////
//Pivot Calcs///
///////////////
GetQuarterForDateTime(Times tim)=>
    int ReturnQuarter = 0
    if(time("M")<4)
        ReturnQuarter := 1
    else if(time("M")<7)
        ReturnQuarter:= 2
    else if(time("M")< 10)
        ReturnQuarter:= 3
    else 
        ReturnQuarter:= 4

    ReturnQuarter
CalcQuarterlyPivots( PriceSeriesProvider PSP, int iYear,int iQuarter )=>

    float PeriodHigh = -1
    float PeriodLow = 10000000
    float PeriodClose = -1
    int LastMonth = -1
    int NumMonthsFound = 0
    for Counter = 0 to PSP.Count - 1
        if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Year == iYear and GetQuarterForDateTime( array.get(PSP.ps,PSP.Count - 1 - Counter).Time ) == iQuarter) 
            NumMonthsFound += 1
            
            if (array.get(PSP.ps,PSP.Count - 1-Counter).High > PeriodHigh) 
                PeriodHigh := array.get(PSP.ps,PSP.Count - 1-Counter).High
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Low < PeriodLow)
                PeriodLow := array.get(PSP.ps,PSP.Count - 1-Counter).Low
            
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Month > LastMonth )
                PeriodClose := array.get(PSP.ps,PSP.Count - 1-Counter).Close
                LastMonth := array.get(PSP.ps,PSP.Count - 1-Counter).Time.Month

    bool ret = (PeriodClose != 0 and PeriodHigh != -1 and PeriodLow != 10000000 and NumMonthsFound == 3)
    ret

CalcYearlyPivots( PriceSeriesProvider PSP, int tempYear )=>

    float PeriodHigh = -1
    float PeriodLow = 10000000
    float PeriodClose = 0
    int NumMonthsFound = 0
    for Counter = 0 to PSP.Count - 1

        if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Year == tempYear )
            NumMonthsFound += 1
            
            if (array.get(PSP.ps,PSP.Count - 1-Counter).High > PeriodHigh)
                PeriodHigh := array.get(PSP.ps,PSP.Count - 1-Counter).High
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Low < PeriodLow)
                PeriodLow := array.get(PSP.ps,PSP.Count - 1-Counter).Low
        
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Month == 12 )
                PeriodClose := array.get(PSP.ps,PSP.Count - 1-Counter).Close
        else if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Year == tempYear - 1)
            break
    
    PeriodClose != 0 and PeriodHigh != -1 and PeriodLow != 10000000 and NumMonthsFound == 12


CalcPivotLevels(float iHigh,float iLow,float iClose, Pivots piv_)=>
    if (not (iHigh == 0 or iLow == 0 or iClose == 0) )
        switch ( PivotCalcType )
            "Traditional pivots"=> 
                piv_.PP := ( iHigh + iLow + iClose ) / 3
                
                piv_.R1 := piv_.PP * 2 - iLow
                piv_.R2 := piv_.PP + iHigh - iLow
                piv_.R3 := piv_.PP * 2 + ( iHigh - 2 * iLow )
                piv_.R4 := piv_.PP * 3 + ( iHigh - 3 * iLow )
                piv_.R5 := piv_.PP * 4 + ( iHigh - 4 * iLow )
                
                piv_.S1 := piv_.PP * 2 - iHigh
                piv_.S2 := piv_.PP - iHigh + iLow
                piv_.S3 := piv_.PP * 2 - ( 2 * iHigh - iLow )
                piv_.S4 := piv_.PP * 3 - ( 3 * iHigh - iLow )
                piv_.S5 := piv_.PP * 4 - ( 4 * iHigh - iLow )    
            
            "Camarilla pivots"=> 
                piv_.PP := ( iHigh + iLow + iClose ) / 3
                
                piv_.R1 := iClose + ( iHigh - iLow ) * 1.1 / 12
                piv_.R2 := iClose + ( iHigh - iLow ) * 1.1 / 6
                piv_.R3 := iClose + ( iHigh - iLow ) * 1.1 / 4
                piv_.R4 := iClose + ( iHigh - iLow ) * 1.1 / 2
                
                piv_.S1 := iClose - ( iHigh - iLow ) * 1.1 / 12 
                piv_.S2 := iClose - ( iHigh - iLow ) * 1.1 / 6
                piv_.S3 := iClose - ( iHigh - iLow ) * 1.1 / 4
                piv_.S4 := iClose - ( iHigh - iLow ) * 1.1 / 2
            
            =>
                piv_.PP := ( iHigh + iLow + iClose ) / 3
                
                piv_.R1 := piv_.PP * 2 - iLow
                piv_.R2 := piv_.PP + iHigh - iLow
                piv_.R3 := piv_.R2 + iHigh - iLow
                
                piv_.S1 := piv_.PP * 2 - iHigh
                piv_.S2 := piv_.PP - iHigh + iLow
                piv_.S3 := piv_.S2 - iHigh + iLow
CalculateLevels()=>
    // if(PivotInterval == "Quarterly")
    //     if (GetQuarterForDateTime(Times.new(year,month)) == 1) 
    //         iy = year - 1
    //         CalcQuarterlyPivots( PivotsPSP, iy, 4 )
    //     else
    //         gqf = GetQuarterForDateTime(Times.new(year,month) ) - 1
    //         CalcQuarterlyPivots( PivotsPSP, year, gqf)
    // else if(PivotInterval == "Yearly")
    //     CalcYearlyPivots( PivotsPSP, year - 1 )
    // else
    CalcPivotLevels( array.get(PivotsPSP.ps,PivotsPSP.Count - 1-PSPIndexOffset).High, array.get(PivotsPSP.ps,PivotsPSP.Count - 1-PSPIndexOffset).Low, array.get(PivotsPSP.ps,PivotsPSP.Count -  1-PSPIndexOffset).Close,pivs)
//
//pivot calcs for next period


CalcPivotLevelsForTomorrow(float iHigh, float iLow, float iClose, Tom tm )=>
    if (not (iHigh == 0 or iLow == 0 or iClose == 0)) 
        switch ( PivotCalcType )
            "Traditional pivots"=>
                tm.PPTom := ( iHigh + iLow + iClose ) / 3
                
                tm.R1Tom := tm.PPTom * 2 - iLow
                tm.R2Tom := tm.PPTom + iHigh - iLow
                tm.R3Tom := tm.PPTom * 2 + ( iHigh - 2 * iLow )
                tm.R4Tom := tm.PPTom * 3 + ( iHigh - 3 * iLow )
                tm.R5Tom := tm.PPTom * 4 + ( iHigh - 4 * iLow )
                
                tm.S1Tom := tm.PPTom * 2 - iHigh
                tm.S2Tom := tm.PPTom - iHigh + iLow
                tm.S3Tom := tm.PPTom * 2 - ( 2 * iHigh - iLow )
                tm.S4Tom := tm.PPTom * 3 - ( 3 * iHigh - iLow )
                tm.S5Tom := tm.PPTom * 4 - ( 4 * iHigh - iLow )
            
            "Camarilla pivots"=>  
                tm.PPTom := ( iHigh + iLow + iClose ) / 3
                
                tm.R1Tom := iClose + ( iHigh - iLow ) * 1.1 / 12
                tm.R2Tom := iClose + ( iHigh - iLow ) * 1.1 / 6
                tm.R3Tom := iClose + ( iHigh - iLow ) * 1.1 / 4
                tm.R4Tom := iClose + ( iHigh - iLow ) * 1.1 / 2
                
                tm.S1Tom := iClose - ( iHigh - iLow ) * 1.1 / 12 
                tm.S2Tom := iClose - ( iHigh - iLow ) * 1.1 / 6
                tm.S3Tom := iClose - ( iHigh - iLow ) * 1.1 / 4
                tm.S4Tom := iClose - ( iHigh - iLow ) * 1.1 / 2
                    
            =>
                tm.PPTom := ( iHigh + iLow + iClose ) / 3
                
                tm.R1Tom := tm.PPTom * 2 - iLow
                tm.R2Tom := tm.PPTom + iHigh - iLow
                tm.R3Tom := tm.R2Tom + iHigh - iLow
                
                tm.S1Tom := tm.PPTom * 2 - iHigh
                tm.S2Tom := tm.PPTom - iHigh + iLow
                tm.S3Tom := tm.S2Tom - iHigh + iLow 
CalcQuarterlyPivotsForTomorrow( PriceSeriesProvider PSP, int iYear, int iQuarter )=>
    float PeriodHigh = 10000000
    float PeriodLow = 10000000
    float PeriodClose = -1
    int LastMonth = -1
    int NumMonthsFound = 0
    for Counter = 0 to PSP.Count - 1
        if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Year == iYear and true)// GetQuarterForDateTime( array.get(PSP.ps,PSP.Count - 1-Counter).Time ) == iQuarter) 
            NumMonthsFound += 1
            if (array.get(PSP.ps,PSP.Count - 1-Counter).High > PeriodHigh)
                PeriodHigh := array.get(PSP.ps,PSP.Count - 1-Counter).High
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Low < PeriodLow )
                PeriodLow := array.get(PSP.ps,PSP.Count - 1-Counter).Low
            
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Month > LastMonth)
                PeriodClose := array.get(PSP.ps,PSP.Count - 1-Counter).Close
                LastMonth := array.get(PSP.ps,PSP.Count - 1-Counter).Time.Month   

    CalcPivotLevelsForTomorrow( PeriodHigh, PeriodLow, PeriodClose,tom )
    
    PeriodClose != 0 and PeriodHigh != -1 and PeriodLow != 10000000 and NumMonthsFound == 3
CalcYearlyPivotsForTomorrow( PriceSeriesProvider PSP, int iYear )=>
    float PeriodHigh = -1
    float PeriodLow = 10000000
    float PeriodClose = 0
    int NumMonthsFound = 0  
    
    for Counter = 0 to PSP.Count - 1
        if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Year == iYear) 
            NumMonthsFound += 1
            
            if (array.get(PSP.ps,PSP.Count - 1-Counter).High > PeriodHigh) 
                PeriodHigh := array.get(PSP.ps,PSP.Count - 1-Counter).High
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Low < PeriodLow)
                PeriodLow := array.get(PSP.ps,PSP.Count - 1-Counter).Low
            if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Month == 12) 
                PeriodClose := array.get(PSP.ps,PSP.Count - 1-Counter).Close

        else if (array.get(PSP.ps,PSP.Count - 1-Counter).Time.Year == iYear - 1)
            break

    CalcPivotLevelsForTomorrow( PeriodHigh, PeriodLow, PeriodClose,tom )
    
    PeriodClose != 0 and PeriodHigh != -1 and PeriodLow != 10000000 and NumMonthsFound == 12
CalculateLevelsForTomorrow()=>
    // if(PivotInterval == "Quarterly")
    //     if (GetQuarterForDateTime(Times.new(year,month) ) == 1)
    //         CalcQuarterlyPivotsForTomorrow( PivotsPSP, year - 1, 4 )
    //     else
    //         CalcQuarterlyPivotsForTomorrow( PivotsPSP, year, GetQuarterForDateTime(Times.new(year,month) ) - 1 )
    // else if(PivotInterval == "Yearly")    
    //     CalcYearlyPivotsForTomorrow( PivotsPSP, year - 1 )
    // else
    CalcPivotLevelsForTomorrow( array.get(PivotsPSP.ps,PivotsPSP.Count  - 1).High, array.get(PivotsPSP.ps,PivotsPSP.Count  - 1).Low, array.get(PivotsPSP.ps,PivotsPSP.Count  - 1).Close,tom )

/////////////////
//Helpers misc//
///////////////
ShowPivotLevel( string pPivotLevel )=>
    ShowLevel = false
    switch ( pPivotLevel )
        R5_KEY=> 
            ShowLevel := ShowR5 and PivotCalcType == "Traditional pivots" 
            
        R4_KEY=> 
            ShowLevel := ShowR4 and PivotCalcType != "Classic pivots"  
            
        R3_KEY=>
            ShowLevel := ShowR3
            
        R2_KEY=>
            ShowLevel := ShowR2
            
        R1_KEY=> 
            ShowLevel := ShowR1
            
        PP_KEY=> 
            ShowLevel := PivotCalcType != "Camarilla pivots" and ShowPP
            
        S1_KEY=> 
            ShowLevel := ShowS1
            
        S2_KEY=>
            ShowLevel := ShowS2
            
        S3_KEY=> 
            ShowLevel := ShowS3
            
        S4_KEY=> 
            ShowLevel := ShowS4 and PivotCalcType != "Classic pivots" 
            
        S5_KEY=> 
            ShowLevel := ShowS5 and PivotCalcType == "Traditional pivots" 
            
        => 
            ShowLevel := false
    
    
    ShowLevel

setUpBox(box b, float x, float y, color cl)=>
    box.set_right(b, right = bar_index) 
    box.set_bottom(b, bottom = math.min(x,y))
    box.set_top(b,top = math.max(x,y)) 
    box.set_bgcolor(b,getColor(cl))

setTransparency(colors cc)=>
    cc.PPPlotColor := color.rgb(255, 255, 255, 100)
    cc.S1PlotColor := color.rgb(255, 255, 255, 100) 
    cc.S2PlotColor := color.rgb(255, 255, 255, 100) 
    cc.S3PlotColor := color.rgb(255, 255, 255, 100)
    cc.S4PlotColor := color.rgb(255, 255, 255, 100)
    cc.S5PlotColor := color.rgb(255, 255, 255, 100)
    cc.R1PlotColor := color.rgb(255, 255, 255, 100) 
    cc.R2PlotColor := color.rgb(255, 255, 255, 100)
    cc.R3PlotColor := color.rgb(255, 255, 255, 100) 
    cc.R4PlotColor := color.rgb(255, 255, 255, 100)
    cc.R5PlotColor := color.rgb(255, 255, 255, 100)



////////////////
//Main Code////
//////////////
// Function to extract hours and minutes from a time string
getHoursAndMinutes(_str) =>
    // Split the string into an array using ":" as the separator
    time_array = str.split(_str, ":")
    // Extract the hours and minutes from the array
    hours = str.tonumber(array.get(time_array,0))
    minutes = str.tonumber(array.get(time_array,1))
    // Return the extracted values
    [hours, minutes]

// Extract hours and minutes from the sample string
[extracted_hours, extracted_minutes] = getHoursAndMinutes(SR2LevelsCalcTime)

Bar dailyBar=Bar.new(request.security(syminfo.tickerid,"D",high[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"D",close[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"D",low[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"D",time[1],barmerge.gaps_off,barmerge.lookahead_on))
Bar weaklyBar=Bar.new(request.security(syminfo.tickerid,"W",high[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"W",close[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"W",low[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"W",time[1],barmerge.gaps_off,barmerge.lookahead_on))
Bar monthlyBar=Bar.new(request.security(syminfo.tickerid,"M",high[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"M",close[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"M",low[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"M",time[1],barmerge.gaps_off,barmerge.lookahead_on))
Bar quorterlyBar=Bar.new(request.security(syminfo.tickerid,"3M",high[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"3M",close[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"3M",low[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"3M",time[1],barmerge.gaps_off,barmerge.lookahead_on))
Bar yearlyBar=Bar.new(request.security(syminfo.tickerid,"12M",high[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"12M",close[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"12M",low[1],barmerge.gaps_off,barmerge.lookahead_on),request.security(syminfo.tickerid,"12M",time[1],barmerge.gaps_off,barmerge.lookahead_on))
color dgray = color.gray
if(hour(time,localtimezone)==extracted_hours and minute(time,localtimezone)==extracted_minutes)
    dgray := color.rgb(255, 255, 255, 100)

Init(PriceSeriesProvider PSP, PriceSeriesProvider CPSP)=>
    var changed = false
    switch(PivotInterval)
        "Daily"=>
            if(dailyBar.T!=dailyBar.T[1])
                array.push(PSP.ps,psarr.new(Times.new(year,month),dailyBar.H,dailyBar.L,dailyBar.C))
                PSP.Count+= 1
            else if(PSP.Count-1>0)
                pp = psarr.new(Times.new(year,month),dailyBar.H,dailyBar.L,dailyBar.C)
                array.set(PSP.ps,PSP.Count-1,pp)
            if(hour(time,localtimezone)==extracted_hours and minute(time,localtimezone)==extracted_minutes)
                array.push(CPSP.ps,psarr.new(Times.new(year,month),high ,low,dailyBar.C))
                CPSP.Count+= 1
                setTransparency(CustomColor)
                
            else if(CPSP.Count-1>0)
                hg = array.get(CPSP.ps,CPSP.Count-1).High  
                lg = array.get(CPSP.ps,CPSP.Count-1).Low  
                pp = psarr.new(Times.new(year,month),high>hg?high:hg,lg<low?lg:low,close)
                array.set(CPSP.ps,CPSP.Count-1,pp)   
            
        "Weekly"=>
            if(weaklyBar.T!=weaklyBar.T[1] )
                array.push(PSP.ps,psarr.new(Times.new(year,month),weaklyBar.H,weaklyBar.L,weaklyBar.C))
                PSP.Count+= 1
            else if(PSP.Count-1>0)
                pp = psarr.new(Times.new(year,month),weaklyBar.H,weaklyBar.L,weaklyBar.C)
                array.set(PSP.ps,PSP.Count-1,pp)
        "Monthly"=>
            if(monthlyBar.T!=monthlyBar.T[1])
                array.push(PSP.ps,psarr.new(Times.new(year,month),monthlyBar.H,monthlyBar.L,monthlyBar.C))
                PSP.Count+= 1
            else if(PSP.Count-1>0)
                pp = psarr.new(Times.new(year,month),monthlyBar.H,monthlyBar.L,monthlyBar.C)
                array.set(PSP.ps,PSP.Count-1,pp)
        "Quarterly"=>
            if(quorterlyBar.T!=quorterlyBar.T[1])
                array.push(PSP.ps,psarr.new(Times.new(year,month),quorterlyBar.H,quorterlyBar.L,quorterlyBar.C))
                PSP.Count+= 1
            else if(PSP.Count-1>0)
                pp = psarr.new(Times.new(year,month),quorterlyBar.H,quorterlyBar.L,quorterlyBar.C)
                array.set(PSP.ps,PSP.Count-1,pp)
        "Yearly"=>
            if(yearlyBar.T!=yearlyBar.T[1])
                array.push(PSP.ps,psarr.new(Times.new(year,month),yearlyBar.H,yearlyBar.L,yearlyBar.C))
                PSP.Count+= 1
            else if(PSP.Count-1>0)
                pp = psarr.new(Times.new(year,month),yearlyBar.H,yearlyBar.L,yearlyBar.C)
                array.set(PSP.ps,PSP.Count-1,pp)
    true
customCalc(float PC,float PH,float PL,Tom tm)=>
    tm.PPTom := ( PC + PH + PL ) / 3
    tm.R1Tom := 2 * tm.PPTom - PL
    tm.R2Tom := tm.PPTom + PH - PL
    tm.R3Tom := tm.R2Tom + PH - PL
    tm.S1Tom := 2 * tm.PPTom - PH
    tm.S2Tom := tm.PPTom - PH + PL
    tm.S3Tom := tm.S2Tom - PH + PL


Init(PivotsPSP,customPSP)
if(isdaily and PlotZones and dailyBar.T!=dailyBar.T[1] )
    bgc=color.red
    Box := Boxes.new(box.new(bar_index,dailyBar.H,bar_index,dailyBar.L,bgcolor = bgc,border_width = 0), box.new(bar_index,dailyBar.H,bar_index,dailyBar.L,bgcolor = bgc,border_width = 0),box.new(bar_index,dailyBar.H,bar_index,dailyBar.L,bgcolor = bgc,border_width = 0),box.new(bar_index,dailyBar.H,bar_index,dailyBar.L,bgcolor = bgc,border_width = 0),box.new(bar_index,dailyBar.H,bar_index,dailyBar.L,bgcolor = bgc,border_width = 0), box.new(bar_index,dailyBar.H,bar_index,dailyBar.L,bgcolor = bgc,border_width = 0),box.new(bar_index,dailyBar.H,bar_index,dailyBar.L,bgcolor = bgc,border_width = 0))
    Line:= Lines.new(line.new(bar_index,0,bar_index,0),line.new(bar_index,0,bar_index,0),line.new(bar_index,0,bar_index,0),line.new(bar_index,0,bar_index,0),line.new(bar_index,0,bar_index,0),line.new(bar_index,0,bar_index,0),line.new(bar_index,0,bar_index,0))       


if true//(BarDateTime > PivotsPSP.Time[0])//todo
    PSPIndexOffset := 0 
else
    PSPIndexOffset := 1
// if (not OkToCalc) 
//     switch (PivotInterval)
//         "Quarterly"=>
//             OkToCalc := PivotsPSP.Count > 3
//         "Yearly"=>
//             OkToCalc := PivotsPSP.Count > 12
//         =>
//             OkToCalc := PivotsPSP.Count > 1

if (PivotsPSP.Count > 1) 
    CalculateLevels()
    CalculateLevelsForTomorrow()

if(isdaily and customPSP.Count>1)
    customCalc(array.get(customPSP.ps,customPSP.Count-2).Close,array.get(customPSP.ps,customPSP.Count-2).High,array.get(customPSP.ps,customPSP.Count-2).Low,customtom)


// when new pivot levels are calculated, we need to create text labels for the new
// pivot levels and set plot colors to transparent to eliminate connector lines 
// from the prior pivot levels to the new pivot levels
setUpLine(line l,float y,color cl)=>
    line.set_color(l,cl)
    line.set_x2(l,bar_index)
    line.set_y1(l,y)
    line.set_y2(l,y)
makest(string st,float pr)=>
    string s = st
    if(ShowPivotIntervalInLabels)  
        s+=" ("
        s+= str.substring(PivotInterval,0,1)
        s+=") "
    if(ShowPriceLevelsInLabels)
        s+=str.tostring(pr,".##")
    s

var labelStartPlace = 0
var label_exist = false
if (InAChart and pivs.PP != 0 and ( pivs.PP != pivs.PP[1] or pivs.R1 != pivs.R1[1] or pivs.S1 != pivs.S1[1] ))
    setTransparency(PSPColor)
    if (ShowPivotLabels)
        if(ShowCurrentPeriodLabelsOnly)
            label.delete(LabelS1 )
            label.delete(LabelS2 )
            label.delete(LabelS3 )
            label.delete(LabelS4 )
            label.delete(LabelS5 )
            label.delete(LabelR1 )
            label.delete(LabelR2 )
            label.delete(LabelR3 )
            label.delete(LabelR4 )
            label.delete(LabelR5 )
            label.delete(LabelPP )
        labelStartPlace := bar_index
        label_exist     := true
        if(ShowPivotLevel( S1_KEY ))
            LabelS1 := label.new(bar_index,tom.S1Tom,makest("S1",tom.S1Tom),textcolor = color.white,color = S1Color)
        if(ShowPivotLevel( S2_KEY ))
            LabelS2 := label.new(bar_index,tom.S2Tom,makest("S2",tom.S2Tom),textcolor = color.white,color = S2Color)
        if(ShowPivotLevel( S3_KEY ))
            LabelS3 := label.new(bar_index,tom.S3Tom,makest("S3",tom.S3Tom),textcolor = color.white,color = S3Color)
        if(ShowPivotLevel( S4_KEY ))
            LabelS4 := label.new(bar_index,tom.S4Tom,makest("S4",tom.S4Tom),textcolor = color.white,color = S4Color)
        if(ShowPivotLevel( S5_KEY ))
            LabelS5 := label.new(bar_index,tom.S5Tom,makest("S5",tom.S5Tom),textcolor = color.white,color = S5Color)
        if(ShowPivotLevel( R1_KEY ))
            LabelR1 := label.new(bar_index,tom.R1Tom,makest("R1",tom.R1Tom),textcolor = color.white,color = R1Color)
        if(ShowPivotLevel( R2_KEY ))
            LabelR2 := label.new(bar_index,tom.R2Tom,makest("R2",tom.R2Tom),textcolor = color.white,color = R2Color)
        if(ShowPivotLevel( R3_KEY ))
            LabelR3 := label.new(bar_index,tom.R3Tom,makest("R3",tom.R3Tom),textcolor = color.white,color = R3Color)
        if(ShowPivotLevel( R4_KEY ))
            LabelR4 := label.new(bar_index,tom.R4Tom,makest("R4",tom.R4Tom),textcolor = color.white,color = R4Color)
        if(ShowPivotLevel( R5_KEY ))
            LabelR5 := label.new(bar_index,tom.R5Tom,makest("R5",tom.R5Tom),textcolor = color.white,color = R5Color)
        if(ShowPivotLevel( PP_KEY ))
            LabelPP := label.new(bar_index,tom.PPTom,makest("MP",tom.PPTom),textcolor = color.white,color = PivotColor)
var label_x = bar_index
switch(AdjustTheLabels)
    "Left"  => 
        label_x := labelStartPlace
    "Center"=> 
        label_x := (labelStartPlace+bar_index)/2
    "Right" => 
        label_x := bar_index
if (label_exist)
    if(ShowPivotLevel( S1_KEY ))
        label.set_x(LabelS1,label_x)
    if(ShowPivotLevel( S2_KEY ))
        label.set_x(LabelS2,label_x)
    if(ShowPivotLevel( S3_KEY ))
        label.set_x(LabelS3,label_x)
    if(ShowPivotLevel( S4_KEY ))
        label.set_x(LabelS4,label_x)
    if(ShowPivotLevel( S5_KEY ))
        label.set_x(LabelS5,label_x)
    if(ShowPivotLevel( R1_KEY ))
        label.set_x(LabelR1,label_x)
    if(ShowPivotLevel( R2_KEY ))
        label.set_x(LabelR2,label_x)
    if(ShowPivotLevel( R3_KEY ))
        label.set_x(LabelR3,label_x)
    if(ShowPivotLevel( R4_KEY ))
        label.set_x(LabelR4,label_x)
    if(ShowPivotLevel( R5_KEY ))
        label.set_x(LabelR5,label_x)
    if(ShowPivotLevel( PP_KEY ))
        label.set_x(LabelPP,label_x)

if(isdaily and PlotZones) 
    if(ShowPivotLevel( R1_KEY )) 
        setUpBox(Box.R1Box,tom.R1Tom,customtom.R1Tom,ZoneColor.R1PlotColor)
        setUpLine(Line.R1Line,(tom.R1Tom+customtom.R1Tom)/2,R1Color)
    if(ShowPivotLevel( R2_KEY ))    
        setUpBox(Box.R2Box,tom.R2Tom,customtom.R2Tom,ZoneColor.R2PlotColor)
        setUpLine(Line.R2Line,(tom.R2Tom+customtom.R2Tom)/2,R2Color)
    if(ShowPivotLevel( R3_KEY )) 
        setUpBox(Box.R3Box,tom.R3Tom,customtom.R3Tom,ZoneColor.R3PlotColor)
        setUpLine(Line.R3Line,(tom.R3Tom+customtom.R3Tom)/2,R3Color)

    if(ShowPivotLevel( S1_KEY )) 
        setUpBox(Box.S1Box,tom.S1Tom,customtom.S1Tom,ZoneColor.S1PlotColor)
        setUpLine(Line.S1Line,(tom.S1Tom+customtom.S1Tom)/2,S1Color)

    if(ShowPivotLevel( S2_KEY ))    
        setUpBox(Box.S2Box,tom.S2Tom,customtom.S2Tom,ZoneColor.S2PlotColor)
        setUpLine(Line.S2Line,(tom.S2Tom+customtom.S2Tom)/2,S2Color)

    if(ShowPivotLevel( S3_KEY )) 
        setUpBox(Box.S3Box,tom.S3Tom,customtom.S3Tom,ZoneColor.S3PlotColor)
        setUpLine(Line.S3Line,(tom.S3Tom+customtom.S3Tom)/2,S3Color)

    if(ShowPivotLevel( PP_KEY )) 
        setUpBox(Box.PPBox,tom.PPTom,customtom.PPTom,ZoneColor.PPPlotColor)
        setUpLine(Line.PPLine,(tom.PPTom+customtom.PPTom)/2,PivotColor)




plot(ShowPivotLevel( R5_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.R5Tom:na, title = R5_KEY , color = PSPColor.R5PlotColor )
plot(ShowPivotLevel( R4_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.R4Tom:na, title = R4_KEY , color = PSPColor.R4PlotColor )
plot(ShowPivotLevel( R3_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.R3Tom:na, title = R3_KEY , color = PSPColor.R3PlotColor )
plot(ShowPivotLevel( R2_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.R2Tom:na, title = R2_KEY , color = PSPColor.R2PlotColor )
plot(ShowPivotLevel( R1_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.R1Tom:na, title = R1_KEY , color = PSPColor.R1PlotColor )
plot(ShowPivotLevel( PP_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.PPTom:na, title = PP_KEY , color = PSPColor.PPPlotColor )
plot(ShowPivotLevel( S1_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.S1Tom:na, title = S1_KEY , color = PSPColor.S1PlotColor )
plot(ShowPivotLevel( S2_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.S2Tom:na, title = S2_KEY , color = PSPColor.S2PlotColor )
plot(ShowPivotLevel( S3_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.S3Tom:na, title = S3_KEY , color = PSPColor.S3PlotColor )
plot(ShowPivotLevel( S4_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.S4Tom:na, title = S4_KEY , color = PSPColor.S4PlotColor )
plot(ShowPivotLevel( S5_KEY ) and tom.PPTom!=0 and FTPLevels ? tom.S5Tom:na, title = S5_KEY , color = PSPColor.S5PlotColor )



plot(ShowPivotLevel( R3_KEY ) and customtom.PPTom!=0 and SR2Levels and isdaily ? customtom.R3Tom:na, title = R3_KEY +"C" , color = CustomColor.R3PlotColor )
plot(ShowPivotLevel( R2_KEY ) and customtom.PPTom!=0 and SR2Levels and isdaily ? customtom.R2Tom:na, title = R2_KEY +"C" , color = CustomColor.R2PlotColor )
plot(ShowPivotLevel( R1_KEY ) and customtom.PPTom!=0 and SR2Levels and isdaily ? customtom.R1Tom:na, title = R1_KEY +"C" , color = CustomColor.R1PlotColor )
plot(ShowPivotLevel( PP_KEY ) and customtom.PPTom!=0 and SR2Levels and isdaily ? customtom.PPTom:na, title = PP_KEY +"C" , color = CustomColor.PPPlotColor )
plot(ShowPivotLevel( S1_KEY ) and customtom.PPTom!=0 and SR2Levels and isdaily ? customtom.S1Tom:na, title = S1_KEY +"C" , color = CustomColor.S1PlotColor )
plot(ShowPivotLevel( S2_KEY ) and customtom.PPTom!=0 and SR2Levels and isdaily ? customtom.S2Tom:na, title = S2_KEY +"C" , color = CustomColor.S2PlotColor )
plot(ShowPivotLevel( S3_KEY ) and customtom.PPTom!=0 and SR2Levels and isdaily ? customtom.S3Tom:na, title = S3_KEY +"C" , color = CustomColor.S3PlotColor )


plot(ShowPivotLevel( R3_KEY ) and customtom.PPTom!=0 and PlotZones and isdaily ? line.get_y1(Line.R3Line):na, title = R3_KEY +"MID" , color = getColor(R3Color,100) )
plot(ShowPivotLevel( R2_KEY ) and customtom.PPTom!=0 and PlotZones and isdaily ? line.get_y1(Line.R2Line):na, title = R2_KEY +"MID" , color = getColor(R2Color,100) )
plot(ShowPivotLevel( R1_KEY ) and customtom.PPTom!=0 and PlotZones and isdaily ? line.get_y1(Line.R1Line):na, title = R1_KEY +"MID" , color = getColor(R1Color,100) )
plot(ShowPivotLevel( PP_KEY ) and customtom.PPTom!=0 and PlotZones and isdaily ? line.get_y1(Line.PPLine):na, title = PP_KEY +"MID" , color = getColor(PivotColor,100) )
plot(ShowPivotLevel( S1_KEY ) and customtom.PPTom!=0 and PlotZones and isdaily ? line.get_y1(Line.S1Line):na, title = S1_KEY +"MID" , color = getColor(S1Color,100) )
plot(ShowPivotLevel( S2_KEY ) and customtom.PPTom!=0 and PlotZones and isdaily ? line.get_y1(Line.S2Line):na, title = S2_KEY +"MID" , color = getColor(S2Color,100) )
plot(ShowPivotLevel( S3_KEY ) and customtom.PPTom!=0 and PlotZones and isdaily ? line.get_y1(Line.S3Line):na, title = S3_KEY +"MID" , color = getColor(S3Color,100) )

Dist_S3_S2 = customtom.S3Tom-(customtom.S3Tom - customtom.S2Tom)/2
Dist_S2_S1 = customtom.S2Tom-(customtom.S2Tom - customtom.S1Tom)/2
Dist_S1_PP = customtom.S1Tom-(customtom.S1Tom - customtom.PPTom)/2
Dist_PP_R1 = customtom.PPTom-(customtom.PPTom - customtom.R1Tom)/2
Dist_R1_R2 = customtom.R1Tom-(customtom.R1Tom - customtom.R2Tom)/2
Dist_R2_R3 = customtom.R2Tom-(customtom.R2Tom - customtom.R3Tom)/2


plot(ShowPivotLevel( R3_KEY ) and customtom.PPTom!=0 and isdaily and ShowGrayLines ? Dist_S3_S2:na, title = "Dist_S3_S2" , color = dgray )
plot(ShowPivotLevel( R2_KEY ) and customtom.PPTom!=0 and isdaily and ShowGrayLines ? Dist_S2_S1:na, title = "Dist_S2_S1" , color = dgray )
plot(ShowPivotLevel( R1_KEY ) and customtom.PPTom!=0 and isdaily and ShowGrayLines ? Dist_S1_PP:na, title = "Dist_S1_PP" , color = dgray )
plot(ShowPivotLevel( PP_KEY ) and customtom.PPTom!=0 and isdaily and ShowGrayLines ? Dist_PP_R1:na, title = "Dist_PP_R1" , color = dgray )
plot(ShowPivotLevel( S1_KEY ) and customtom.PPTom!=0 and isdaily and ShowGrayLines ? Dist_R1_R2:na, title = "Dist_R1_R2" , color = dgray )
plot(ShowPivotLevel( S2_KEY ) and customtom.PPTom!=0 and isdaily and ShowGrayLines ? Dist_R2_R3:na, title = "Dist_R2_R3" , color = dgray )
