#// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
#// © cyatophilum
#indicator("Volume Divergence Indicator",overlay= true)
# Converted by Sam4Cok@Samer800 - 05/2023
declare lower;
#// Inputs {
input priceLookBack = 20; # 'Price and volume Lookback'
input bull_Sensitivity = 3; # 'Bull Sensitivity'
input bear_Sensitivity = 4; # 'Bear Sensitivity'
input VolumeMovAvgLength = 20; # 'Volume MA length'
input SensitivityOfSpikes = 3; # 'Sensitivity of Spikes'
input SensitivityOfContractions = 1; # 'Sensitivity of Contractions'
input trendSensitivity = 5; # 'Trend sensitivity'
def mult = SensitivityOfSpikes;
def mult2 = SensitivityOfContractions;
def maLength = VolumeMovAvgLength;
def bullSensitivity = bull_Sensitivity + 1;
def bearSensitivity = bear_Sensitivity + 1;
def na = Double.NaN;
def last = IsNaN(close);
#barssince(Condition) =>
script barssince {
input Condition = 0;
def barssince = if Condition then 0 else barssince[1] + 1;
plot return = barssince;
}
#// Algorithm {
#// Bullish Divergence
def priceLowerLows = Lowest(low, priceLookBack) == Lowest(low, priceLookBack * bullSensitivity);
def lowVol1 = Lowest(volume, priceLookBack);
def lowVol2 = Lowest(volume, priceLookBack * bullSensitivity);
def volumeHigherLows = lowVol1 > lowVol2;
def bulDiv = priceLowerLows and volumeHigherLows;
def bullishDivergence = priceLowerLows and volumeHigherLows and !bulDiv[1];
#// Bearish Divergence
def priceHigherHighs = Highest(high, priceLookBack) == Highest(high, priceLookBack * bearSensitivity);
def highVol1 = Highest(volume, priceLookBack);
def highVol2 = Highest(volume, priceLookBack * bearSensitivity);
def volumeLowerHighs = highVol1 < highVol2;
def bearDiv = priceHigherHighs and volumeLowerHighs;
def bearishDivergence = priceHigherHighs and volumeLowerHighs and !bearDiv[1];
#// Volume Spike:
def volMA = Average(volume, maLength);
def volDev = mult * StDev(volume, maLength);
def volDev2 = mult2 * StDev(volume, maLength);
def upperDevVol1 = volMA + volDev;
def volumeSpike = Crosses(volume, upperDevVol1, CrossingDirection.ABOVE);
#// Volume Contraction:
def lowerDevVol1 = volMA - volDev2;
def volumeContraction = Crosses(volume, lowerDevVol1, CrossingDirection.BELOW) and !last;
#// Volume Trend:
def increasingTrend = barssince(volume < volMA) > trendSensitivity;
def decreasingTrend = barssince(volume > volMA) > trendSensitivity;
plot pvolMA = volMA;#, 'Volume MA',
pvolMA.SetLineWeight(2);
pvolMA.AssignValueColor(if increasingTrend then Color.GREEN else
if decreasingTrend then color.red else Color.WHITE);
plot pdevVol1 = upperDevVol1;#, 'stdevVol1',
pdevVol1.SetLineWeight(2);
pdevVol1.SetDefaultColor(Color.DARK_GREEN);
plot pdevVol2 = lowerDevVol1;#, 'stdevVol2',color.rgb(255, 82, 82, 50),
pdevVol2.SetLineWeight(2);
pdevVol2.SetDefaultColor(Color.DARK_RED);
AddCloud(pdevVol1,pvolMA, Color.DARK_GREEN);
AddCloud(pvolMA,pdevVol2, Color.DARK_RED);
plot vol = Volume;
vol.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
vol.AssignValueColor(if bullishDivergence then color.lime else
if bearishDivergence then color.red else
if volumeSpike then color.yellow else
if volumeContraction then color.CYAN else CreateColor(119, 119, 119));
#--- END of CODE