Exchange Netflow
Tracks the net movement of coins onto and off exchanges — the most direct on-chain signal of sell pressure.
What is it?
Exchange Netflow = Exchange Inflow − Exchange Outflow. Inflow is the volume of coins moving onto exchange wallets (typically to sell); outflow is the volume moving off exchanges (typically to self-custody, indicating long-term holding intent). Positive netflow (more coins entering exchanges) is bearish — it suggests holders are preparing to sell. Negative netflow (more coins leaving exchanges) is bullish — it suggests accumulation and reduced sell pressure. Exchange reserve (the total balance held on all exchanges) is the cumulative version of netflow — a declining reserve over months is a strong bullish signal.
When to use it
- Sell pressure detection: a sudden spike in exchange inflow (large positive netflow) often precedes a price decline as coins are deposited to sell.
- Accumulation confirmation: sustained negative netflow (coins leaving exchanges) during a price consolidation confirms institutional accumulation.
- Exchange reserve trend: a multi-month declining exchange reserve is one of the strongest bullish on-chain signals — supply is being removed from the market.
- Whale alert correlation: combine exchange netflow with whale wallet tracking to identify whether large inflows are from long-term holders or short-term speculators.
- Pre-breakout confirmation: a price breakout accompanied by negative netflow (coins leaving exchanges) is more reliable than a breakout with positive netflow.
Common pitfalls
- Exchange netflow data quality varies significantly by provider. Different providers track different sets of exchange wallets — always use the same provider for consistency.
- Internal exchange transfers (e.g. moving coins between cold and hot wallets within the same exchange) can be misclassified as inflow or outflow.
- The relationship between netflow and price is not immediate. Large inflows can precede price drops by days or weeks — it is a leading indicator, not a timing tool.
- DeFi and self-custody trends mean that coins leaving exchanges may be going to DeFi protocols rather than long-term cold storage. This reduces the bullish signal strength.
- Exchange netflow is most reliable for Bitcoin. For altcoins, a significant portion of trading occurs on DEXs, making exchange-based netflow an incomplete picture.
Free code template
Requires Python 3.9+ and the listed pip packages. See inline comments for usage.
# Exchange Netflow Analysis — DAI Python Template
# Data source: Glassnode API
# pip install requests pandas matplotlib
import requests
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
GLASS_API_KEY = 'YOUR_GLASSNODE_API_KEY'
def fetch_glassnode(metric: str, asset: str = 'BTC', resolution: str = '24h') -> pd.DataFrame:
url = f'https://api.glassnode.com/v1/metrics/{metric}'
r = requests.get(url, params={'a': asset, 'i': resolution, 'api_key': GLASS_API_KEY, 'f': 'JSON'})
r.raise_for_status()
df = pd.DataFrame(r.json())
df['t'] = pd.to_datetime(df['t'], unit='s')
return df.set_index('t').rename(columns={'v': metric.split('/')[-1]})
def plot_exchange_netflow(asset: str = 'BTC'):
price_df = fetch_glassnode('market/price_usd_close', asset)
inflow_df = fetch_glassnode('transactions/transfers_volume_to_exchanges_sum', asset)
outflow_df = fetch_glassnode('transactions/transfers_volume_from_exchanges_sum', asset)
reserve_df = fetch_glassnode('distribution/balance_exchanges', asset)
df = price_df.join(inflow_df).join(outflow_df).join(reserve_df)
df.columns = ['price', 'inflow', 'outflow', 'reserve']
df['netflow'] = df['inflow'] - df['outflow']
df['netflow_7d'] = df['netflow'].rolling(7).mean()
fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(14, 12), sharex=True)
fig.patch.set_facecolor('#0d1f3c')
ax1.semilogy(df.index, df['price'], color='#3b82f6', linewidth=1.5)
ax1.set_facecolor('#0d1f3c'); ax1.tick_params(colors='white')
ax1.set_ylabel(f'{asset} Price (log)', color='white')
colors = ['#ef4444' if v > 0 else '#22c55e' for v in df['netflow_7d']]
ax2.bar(df.index, df['netflow_7d'], color=colors, alpha=0.7, width=1)
ax2.axhline(0, color='#94a3b8', linestyle=':', alpha=0.5)
ax2.set_facecolor('#0d1f3c'); ax2.tick_params(colors='white')
ax2.set_ylabel('Netflow 7D MA (BTC)', color='white')
ax3.plot(df.index, df['reserve'], color='#f59e0b', linewidth=1.5)
ax3.set_facecolor('#0d1f3c'); ax3.tick_params(colors='white')
ax3.set_ylabel('Exchange Reserve (BTC)', color='white')
print(f'Latest Netflow (7D MA): {df["netflow_7d"].iloc[-1]:,.0f} BTC')
print(f'Exchange Reserve: {df["reserve"].iloc[-1]:,.0f} BTC')
plt.tight_layout()
plt.savefig('exchange_netflow.png', dpi=150, bbox_inches='tight')
plt.show()
# plot_exchange_netflow('BTC')