4. 数据源准备(下):获取链上交易量、活跃地址数、链上大额转账数据
上一节我们把价格数据搞定了。但说实话,光看价格做恐慌贪婪指数,就像只看体温不看血常规——太片面了。
链上数据才是真正的「硬指标」。交易量是真是假?地址活跃度如何?有没有大户在悄悄转移筹码?这些信息,都藏在区块链的原始数据里。
今天我们就来搞定三个核心指标:链上交易量、活跃地址数、链上大额转账。我会用 Glassnode 和 CoinMetrics 的 API 来演示。
4.1 为什么是这三个指标?
你想想看,市场情绪最终会反映在链上行为上:
- 链上交易量:反映的是真实的价值转移。交易所里的交易量可以刷,但链上转账是要付 Gas 费的,造假成本高得多。
- 活跃地址数:说白了就是「有多少人在用这条链」。地址数飙升,说明新用户进场;地址数萎缩,说明市场冷清。
- 链上大额转账:这个我最看重。大户(鲸鱼)的动向往往领先于价格。我曾经在 2021 年 5 月观察到连续三天的大额 BTC 转往交易所,结果一周后市场就崩了。
这三个指标组合起来,基本能勾勒出市场的「真实温度」。
4.2 Glassnode API 实战
Glassnode 是目前链上数据最全的平台之一。我个人习惯用它来做深度分析,因为它的指标定义很严谨。
首先,你需要去 glassnode.com 注册账号,拿到 API Key。免费版有调用次数限制,但做回测足够了。
4.2.1 获取链上交易量
Glassnode 把交易量分为两种:Transfer Volume(转账量)和 Exchange Flow(交易所进出量)。我们这里用前者。
import requests
import pandas as pd
from datetime import datetime, timedelta
API_KEY = "你的API_KEY"
BASE_URL = "https://api.glassnode.com/v1/metrics/transactions/transfers_volume"
# 设置参数
params = {
"a": "BTC", # 资产
"s": "2023-01-01", # 开始日期
"u": "2023-12-31", # 结束日期
"i": "24h", # 时间粒度
"api_key": API_KEY
}
# 发起请求
response = requests.get(BASE_URL, params=params)
data = response.json()
# 转为 DataFrame
df_volume = pd.DataFrame(data)
df_volume['t'] = pd.to_datetime(df_volume['t'], unit='s')
df_volume.columns = ['timestamp', 'transfer_volume']
print(df_volume.head())
4.2.2 获取活跃地址数
活跃地址的定义是:在给定时间窗口内,至少参与过一次交易(发送或接收)的唯一地址数。
# 活跃地址数 API
URL_ACTIVE = "https://api.glassnode.com/v1/metrics/addresses/active_count"
params_active = {
"a": "BTC",
"s": "2023-01-01",
"u": "2023-12-31",
"i": "24h",
"api_key": API_KEY
}
resp_active = requests.get(URL_ACTIVE, params=params_active)
df_active = pd.DataFrame(resp_active.json())
df_active['t'] = pd.to_datetime(df_active['t'], unit='s')
df_active.columns = ['timestamp', 'active_addresses']
嗯,这里要注意:活跃地址数在周末通常会下降,因为机构交易者休息了。这不是市场恐慌,是正常的周期性波动。做指数时最好做周度平滑处理。
4.2.3 获取大额转账数据
大额转账,Glassnode 定义为单笔金额超过 10 BTC 或 100 BTC 的交易。我个人习惯用 100 BTC 作为阈值,因为这才是真正的「鲸鱼级别」。
# 大额转账(≥100 BTC)
URL_LARGE = "https://api.glassnode.com/v1/metrics/transactions/transfers_volume_large"
params_large = {
"a": "BTC",
"s": "2023-01-01",
"u": "2023-12-31",
"i": "24h",
"api_key": API_KEY,
"f": "USD", # 以美元计价
"t": "100" # 阈值:100 BTC
}
resp_large = requests.get(URL_LARGE, params=params_large)
df_large = pd.DataFrame(resp_large.json())
df_large['t'] = pd.to_datetime(df_large['t'], unit='s')
df_large.columns = ['timestamp', 'large_transfer_volume_usd']
4.3 CoinMetrics API 作为备选
Glassnode 虽好,但免费额度有限。如果你需要更灵活的数据获取方式,CoinMetrics 的社区版 API 是个不错的选择。
CoinMetrics 的数据更「原始」一些,需要自己计算指标。但好处是:你可以自定义时间粒度和资产范围。
# CoinMetrics 社区版 API 示例
import json
CM_API_KEY = "你的CoinMetrics_API_KEY"
CM_BASE = "https://community-api.coinmetrics.io/v4"
# 获取 BTC 的链上交易量
url_cm = f"{CM_BASE}/timeseries/asset-metrics"
params_cm = {
"assets": "btc",
"metrics": "TxTfrValAdjUSD", # 调整后的转账量(美元)
"frequency": "1d",
"start_time": "2023-01-01",
"end_time": "2023-12-31",
"api_key": CM_API_KEY
}
resp_cm = requests.get(url_cm, params=params_cm)
data_cm = resp_cm.json()
# 解析数据
records = []
for item in data_cm.get('data', []):
records.append({
'timestamp': item['time'],
'adjusted_volume_usd': float(item['TxTfrValAdjUSD'])
})
df_cm = pd.DataFrame(records)
print(df_cm.head())
- Glassnode:指标丰富,开箱即用,适合快速搭建原型
- CoinMetrics:数据更底层,灵活性高,适合自定义计算
4.4 数据清洗与合并
三个指标的数据格式可能不一致,需要统一处理。我习惯的做法是:
- 将所有时间戳统一为 UTC 日期格式(YYYY-MM-DD)
- 按日期做左连接,确保数据对齐
- 处理缺失值(用前向填充或插值)
# 合并三个数据源
df_volume['date'] = df_volume['timestamp'].dt.date
df_active['date'] = df_active['timestamp'].dt.date
df_large['date'] = df_large['timestamp'].dt.date
# 合并
df_merged = df_volume[['date', 'transfer_volume']].merge(
df_active[['date', 'active_addresses']], on='date', how='left'
).merge(
df_large[['date', 'large_transfer_volume_usd']], on='date', how='left'
)
# 处理缺失值
df_merged = df_merged.fillna(method='ffill')
# 添加日期索引
df_merged.set_index('date', inplace=True)
print(df_merged.tail())
4.5 本章知识体系
下面这张图概括了我们今天讲的核心逻辑:
从图中可以看到,两个数据源是互补关系。Glassnode 提供现成指标,CoinMetrics 提供原始数据。最终三个指标经过清洗合并后,成为恐慌贪婪指数的核心输入。
好了,链上数据这块就讲到这里。下一节我们会把这些数据组合起来,真正开始构建恐慌贪婪指数。到时候你会发现——原来市场情绪是可以「量化」的。
公众号:蓝海数据掘金营,微信deep3321