MM Detector (Long)
// 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
indicator("MM Detector (Long)", overlay=true, max_bars_back = 5000)

import carlpwilliams2/CarlLib/5 as carlLib

numberOfPushes = input.int(2,title="Number Of Pushes", minval = 1)
ma50 = ta.ema(close,50)
[bodySize, wickSize, upperShadow,lowerShadow, lowerShadowPercentage,upperShadowPercentage,shadowRatio,wickPercentage]= carlLib.candleDetails(open,high,low,close)

var mmIsValid = false
var lowOfBullClimaxCandle = low
var highOfBullClimaxCandle = high
var pushCount = 0
var pushRun = false
var inTrade = false
var bullishCandleLbls = array.new_label(0)
var pushCandleLbls = array.new_label(0)

if(ta.crossunder(close,ma50))
    inTrade:=false
// climax detector
showPushCandles = input.bool(true,title="Show Push Candles")
climaxShadowThreshold = input.int(30,title="Shadow Length Minimum %", group="Short Climax Candle")
climaxWickThreshold = input.int(10, title="Wick Length Maximum %", group="Short Climax Candle")

volSpikeThresh = input.float(30,title="Spike Threshold")
volAverage = ta.sma(volume,10)
volumeDifference = ((volume-volume[1])/volume)*100
volumeAverageDifference = ((volume-volAverage)/volume)*100

plot(volumeDifference, title="Volume Spke %", display = display.data_window)
plot(volumeAverageDifference, title="Volume avg Spke %", display = display.data_window)
plot(upperShadowPercentage, title="Upper Shadow", display = display.data_window)
plot(lowerShadowPercentage, title="Lower Shadow", display = display.data_window)
plot(shadowRatio, title="Shadow Ratio", display = display.data_window)

// Print the wick percentage
plot(wickPercentage, title="wick %", display = display.data_window)
plot(volumeDifference, title="volume Diff", display= display.data_window)

volumeSpike = volumeDifference>volSpikeThresh and volumeAverageDifference>60

bearishCandle = close < open
bullishCandle = close > open

bullishClimaxCandle = close< ma50 and volumeSpike and bearishCandle and wickPercentage>climaxShadowThreshold and close > low and lowerShadowPercentage>climaxShadowThreshold and shadowRatio>60 
bearishClimaxCandle = volumeSpike and bullishCandle and wickPercentage>climaxShadowThreshold and close > low and upperShadowPercentage>climaxShadowThreshold and shadowRatio<40

barsSinceClimax = ta.barssince(bullishClimaxCandle)

if(bullishClimaxCandle)
    lowOfBullClimaxCandle := mmIsValid ? low < lowOfBullClimaxCandle ? low : lowOfBullClimaxCandle : low
    highOfBullClimaxCandle :=  high 
    mmIsValid := true
    array.push(bullishCandleLbls,label.new(bar_index,low,"Low\nof\nBullish\nClimax",style=label.style_label_upper_right, textcolor = color.white))

    

// lowOfBullClimaxCandle :=  low[barsSinceClimax]
sizeOfClimaxCandle = math.abs(close[barsSinceClimax] - open[barsSinceClimax])

pushCandle = volumeSpike and not bearishCandle and bodySize> sizeOfClimaxCandle and bodySize> bodySize[1]

if(pushCandle and not pushRun)
    pushCount := pushCount + 1
    pushRun := true
    if(showPushCandles and (inTrade or mmIsValid))
        array.push(pushCandleLbls,label.new(bar_index,low,text="Push Run" + str.tostring(pushCount), style=label.style_label_upper_left, textcolor = color.white))

if(barstate.isconfirmed and close < open)
    pushRun :=false

barsSincePush = ta.barssince(pushCandle)

lastLow = barsSinceClimax > 0 ? ta.lowest(low,barsSinceClimax) : low

// tdi

lengthrsi=input(13)
src=close
lengthband=input(34)
lengthrsipl=input(2)
lengthtradesl=input(7)

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)

// if(barsSinceClimax < 300 and barsSinceClimax < barsSincePush and (lowOfBullClimaxCandle < lastLow or barsSinceClimax == 0))
//     mmIsValid := true
//     highOfBullClimaxCandle := high
//     pushCount := 0
if(barsSinceClimax<300 and pushCandle and mmIsValid)
    inTrade:=true
if(close > highOfBullClimaxCandle)
    highOfBullClimaxCandle :=na

if(close < lowOfBullClimaxCandle)
    mmIsValid:=false
    lowOfBullClimaxCandle := na
    // highOfBullClimaxCandle := na
    pushRun:=false
    pushCount:=0

if(barsSinceClimax > barsSincePush and pushCount>=numberOfPushes)
    mmIsValid:=false
    pushCount:=0
    lowOfBullClimaxCandle := na
    highOfBullClimaxCandle := na

plot(lastLow, title="last Low", display = display.data_window)
plot(barsSinceClimax, title="Bars since Climax Candle", display = display.data_window)
plot(mmIsValid ? lowOfBullClimaxCandle : na, title="Climax candle low", style = plot.style_linebr, color=color.yellow)
plot(mmIsValid ? highOfBullClimaxCandle : na, title="Climax candle high", style = plot.style_linebr, color=color.rgb(118, 185, 240))

plotshape(bullishClimaxCandle?lowOfBullClimaxCandle:na, location = location.absolute, text = "Bullish\nClimax\nCandle",title="Bullish Climax Candles", style = shape.labelup, textcolor = color.white, display = display.none)
plotshape(bearishClimaxCandle?close:na, location = location.top, text = "Bearish\nClimax\nCandle",title="Bearish Climax Candles",  style = shape.labeldown, textcolor = color.white, display = display.none)
plotshape(mmIsValid and mabCross?lowOfBullClimaxCandle:na, location = location.absolute)

plotshape(mmIsValid[1] and pushCandle?lowOfBullClimaxCandle:na, location = location.absolute, text = "Push", style = shape.labelup, textcolor = color.white, title="Push Label")
plotshape(mmIsValid and sharkFin?lowOfBullClimaxCandle:na, location = location.absolute, text = "Long", style = shape.labelup, textcolor = color.white, title="Long Label")

bgcolor(mmIsValid? color.new(color.green,95):na, title="Market Maker Possible")
// bgcolor(bullishClimaxCandle? color.new(color.green,50):na, title="Market Maker Possible")
// bgcolor(pushRun and (mmIsValid or mmIsValid[1])?color.new(color.red,50):na)
// bgcolor(inTrade?color.new(color.blue,70):na)
alertcondition(bullishClimaxCandle,title="Market Maker Climax Candle", message = "Possible Market Maker Pattern on {{ticker}}({{interval}}), price = {{close}}")
alertcondition(mmIsValid[1] and pushCandle,title="Market Maker Push Candle", message = "Push Candle whilst Market Maker pattern is valid on {{ticker}}({{interval}}), price = {{close}}")
alertcondition(mmIsValid and sharkFin,title="Market Maker Long", message = "Go long signal detected whilst Market Maker Pattern is valid on {{ticker}}({{interval}}), price = {{close}}")
