Developed by the renowned market technician Marc Chaikin, the Accumulation/Distribution (A/D) Line is a sophisticated volume-based indicator designed to measure the cumulative flow of money into or out of an asset. It achieves this by assessing the closing price’s position within the period’s high-low range and then weighting this by the volume for that period. The A/D Line aims to quantify the net buying pressure (accumulation) or selling pressure (distribution).
The calculation process for each period is as follows:
Money Flow Multiplier (MFM): This determines the
strength of buying or selling pressure for a single period. It ranges
from -1 (maximum selling pressure) to +1 (maximum buying pressure). If High = Low (i.e., no price range for the
period), the MFM is typically treated as 0.
Money Flow Volume (MFV): This is calculated by
multiplying the Money Flow Multiplier by the volume for the period. A positive MFV indicates buying pressure, while
a negative MFV suggests selling pressure.
Accumulation/Distribution (A/D) Line: The A/D
Line is a cumulative sum of the Money Flow Volume from each period. The line trends upwards when the closing price
is consistently in the upper half of the period’s trading range,
especially on increasing volume, signaling accumulation. Conversely, it
trends downwards when the closing price is frequently in the lower half
of the range on increasing volume, indicating distribution.
Usage: The Chaikin A/D Line, much like On Balance Volume (OBV), is primarily used to confirm price trends and identify potential reversals through divergences. The actual numerical value of the A/D Line is less important than its direction and its relationship with the price action.
TA-Lib Function: The Technical Analysis Library (TA-Lib) provides a function to calculate the Chaikin A/D Line:
talib.AD(high_prices, low_prices, close_prices, volume)
high_prices
: An array or series of high prices for each
period.low_prices
: An array or series of low prices for each
period.close_prices
: An array or series of closing prices for
each period.volume
: An array or series of volume data for each
period. All input series must be of the same length and aligned. Volume
should be a numeric type (e.g., float).Code Example (Calculation & Plot with yfinance Data):
The following Python code demonstrates how to fetch the necessary
High, Low, Close, and Volume data using yfinance
, calculate
the Chaikin A/D Line, and then plot the asset’s price alongside its A/D
Line.
import yfinance as yf
import talib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# --- 1. Data Fetching using yfinance ---
= "GOOGL" # Example: Alphabet Inc.
ticker_symbol # Fetching a bit more data initially to ensure enough for indicator calculation start
= "2022-12-01"
data_start_date = "2023-01-01" # Start plotting from here
plot_start_date = "2024-05-01"
data_end_date
= yf.download(ticker_symbol, start=data_start_date, end=data_end_date, auto_adjust=False, progress=False)
data
if data.empty or 'Volume' not in data.columns or data['Volume'].isnull().all() or \
'High' not in data.columns or 'Low' not in data.columns or 'Close' not in data.columns:
print(f"Insufficient HLCV data found for {ticker_symbol}. Exiting.")
else:
# Complying with user preference for droplevel
if isinstance(data.columns, pd.MultiIndex):
= data.columns.droplevel(level=1)
data.columns
# Prepare data: ensure no NaNs in HLCV for the period used by TA-Lib
# TA-Lib's AD function does not require a specific lookback period like MA or RSI,
# it calculates from the first available HLCV data point.
# We just need to ensure there are no NaNs in the input arrays.
= data[['High', 'Low', 'Close', 'Volume']].dropna()
ohlcv_data
= ohlcv_data['High']
high_prices = ohlcv_data['Low']
low_prices = ohlcv_data['Close']
close_prices = ohlcv_data['Volume'].astype(float) # Ensure volume is float
volume_data = ohlcv_data.index
date_index
# --- 2. Chaikin A/D Line Calculation ---
if len(close_prices) > 0: # AD can be calculated if there's at least one data point
= talib.AD(high_prices, low_prices, close_prices, volume_data)
ad_line_values = "Chaikin A/D Line"
indicator_name print(f"\n--- {indicator_name} (AD) for {ticker_symbol} ---")
if len(ad_line_values) >= 5:
print(f"Output {indicator_name} (last 5): {ad_line_values[-5:].round(2)}")
elif len(ad_line_values) > 0:
print(f"Output {indicator_name} (all): {ad_line_values.round(2)}")
else:
print(f"Output {indicator_name}: No A/D Line values calculated.")
# Filter data for the desired plotting period
= ohlcv_data[ohlcv_data.index >= plot_start_date]
plot_ohlcv_data = pd.Series(ad_line_values, index=ohlcv_data.index)[plot_ohlcv_data.index]
plot_ad_line_values = plot_ohlcv_data.index
plot_date_index = plot_ohlcv_data['Close']
plot_close_prices
# --- 3. Plotting ---
if not plot_date_index.empty:
= plt.subplots(2, 1, figsize=(14, 10), sharex=True,
fig, axes ={'height_ratios': [3, 1]})
gridspec_kw
# Plot Price
0].plot(plot_date_index, plot_close_prices, label='Close Price', color='blue')
axes[0].set_title(f'{ticker_symbol} Price and {indicator_name}')
axes[0].set_ylabel('Price')
axes[0].legend(loc='upper left')
axes[0].grid(True)
axes[
# Plot Chaikin A/D Line
1].plot(plot_date_index, plot_ad_line_values, label=indicator_name, color='teal')
axes[1].set_ylabel('A/D Line Value')
axes[1].set_xlabel('Date')
axes[1].ticklabel_format(style='sci', axis='y', scilimits=(0,0)) # For potentially large cumulative values
axes[1].legend(loc='upper left')
axes[1].grid(True)
axes[
plt.tight_layout()
plt.show()else:
print(f"No data available for the plotting period starting {plot_start_date}.")
else:
print(f"\nSkipping {indicator_name} plot for {ticker_symbol}: Insufficient data after cleaning.")
if not data.empty:
print(f"Original data available from {data.index.min().date()} to {data.index.max().date()}. Check for NaNs in HLCV columns.")
Explanation of the Code:
yfinance
, talib
, numpy
,
matplotlib.pyplot
, pandas
) are imported.yf.download()
fetches High, Low, Close, and Volume
(HLCV) data. User preferences auto_adjust=False
and
droplevel
are applied.ohlcv_data = data[['High', 'Low', 'Close', 'Volume']].dropna()
prepares the data by removing any rows where any of HLCV values are
missing, ensuring clean input for TA-Lib.high_prices
, low_prices
,
close_prices
, and volume_data
(converted to
float
) are extracted.if len(close_prices) > 0:
ensures data
exists.talib.AD(high_prices, low_prices, close_prices, volume_data)
computes the A/D Line. TA-Lib’s AD
function returns an
array of the same length as the input data, with the calculation
starting from the first data point.plot_start_date
onwards, making the chart
cleaner if a long history was fetched for calculation stability.plt.subplots(2, 1, ...)
creates a figure with two
vertically stacked subplots.axes[1].ticklabel_format(style='sci', axis='y', scilimits=(0,0))
is used for the y-axis of the A/D plot to handle potentially large
cumulative values with scientific notation.plt.tight_layout()
ensures good spacing.plt.show()
displays the chart.The Chaikin A/D Line offers a nuanced view of volume dynamics by considering where the price closes within its range. This makes it a valuable tool for traders looking to confirm trends and identify subtle shifts in buying or selling pressure that might precede price reversals.