◈ Contents
-
→ What Is MVRV and Why On-Chain Traders Rely on It
-
→ Getting Started: Glassnode API Keys and Plan Requirements
-
→ Fetching MVRV Data: Your First Real API Call
-
→ Parsing the Response and Building an MVRV Signal Engine
-
→ Integrating MVRV into a Live Crypto Trading Workflow
-
→ Frequently Asked Questions
-
→ Conclusion
The MVRV ratio is one of the most battle-tested on-chain indicators in crypto. It compares Bitcoin's market capitalization to its realized capitalization — effectively telling you whether the average coin holder is sitting on a profit or a loss. When MVRV dips below 1, the market is statistically near a cycle bottom. When it stretches above 3.5, history says start taking profits. The problem? Most traders eyeball MVRV on a chart and react emotionally. The real edge comes from automating it — pulling raw MVRV data directly from the Glassnode API, parsing it programmatically, and triggering alerts before the crowd notices the signal. This guide gives you working Python code to do exactly that.
What Is MVRV and Why On-Chain Traders Rely on It
MVRV stands for Market Value to Realized Value. Market value is simply the current price multiplied by circulating supply — standard market cap. Realized value is more nuanced: it prices each Bitcoin at the value it last moved on-chain, creating an aggregate cost basis for the entire market. The ratio between these two numbers reveals whether the market is trading at a premium or discount relative to what participants actually paid.
Historically, MVRV below 1.0 has marked generational buying opportunities — the 2015 bottom, the March 2020 crash, and the late-2022 cycle low all printed MVRV under 1. Conversely, readings above 3.5 to 4.0 have consistently preceded major corrections. This is why institutional desks, algorithmic funds, and platforms like VoiceOfChain incorporate MVRV into their signal stacks alongside price action and derivatives data.
Unlike RSI or MACD which are derived purely from price, MVRV measures actual on-chain holder behavior — the real profit and loss position of every BTC participant. That structural difference makes it harder to manipulate and more durable across full market cycles.
MVRV Ratio Zones and Historical Interpretation
| MVRV Range | Market Signal | Typical Action |
| < 1.0 | Extreme undervaluation | Strong accumulation — capitulation zone |
| 1.0 – 2.0 | Undervalued to fair value | Accumulate — historically high reward/risk |
| 2.0 – 3.5 | Fair to slightly overvalued | Hold — tighten stops, watch for distribution |
| > 3.5 | Overheated / euphoria zone | Reduce exposure — aligns with historical cycle tops |
Getting Started: Glassnode API Keys and Plan Requirements
Glassnode gates its metrics behind subscription tiers. The free tier covers basic price and volume data — but MVRV requires at minimum the Advanced plan. The Professional plan unlocks higher resolution data including hourly intervals and longer historical windows, which matters if you are running intraday strategies using Binance or Bybit futures.
Once subscribed, navigate to your Glassnode account settings and generate an API key. Store it as an environment variable — never hardcode it in source files, especially if you push to a public repository. The Glassnode REST API follows a consistent structure: every metric lives at https://api.glassnode.com/v1/metrics/{category}/{metric_name}. The MVRV endpoint is /v1/metrics/market/mvrv. All requests are GET calls with query parameters, and your key goes in as the api_key parameter.
import requests
import os
API_KEY = os.getenv("GLASSNODE_API_KEY", "your_api_key_here")
BASE_URL = "https://api.glassnode.com/v1/metrics"
def test_connection():
"""Verify API key and connectivity before running live queries."""
endpoint = f"{BASE_URL}/market/price_usd_close"
params = {
"a": "BTC",
"api_key": API_KEY,
"i": "24h"
}
try:
r = requests.get(endpoint, params=params, timeout=10)
if r.status_code == 200:
print("Glassnode API: connected successfully")
return True
elif r.status_code == 401:
print("Authentication failed — check your API key")
elif r.status_code == 403:
print("Access denied — this metric requires a higher plan")
else:
print(f"Unexpected status: {r.status_code}")
return False
except requests.exceptions.ConnectionError:
print("Network error — check your internet connection")
return False
except requests.exceptions.Timeout:
print("Request timed out — Glassnode may be slow, retry later")
return False
test_connection()
Fetching MVRV Data: Your First Real API Call
With authentication confirmed, you can query the MVRV endpoint directly. The most useful parameters are: a (asset — BTC, ETH, etc.), i (interval — 24h for daily, 1h for hourly on paid plans), s and u (Unix timestamps for start and end dates), and f (response format, default JSON). For cycle analysis, daily resolution is sufficient and keeps your payload small. If you are running a more tactical strategy — monitoring MVRV shifts during a Bybit or OKX liquidation cascade, for example — hourly data gives you faster signal. The function below includes proper error handling for the most common failure modes including rate limits and plan access errors.
import requests
import os
from datetime import datetime, timedelta
API_KEY = os.getenv("GLASSNODE_API_KEY")
BASE_URL = "https://api.glassnode.com/v1/metrics"
def fetch_mvrv(asset="BTC", days=365, interval="24h"):
"""
Fetch MVRV ratio from Glassnode API.
Args:
asset: Ticker symbol (BTC, ETH, SOL, etc.)
days: Number of historical days to fetch
interval: Data resolution ('24h', '1h', '10m')
Returns:
List of dicts with 't' (timestamp) and 'v' (value), or None on error
"""
endpoint = f"{BASE_URL}/market/mvrv"
since_ts = int((datetime.now() - timedelta(days=days)).timestamp())
params = {
"a": asset,
"api_key": API_KEY,
"i": interval,
"s": since_ts,
"f": "JSON"
}
try:
response = requests.get(endpoint, params=params, timeout=20)
response.raise_for_status()
data = response.json()
print(f"Fetched {len(data)} MVRV data points for {asset}")
return data
except requests.exceptions.HTTPError as e:
status = response.status_code
if status == 403:
print("MVRV requires Glassnode Advanced plan or higher")
elif status == 429:
print("Rate limited — back off and retry in 60 seconds")
else:
print(f"HTTP {status}: {e}")
return None
except requests.exceptions.Timeout:
print("Request timed out — try reducing the date range")
return None
except Exception as e:
print(f"Unexpected error: {e}")
return None
# Fetch 1 year of daily BTC MVRV
btc_mvrv = fetch_mvrv("BTC", days=365, interval="24h")
if btc_mvrv:
print(f"Latest data point: {btc_mvrv[-1]}")
Parsing the Response and Building an MVRV Signal Engine
The Glassnode API returns a JSON array where each element has two keys: t (Unix timestamp) and v (metric value). Converting this into a pandas DataFrame takes two lines, and from there you can apply any signal logic that fits your strategy. The function below parses the raw response, classifies the current MVRV reading into a market zone, and prints a tradeable signal. This same output can feed into a Telegram alert bot, a webhook to Binance or Coinbase, or an aggregated signal dashboard. VoiceOfChain, for example, combines on-chain metrics like MVRV with funding rates and exchange netflow data to deliver real-time alerts without requiring traders to maintain their own data pipelines.
import pandas as pd
# MVRV signal zones calibrated to BTC historical cycle data
MVRV_ZONES = [
(float("-inf"), 1.0, "STRONG BUY", "Capitulation — average holder at a loss"),
(1.0, 2.0, "BUY", "Undervalued — historically high reward/risk"),
(2.0, 3.5, "HOLD", "Fair value — watch for distribution signals"),
(3.5, float("inf"), "REDUCE", "Overheated — aligns with historical cycle tops"),
]
def classify_mvrv(value):
for low, high, signal, reason in MVRV_ZONES:
if low <= value < high:
return signal, reason
return "UNKNOWN", "Value outside expected range"
def parse_and_signal(raw_data):
if not raw_data:
print("No data to parse")
return None
df = pd.DataFrame(raw_data)
df["timestamp"] = pd.to_datetime(df["t"], unit="s")
df["mvrv"] = pd.to_numeric(df["v"], errors="coerce")
df = df[["timestamp", "mvrv"]].dropna().sort_values("timestamp").reset_index(drop=True)
latest = df.iloc[-1]
signal, reason = classify_mvrv(latest["mvrv"])
print("=" * 52)
print(f"Date: {latest['timestamp'].date()}")
print(f"MVRV: {latest['mvrv']:.4f}")
print(f"Signal: {signal}")
print(f"Reason: {reason}")
print("=" * 52)
return df
# Full pipeline: fetch -> parse -> signal
raw = fetch_mvrv("BTC", days=730)
df = parse_and_signal(raw)
# Export for further analysis or backtest
if df is not None:
df.to_csv("btc_mvrv.csv", index=False)
print(f"Saved {len(df)} rows to btc_mvrv.csv")
Integrating MVRV into a Live Crypto Trading Workflow
Raw MVRV data only creates value when it connects to your actual trading setup. Here is how experienced traders wire it in across different styles.
For spot accumulation on Binance or Coinbase, MVRV works best as a position sizing multiplier. When MVRV is below 1.5, deploy maximum DCA allocation. When it climbs above 3.0, scale back to 25% of your normal buy size or pause entirely. This mechanical rule has outperformed unstructured buy-and-hold across the last two full BTC cycles.
For derivatives traders on Bybit, OKX, or Bitget, MVRV provides macro regime context for your directional bias. Running aggressive BTC longs when MVRV is above 3.5 is swimming against structural tide. Use it as a filter: if your momentum model says long but MVRV is signaling overheated conditions, cut position size by half and tighten your stop.
For algo builders, schedule fetch_mvrv() to run nightly via cron or a cloud scheduler. Store readings to a time-series database, compare against yesterday's value to detect zone transitions, and fire a webhook alert when the signal flips. Keep rate limits in mind — build in exponential backoff, and never loop requests without delay, especially if you are fetching multiple assets like BTC, ETH, and SOL in parallel. Use asyncio or a simple queue to stagger calls cleanly.
MVRV is a lagging indicator by design — realized prices update as coins move on-chain, not tick-by-tick. Never use it as a precise entry or exit trigger. Use it as a regime filter: it tells you what zone the market is in, not exactly when to click the button. Pair it with price structure or funding rates for execution timing.
Frequently Asked Questions
Do I need a paid Glassnode plan to access the MVRV API?
Yes. MVRV is classified as an Advanced metric on Glassnode, requiring at minimum the Advanced subscription tier. The free tier only covers basic price and volume endpoints. Hourly MVRV resolution for shorter-term strategies requires the Professional plan.
What is the exact Glassnode API endpoint for MVRV?
The endpoint is https://api.glassnode.com/v1/metrics/market/mvrv. Pass your key as the api_key query parameter, the asset as a (e.g. BTC), and the interval as i (24h for daily). The response is a JSON array of objects with t (Unix timestamp) and v (MVRV value).
Can I fetch MVRV data for ETH or other altcoins?
Yes, change the a parameter to ETH, SOL, LTC, or any other asset Glassnode supports. Not all assets have the same historical depth as Bitcoin — some altcoins have shorter data histories. Check the Glassnode metric coverage page before building a production pipeline around a specific asset.
How often does Glassnode MVRV data update?
Daily MVRV data updates roughly every 24 hours, typically in early UTC hours after the previous day's on-chain data is finalized. Hourly data updates more frequently but carries a short lag. For cycle regime monitoring, daily resolution is usually sufficient since MVRV moves slowly relative to price.
What does a 403 error mean when calling the MVRV endpoint?
A 403 means your current plan does not include access to that metric. Upgrading your Glassnode subscription resolves it. Also confirm you are using the API key tied to the subscribed account — it is easy to accidentally test with a free-tier key from a different account.
Is MVRV reliable for altcoins, or only for Bitcoin?
MVRV is most battle-tested on Bitcoin where multiple full market cycles validate the signal zones. For altcoins, treat the same thresholds as rough guides — alt markets have different holder behavior and shorter histories, so the 1.0 and 3.5 thresholds may need calibration. Use BTC MVRV as your primary macro regime filter and apply it as context across all markets.
Conclusion
The Glassnode MVRV API is one of the cleaner on-chain data feeds to work with — consistent JSON response format, straightforward authentication, and a metric with a genuine multi-cycle track record on Bitcoin. The three code blocks in this guide give you a complete working pipeline: authenticate, fetch, parse, and generate a signal. From here the natural next steps are scheduling nightly runs, persisting readings to a time-series database, and routing zone-change alerts into your trading setup on Binance, OKX, or Bybit. If you want MVRV alongside other on-chain signals without maintaining your own data infrastructure, VoiceOfChain aggregates metrics like MVRV, exchange netflows, and funding rates into a unified real-time signal feed built specifically for active crypto traders.