Cumulative delta indicator development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Cumulative delta indicator development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1217
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1046
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Cumulative Volume Delta (CVD) Indicator Development

Cumulative Volume Delta (CVD — Cumulative Volume Delta) is the accumulated sum of the difference between aggressive buy and sell volumes over a selected period. Unlike delta of individual candle, CVD shows the accumulated balance of market forces, making hidden divergences with price visible.

How CVD Works

Candle 1: buy_vol=100, sell_vol=60 → delta=+40, CVD=+40
Candle 2: buy_vol=80,  sell_vol=90 → delta=-10, CVD=+30
Candle 3: buy_vol=50,  sell_vol=120 → delta=-70, CVD=-40
Candle 4: buy_vol=200, sell_vol=80 → delta=+120, CVD=+80

CVD grows when buyers are more aggressive. With rising price and falling CVD — bullish narrative is not confirmed by volume (bearish divergence).

CVD Calculation

import pandas as pd
from decimal import Decimal
import asyncio

class CVDCalculator:
    def __init__(self, symbol: str, reset_period: str = 'session'):
        """
        reset_period: 'session' (daily), 'week', 'never'
        """
        self.symbol = symbol
        self.reset_period = reset_period

    def calculate_from_trades(self, trades: list[dict]) -> pd.DataFrame:
        """
        Calculate CVD from raw aggTrades data
        trades: list {price, quantity, time, is_buyer_maker}
        """
        df = pd.DataFrame(trades)

        # Determine trade side
        df['buy_vol'] = df.apply(
            lambda row: row['quantity'] if not row['is_buyer_maker'] else 0,
            axis=1
        )
        df['sell_vol'] = df.apply(
            lambda row: row['quantity'] if row['is_buyer_maker'] else 0,
            axis=1
        )
        df['delta'] = df['buy_vol'] - df['sell_vol']

        # Group by candles (e.g., 1-minute)
        df['time'] = pd.to_datetime(df['time'], unit='ms')
        df = df.set_index('time')

        candle_delta = df['delta'].resample('1min').sum()
        candle_buy = df['buy_vol'].resample('1min').sum()
        candle_sell = df['sell_vol'].resample('1min').sum()

        result = pd.DataFrame({
            'delta': candle_delta,
            'buy_vol': candle_buy,
            'sell_vol': candle_sell,
        })

        # CVD with session reset
        if self.reset_period == 'session':
            result['session'] = result.index.date
            result['cvd'] = result.groupby('session')['delta'].cumsum()
        else:
            result['cvd'] = result['delta'].cumsum()

        return result

Detecting Divergences

class CVDDivergenceDetector:
    def find_divergences(
        self,
        price_series: pd.Series,
        cvd_series: pd.Series,
        lookback: int = 20
    ) -> pd.DataFrame:
        divergences = []

        for i in range(lookback, len(price_series)):
            window_price = price_series.iloc[i-lookback:i+1]
            window_cvd = cvd_series.iloc[i-lookback:i+1]

            current_price = window_price.iloc[-1]
            current_cvd = window_cvd.iloc[-1]

            # Bearish divergence: price higher, CVD below previous high
            prev_price_high = window_price.iloc[:-1].max()
            prev_cvd_at_high = window_cvd.iloc[window_price.iloc[:-1].argmax()]

            if current_price > prev_price_high and current_cvd < prev_cvd_at_high:
                divergences.append({
                    'time': price_series.index[i],
                    'type': 'bearish',
                    'price': current_price,
                    'cvd': current_cvd,
                    'strength': (prev_cvd_at_high - current_cvd) / abs(prev_cvd_at_high) * 100
                })

            # Bullish divergence: price lower, CVD above previous low
            prev_price_low = window_price.iloc[:-1].min()
            prev_cvd_at_low = window_cvd.iloc[window_price.iloc[:-1].argmin()]

            if current_price < prev_price_low and current_cvd > prev_cvd_at_low:
                divergences.append({
                    'time': price_series.index[i],
                    'type': 'bullish',
                    'price': current_price,
                    'cvd': current_cvd,
                    'strength': (current_cvd - prev_cvd_at_low) / abs(prev_cvd_at_low) * 100
                })

        return pd.DataFrame(divergences)

Pine Script Implementation

//@version=5
indicator("Cumulative Volume Delta", shorttitle="CVD", overlay=false)

reset_on_session = input.bool(true, "Reset daily")

// Approximate delta from OHLCV
candle_up = close >= open
delta_approx = candle_up ?
    volume * ((close - open) / (high - low + 0.001)) :
    -volume * ((open - close) / (high - low + 0.001))

// CVD with session reset
var float cvd = 0.0
new_session = ta.change(time("D")) != 0

if reset_on_session and new_session
    cvd := delta_approx
else
    cvd := cvd + delta_approx

// Color by direction
cvd_color = cvd >= cvd[1] ? color.new(color.green, 40) : color.new(color.red, 40)

hline(0, color=color.gray, linestyle=hline.style_dotted)
plot(cvd, "CVD", cvd_color, linewidth=2)

// Divergence markers (simplified)
price_up = close > close[20]
cvd_down = cvd < cvd[20]
bearish_div = price_up and cvd_down
plotshape(bearish_div, "Bear Div", shape.circle, location.top,
          color.new(color.red, 0), size=size.tiny)

Real-time WebSocket Update

class CVDWebSocketStreamer:
    def __init__(self, symbol: str):
        self.symbol = symbol
        self.cvd = 0.0
        self.session_date = None

    async def stream(self):
        url = f"wss://stream.binance.com:9443/ws/{self.symbol.lower()}@aggTrade"

        async with websockets.connect(url) as ws:
            async for message in ws:
                trade = json.loads(message)
                await self.process_trade(trade)

    async def process_trade(self, trade: dict):
        import datetime
        today = datetime.date.today()

        # Reset CVD at session start
        if self.session_date != today:
            self.cvd = 0.0
            self.session_date = today

        qty = float(trade['q'])
        is_buyer_maker = trade['m']

        delta = -qty if is_buyer_maker else qty
        self.cvd += delta

        # Publish update to subscribers
        await self.broadcast({
            'type': 'cvd_update',
            'symbol': self.symbol,
            'cvd': self.cvd,
            'delta': delta,
            'timestamp': trade['T']
        })

CVD is a more advanced tool than regular bar delta. Accumulated divergence is visible immediately: when price rose for 3 days but CVD fell all that time — serious warning signal about trend weakness.