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

//@version=5


// @description
library("CarlLib", overlay=true)

// @function  returns values to plot/use volatility oscillator 
// @param open the source of the close value to use
// @param open the source of the open value to use
// @param The oscillator length to use as a standard deviation
// @returns [x, y, spike, volOscBullish]
export VolatilityOscillator(float source, float open, int colOscLength) =>
    spike = source - open
    x = ta.stdev(spike,colOscLength)
    y = ta.stdev(spike,colOscLength) * -1
    volOscBullish = spike>x
    [x, y, spike, volOscBullish]

// @function  returns values representing the high of the most recent green and the low of the most recent red
// @param open open series
// @param close close series
// @param high high series
// @param close close series
// @param reqChangePerc the minimum require change percentage for the values to switch to new ones.
// @returns [highOfLastGreen, lowOfLastRed,changeOfLowPerc, distanceToHigh, distanceToLow, distanceToLongExitPercentage,distanceToShortExitPercentage]    
export LastLowRedHighGreen(float open, float high, float low, float close, float reqChangePerc) =>
    var lowOfLastRed =low
    var highOfLastGreen = high
    var tpLongPrice = close
    
    candleIsRed = open>close
    candleIsGreen = not candleIsRed
    
    changeOfLowPerc = lowOfLastRed>low? ((lowOfLastRed - low)/low)*100 : ((low - lowOfLastRed)/lowOfLastRed) *100
    changeOfHighPerc =  highOfLastGreen>high? ((highOfLastGreen - high)/high) *100 :  ((high - highOfLastGreen)/highOfLastGreen) *100
    
    if(candleIsRed and barstate.isconfirmed and (changeOfLowPerc>reqChangePerc or changeOfLowPerc<0))
        lowOfLastRed :=  low
    
    if(candleIsGreen and barstate.isconfirmed and (changeOfHighPerc>reqChangePerc or changeOfHighPerc>0))
        highOfLastGreen := high
    
    distanceToHigh = (highOfLastGreen - close)
    distanceToLow  = (close - lowOfLastRed)
    distanceToLongExitPercentage = (distanceToLow/close)*100
    distanceToShortExitPercentage = (distanceToHigh/highOfLastGreen) * 100
    
    // haveReasonableLongExit = distanceToLongExitPercentage > stopLossTarget
    // haveReasonableShortExit = distanceToShortExitPercentage > stopLossTarget
    [highOfLastGreen, lowOfLastRed,changeOfLowPerc, distanceToHigh, distanceToLow, distanceToLongExitPercentage,distanceToShortExitPercentage]    

export pstdev (float Series, int Period) =>
    mean = math.sum(Series, Period) / Period
    summation = 0.0
    for i=0 to Period-1
        sampleMinusMean = nz(Series[i]) - mean
        summation := summation + sampleMinusMean * sampleMinusMean
    math.sqrt(summation / Period)

export candleDetails (float open, float high, float low, float close) =>
    bodySize = math.abs(close - open)
    upperShadow = math.max(high - math.max(close, open), 0)

// Calculate the size of the lower shadow
    lowerShadow = math.max(math.min(close, open) - low, 0)
// Calculate the total size of the shadow
    wickSize = upperShadow + lowerShadow
    wickPercentage = (wickSize / (wickSize + bodySize)) * 100
    lowerShadowPercentage = (lowerShadow /(lowerShadow + bodySize))*100
    upperShadowPercentage = (upperShadow /(upperShadow+ bodySize))*100 
    shadowRatio = lowerShadow /(lowerShadow + upperShadow) * 100
    [bodySize, wickSize, upperShadow,lowerShadow, lowerShadowPercentage,upperShadowPercentage,shadowRatio,wickPercentage]


export volumeHeatmap(int volumeMALength, int volumeStdLength) =>
    length          = volumeMALength
    slength         = volumeStdLength

    thresholdExtraHigh  =3// input.float(3, title="Extra High Volume Threshold")
    thresholdHigh       =1.5// input.float(1.5, title="High Volume Threshold")
    thresholdMedium     =0.2// input.float(0.2, title="Medium Volume Threshold")
    thresholdNormal     =-0.5// input.float(-0.5, title="Normal Volume Threshold")



    //------------------------------------------------------------------------------
    // Calcs

    length := length > bar_index + 1 ? bar_index + 1 : length
    slength := slength > bar_index + 1 ? bar_index + 1 : slength

    mean    = ta.sma(volume, length)
    std     = pstdev(volume, slength)
    stdbar  = (volume - mean) / std

    //------------------------------------------------------------------------------
    // Alerts


    conditionExtraHigh  = stdbar > thresholdExtraHigh
    conditionHigh       = stdbar <= thresholdExtraHigh and stdbar > thresholdHigh 
    conditionMedium     = stdbar <= thresholdHigh and stdbar > thresholdMedium
    conditionNormal     = stdbar <= thresholdMedium and stdbar > thresholdNormal
    conditionLow        = stdbar <= thresholdNormal
    [stdbar, conditionLow,conditionMedium, conditionHigh, conditionExtraHigh]
    
export maAndVolumeConfirmedSupretrend(float Close, int volumeMALength, int volumeStdLength) =>

    [stdbar, conditionLow,conditionMedium, conditionHigh, conditionExtraHigh] = volumeHeatmap(volumeMALength, volumeStdLength)

    ma1 = ta.ema(Close,50)
    ma2 = ta.ema(Close, 200)

    maLong = Close > ma1 and Close > ma2 and ma1>ma2
    maShort = Close <ma1 and Close < ma2 and ma1 <ma2

    // pp supertrend
    prd = 2//input.int(defval = 2, title="Pivot Point Period", minval = 1, maxval = 50)
    Factor=3//input.float(defval = 3, title = "ATR Factor", minval = 1, step = 0.1)
    Pd= 10//input.int(defval = 10, title = "ATR Period", minval=1)

    // get Pivot High/Low
    float ph = ta.pivothigh(prd, prd)
    float pl = ta.pivotlow(prd, prd)


    // calculate the Center line using pivot points
    var float center = na
    float lastpp = ph ? ph : pl ? pl : na
    if lastpp
        if na(center)
            center := lastpp
        else
            //weighted calculation
            center := (center * 2 + lastpp) / 3

    // upper/lower bands calculation
    Up = center - (Factor * ta.atr(Pd))
    Dn = center + (Factor * ta.atr(Pd))

    // get the trend
    float TUp = na
    float TDown = na
    Trend = 0
    TUp := close[1] > TUp[1] ? math.max(Up, TUp[1]) : Up
    TDown := close[1] < TDown[1] ? math.min(Dn, TDown[1]) : Dn
    Trend := close > TDown[1] ? 1: close < TUp[1]? -1: nz(Trend[1], 1)
    Trailingsl = Trend == 1 ? TUp : TDown

    // check and plot the signals
    bSignal = Trend == 1 and Trend[1] == -1
    cBsignal = bSignal and maLong and (conditionHigh or conditionMedium)
    ssignal = Trend == -1 and Trend[1] == 1
    cSsignal = ssignal and maShort and (conditionHigh or conditionMedium)
    [bSignal, cBsignal, ssignal, cSsignal]



export tripleSupertrend() =>
    
    // 1
    
    [supertrend1, direction1] = ta.supertrend(3, 12)

    // 2

    [supertrend2, direction2] = ta.supertrend(2, 1)

    // 3

    [supertrend3, direction3] = ta.supertrend(1, 10)

    allBuy = (direction1 < 0) and (direction2 < 0) and (direction3 < 0)
    allSell = (direction1 > 0) and (direction2 > 0) and (direction3 > 0)
    [allBuy, allSell]

//--

export tdi(float src, int lengthrsi, int lengthband, int lengthrsipl)=>
    r=ta.rsi(src, lengthrsi)
    ma=ta.sma(r,lengthband)
    offs=(1.6185 * ta.stdev(r, lengthband))
    up=ma+offs
    dn=ma-offs
    mid=(up+dn)/2
    mab=ta.sma(r, lengthrsipl)
    // mbb=ta.sma(r, lengthtradesl)
    mabCross = ta.crossover(mab,mid)
    sharkFin = ta.crossover(mab,up)
    [mid,mab,mabCross,sharkFin]



showVolOsc = input.bool(false,title="Show Volatility Oscillator")
showLastGreen = input.bool(false,title="Show Last green low/last red high")

stopLossTarget = input.float(0.5,title="Stop loss target %", group="Last Green Low/red high")
reqChangePerc = input.float(0.1,title="Change % required for new high/low", group="Last Green Low/red high")


[highOfLastGreen, lowOfLastRed,changeOfLowPerc, distanceToHigh, distanceToLow, distanceToLongExitPercentage,distanceToShortExitPercentage]   
     = LastLowRedHighGreen(open,high,low,close,reqChangePerc)

plot(showLastGreen and not ta.change(lowOfLastRed) ? lowOfLastRed : na, title = "Low of last red", style = plot.style_stepline_diamond, color = distanceToLongExitPercentage > stopLossTarget ? color.red:color.new(color.red,60), linewidth=2)
plot(showLastGreen and not ta.change(highOfLastGreen) ? highOfLastGreen : na, title="High of last green", style=plot.style_stepline_diamond, color = distanceToShortExitPercentage > stopLossTarget ? color.green:color.new(color.green,60), linewidth=2)


/// plot volOsc
[x, y, spike, volOscBullish] = VolatilityOscillator(close, open, 100)
plot(showVolOsc?spike:na, color = color.black, linewidth = 2, title = "Spike Linel")

p1 = plot(showVolOsc?x:na, "Upper Line")
[bodySize, wickSize, upperShadow,lowerShadow, lowerShadowPercentage,upperShadowPercentage,shadowRatio, wickPercentage]= candleDetails(open,high,low,close)

