CVD by armandavoodi79
224 downloads / 360 views / Created: 14.12.2025 Average Rating: 0
Addon Description
Cumulative Volume Delta
Comments
// -------------------------------------------------------------------------------
// Cumulative Volume Delta (CVD) displays buy/sell volume difference accumulated during some period.
// Supports SMA and EMA smoothing.
//
// Version 1.00
// Copyright 2025, EarnForex.com
// https://www.earnforex.com/indicators/CVD/
// -------------------------------------------------------------------------------
using System;
using cAlgo.API;
namespace cAlgo
{
[Indicator(IsOverlay = false, AccessRights = AccessRights.None)]
public class CVD : Indicator
{
// Enumeration for smoothing type.
public enum SmoothingMethod
{
None, // No Smoothing
SMA, // Simple Moving Average
EMA // Exponential Moving Average
}
// Input parameters.
[Parameter("Source Timeframe", DefaultValue = "Current")]
public TimeFrame DataTimeframe { get; set; }
[Parameter("Cumulative Period", DefaultValue = 20, MinValue = 1)]
public int CumulativePeriod { get; set; }
[Parameter("Smoothing Method", DefaultValue = SmoothingMethod.None)]
public SmoothingMethod SmoothMethod { get; set; }
[Parameter("Smoothing Period", DefaultValue = 1, MinValue = 1)]
public int SmoothPeriod { get; set; }
// Output buffers.
[Output("CVD Positive", LineColor = "LimeGreen", PlotType = PlotType.Histogram, Thickness = 2)]
public IndicatorDataSeries CVDPositive { get; set; }
[Output("CVD Negative", LineColor = "Red", PlotType = PlotType.Histogram, Thickness = 2)]
public IndicatorDataSeries CVDNegative { get; set; }
[Output("CVD Smoothed", LineColor = "DarkGray", PlotType = PlotType.Line, LineStyle = LineStyle.Dots)]
public IndicatorDataSeries CVDSmooth { get; set; }
// Internal data series.
private IndicatorDataSeries CVDRaw;
private IndicatorDataSeries DeltaVolume;
// Multi-timeframe bars.
private Bars lowerTFBars;
// EMA multiplier.
private double alpha;
protected override void Initialize()
{
// Initialize internal data series.
CVDRaw = CreateDataSeries();
DeltaVolume = CreateDataSeries();
// Get lower timeframe bars.
if (DataTimeframe.Name == "Current")
{
lowerTFBars = Bars;
}
else
{
lowerTFBars = MarketData.GetBars(DataTimeframe);
}
// Check if selected timeframe is valid.
if (lowerTFBars.TimeFrame > Bars.TimeFrame)
{
Print("Warning: Data timeframe should be equal to or lower than the current chart timeframe. Using current timeframe.");
lowerTFBars = Bars;
}
// Calculate EMA multiplier.
alpha = 2.0 / (SmoothPeriod + 1.0);
}
public override void Calculate(int index)
{
// Check for sufficient data.
if (index < CumulativePeriod)
{
CVDPositive[index] = 0;
CVDNegative[index] = 0;
CVDSmooth[index] = 0;
return;
}
// Calculate non-cumulative delta volume for current bar.
DeltaVolume[index] = CalculateVolumeDelta(index);
// Calculate rolling cumulative delta over fixed period.
double rollingSumDelta = 0;
int periodsToSum = Math.Min(CumulativePeriod, index + 1);
// Sum delta volume for the last N bars (including current bar).
for (int j = 0; j < periodsToSum; j++)
{
rollingSumDelta += DeltaVolume[index - j];
}
CVDRaw[index] = rollingSumDelta;
// Apply smoothing.
ApplySmoothing(index);
// Split values into positive and negative buffers for histogram display.
if (CVDSmooth[index] >= 0)
{
CVDPositive[index] = CVDSmooth[index];
CVDNegative[index] = 0;
}
else
{
CVDPositive[index] = 0;
CVDNegative[index] = CVDSmooth[index];
}
}
private double CalculateVolumeDelta(int barIndex)
{
// Get current bar time.
DateTime barTime = Bars.OpenTimes[barIndex];
DateTime nextBarTime = Bars.OpenTimes[barIndex + 1]; // A newer bar.
if (IsLastBar) nextBarTime = DateTime.Now; // No newer bar.
// Find corresponding bars in lower timeframe.
int lowerTFStartIndex = lowerTFBars.OpenTimes.GetIndexByTime(barTime);
if (lowerTFStartIndex < 0 || lowerTFBars.OpenTimes[lowerTFStartIndex] < barTime)
return 0;
double totalDelta = 0;
// Accumulate delta from all lower timeframe bars within current bar.
for (int i = lowerTFStartIndex; i < lowerTFBars.Count; i++)
{
// Check if still within current bar timeframe.
if (lowerTFBars.OpenTimes[i] >= nextBarTime)
break;
// Get OHLC and volume for lower timeframe bar.
double ltfHigh = lowerTFBars.HighPrices[i];
double ltfLow = lowerTFBars.LowPrices[i];
double ltfClose = lowerTFBars.ClosePrices[i];
double ltfVolume = lowerTFBars.TickVolumes[i];
// Calculate delta using price position within range.
double range = ltfHigh - ltfLow;
double buyVolume = 0;
double sellVolume = 0;
if (range > 0)
{
// Estimate buy/sell volume based on close position in range.
double closePosition = (ltfClose - ltfLow) / range;
buyVolume = ltfVolume * closePosition;
sellVolume = ltfVolume * (1 - closePosition);
totalDelta += (buyVolume - sellVolume);
}
}
return totalDelta;
}
private void ApplySmoothing(int index)
{
if (SmoothPeriod <= 1 || SmoothMethod == SmoothingMethod.None)
{
CVDSmooth[index] = CVDRaw[index];
}
else if (SmoothMethod == SmoothingMethod.SMA)
{
CVDSmooth[index] = CalculateSMA(index, SmoothPeriod, CVDRaw);
}
else if (SmoothMethod == SmoothingMethod.EMA)
{
CVDSmooth[index] = CalculateEMA(index, SmoothPeriod, CVDRaw);
}
}
private double CalculateSMA(int index, int period, IndicatorDataSeries source)
{
if (period <= 0 || index < period - 1)
{
return source[index];
}
double sum = 0;
int count = 0;
for (int i = 0; i < period && index - i >= 0; i++)
{
sum += source[index - i];
count++;
}
return count > 0 ? sum / count : source[index];
}
private double CalculateEMA(int index, int period, IndicatorDataSeries source)
{
if (period <= 0)
{
return source[index];
}
// Initialize with SMA for the first value.
if (index < period)
{
return CalculateSMA(index, index + 1, source);
}
// For the first complete period, use SMA.
if (index == period - 1 || double.IsNaN(CVDSmooth[index - 1]))
{
return CalculateSMA(index, period, source);
}
// EMA formula: (Current - Previous EMA) * multiplier + Previous EMA.
return (source[index] - CVDSmooth[index - 1]) * alpha + CVDSmooth[index - 1];
}
}
}
Risk warning: Forex, spread bets and CFD are leveraged products. They may not be suitable for you as they carry a high degree of risk to your capital and you can lose more than your initial investment. You should ensure you understand all of the risks.
Copyright © 2006 - 2025, Forex Software Ltd.;
Copyright © 2006 - 2025, Forex Software Ltd.;