Absolute Momentum Intensity
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ALifeToMake

//@version=5
indicator(title="Absolute Momentum Intensity V1.2", shorttitle="AMI", overlay=false)

// AMI ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Inputs
bullColor=input.color(color.new(#22ab94, 0), title="Bullish")
bearColor=input.color(color.new(#f7525f, 0), title="Bearish")

contrast = input.int(100, minval = 1, title = "Contrast", tooltip="Can be used to increase or decrease the difference between high and low momentum. A value of 20 will show every single impulse, while 100 will flatten them, thus revealing when the momentum is the strongest.")

MAoneLength = input.int(5, minval = 1, title = "Length of the moving average", group = "First ribbon", tooltip="This line serves as threshold between bullish and bearish for AMI.")
MAoneColor = input.color(color.new(#787b86, 0), title = "Line", group = "First ribbon")
BullOneBGColor=input.color(color.new(#42bda8, 0), title="Bullish bg", group="First ribbon", tooltip="Background (bg) color.")
BearOneBGColor=input.color(color.new(#f77c80, 0), title="Bearish bg", group="First ribbon")
decreaseOneBGColor=input.color(color.new(#9598a1, 0), title="Decreasing momentum bg", group="First ribbon")

MAtwoLength = input.int(10, minval = 1, title = "Length of the moving average", group = "Second ribbon")
MAtwoColor = input.color(color.new(#1e1e1e, 100), title = "Line", group = "Second ribbon")
BullTwoBGColor=input.color(color.new(#70ccbd, 0), title="Bullish bg", group = "Second ribbon")
BearTwoBGColor=input.color(color.new(#faa1a4, 0), title="Bearish bg", group = "Second ribbon")
decreaseTwoBGColor=input.color(color.new(#b2b5be, 0), title="Decreasing momentum bg", group = "Second ribbon")

MAthreeLength = input.int(15, minval = 1, title = "Length of the moving average", group = "Third ribbon")
MAthreeColor = input.color(color.new(#1e1e1e, 100), title = "Line", group = "Third ribbon")
BullThreeBGColor=input.color(color.new(#ace5dc, 0), title="Bullish bg", group = "Third ribbon")
BearThreeBGColor=input.color(color.new(#fccbcd, 0), title="Bearish bg", group = "Third ribbon")
decreaseThreeBGColor=input.color(color.new(#d1d4dc, 0), title="Decreasing momentum bg", group = "Third ribbon")

// Calculations -----------------------------------------------------------------------------------------
body = open<close ? close-open : open-close

var momentumVal=0.0
float volumeMA = ta.sma(volume, contrast)
float ampMA = ta.sma(body, contrast)
float myVolumeMA = (volume/volumeMA)+1
float myAmpMA = (body/ampMA)+1
float momentum = myVolumeMA*myAmpMA

// If no data is available
var bool naCounter = true
if na(momentum) and naCounter
    label.new(bar_index,0,"Insufficient datas to calculate AMI", color = #787b86, textcolor = #000000, style = label.style_label_down)
    naCounter := false

// If datas are available
orientedMomentum = open<close ? momentum : -momentum
momentumVal := momentumVal[1]? momentumVal[1]+orientedMomentum : momentum
MAmoOne = ta.rma(momentumVal,MAoneLength)
MAmoTwo = ta.rma(momentumVal,MAtwoLength)
MAmoThree = ta.rma(momentumVal,MAthreeLength)
inBetween = momentumVal > MAmoOne ? momentumVal-MAmoOne : momentumVal < MAmoOne ? MAmoOne-momentumVal : momentumVal
inBetweenPast=inBetween*0.8

// Plots ------------------------------------------------------------------------------------------------
moColor = momentumVal >= MAmoOne ? bullColor : bearColor

siPlotThree=plot(MAmoThree, color=MAthreeColor, linewidth = 1)
siPlotTwo=plot(MAmoTwo, color=MAtwoColor, linewidth = 1)
siPlotOne=plot(MAmoOne, color=MAoneColor, linewidth = 1)
moPlot=plot(momentumVal, color=moColor, linewidth = 2)

isCrossOver = ta.crossover(momentumVal,MAmoOne)
isCrossUnder = ta.crossunder(momentumVal,MAmoOne)

bullBearOneBGColor = momentumVal >= MAmoOne and inBetween>=inBetweenPast[1]? BullOneBGColor : momentumVal >= MAmoOne and inBetween<inBetweenPast[1]? decreaseOneBGColor : momentumVal <= MAmoOne and inBetween>=inBetweenPast[1]? BearOneBGColor : momentumVal <= MAmoOne and inBetween<inBetweenPast[1]? decreaseOneBGColor : isCrossOver ? BullOneBGColor : isCrossUnder ? BearOneBGColor : decreaseOneBGColor
bullBearTwoBGColor = momentumVal >= MAmoOne and inBetween>=inBetweenPast[1]? BullTwoBGColor : momentumVal >= MAmoOne and inBetween<inBetweenPast[1]? decreaseTwoBGColor : momentumVal <= MAmoOne and inBetween>=inBetweenPast[1]? BearTwoBGColor : momentumVal <= MAmoOne and inBetween<inBetweenPast[1]? decreaseTwoBGColor : isCrossOver ? BullTwoBGColor : isCrossUnder ? BearTwoBGColor : decreaseTwoBGColor
bullBearThreeBGColor = momentumVal >= MAmoOne and inBetween>=inBetweenPast[1]? BullThreeBGColor : momentumVal >= MAmoOne and inBetween<inBetweenPast[1]? decreaseThreeBGColor : momentumVal <= MAmoOne and inBetween>=inBetweenPast[1]? BearThreeBGColor : momentumVal <= MAmoOne and inBetween<inBetweenPast[1]? decreaseThreeBGColor : isCrossOver ? BullThreeBGColor : isCrossUnder ? BearThreeBGColor : decreaseThreeBGColor

fill(siPlotTwo, siPlotThree, color=bullBearThreeBGColor)
fill(siPlotOne, siPlotTwo, color=bullBearTwoBGColor)
fill(moPlot, siPlotOne, color=bullBearOneBGColor)

// DIVERGENCES -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Inputs
bullDivColor=input.color(color.new(#22ab94, 40), title="Bullish", group = "Divergences")
bearDivColor=input.color(color.new(#f7525f, 40), title="Bearish", group = "Divergences")

pivotsRight = input(title='Right search length', defval=10, group = "Divergences")
pivotsLeft = input(title='Left search length', defval=10, group = "Divergences")
minRange = input(title='Smallest area of search', defval=5, group = "Divergences")
maxRange = input(title='Largest area of search', defval=60, group = "Divergences")

// Calculations -----------------------------------------------------------------------------------------
isPivotLow = na(ta.pivotlow(momentumVal, pivotsLeft, pivotsRight)) ? false : true
isPivotHigh = na(ta.pivothigh(momentumVal, pivotsLeft, pivotsRight)) ? false : true

distance(myPivot) =>
    bars = ta.barssince(myPivot == true)
    minRange <= bars and bars <= maxRange

isIndiePivotLow = momentumVal[pivotsRight] > ta.valuewhen(isPivotLow, momentumVal[pivotsRight], 1) and distance(isPivotLow[1])
isChartPivotLow = low[pivotsRight] < ta.valuewhen(isPivotLow, low[pivotsRight], 1)
isIndiePivotHigh = momentumVal[pivotsRight] < ta.valuewhen(isPivotHigh, momentumVal[pivotsRight], 1) and distance(isPivotHigh[1])
isChartPivotHigh = high[pivotsRight] > ta.valuewhen(isPivotHigh, high[pivotsRight], 1)
bullishDivergence = isChartPivotLow and isIndiePivotLow and isPivotLow
bearishDivergence = isChartPivotHigh and isIndiePivotHigh and isPivotHigh

// Plots ------------------------------------------------------------------------------------------------
bullActivDivColor=bullishDivergence ? bullDivColor : color.new(#ffffff, 100)
bearActivDivColor=bearishDivergence ? bearDivColor : color.new(#ffffff, 100)
plotBullDiv = isPivotLow ? momentumVal[pivotsRight] : na
plotBearDiv = isPivotHigh ? momentumVal[pivotsRight] : na

plot(plotBullDiv, offset=-pivotsRight, linewidth=1, color=bullActivDivColor)
plot(plotBearDiv, offset=-pivotsRight, linewidth=1, color=bearActivDivColor)
