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())
小技巧:Glassnode 返回的时间戳是 Unix 秒数,记得转换。我刚开始用的时候忘了这步,画出来的图时间轴全乱了。

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']
避坑指南:我曾经遇到过一个问题——大额转账数据在某些日期会突然归零。后来发现是 Glassnode 的数据更新有延迟,通常要等 2-3 个区块确认。所以建议拉数据时,至少留出 6 小时的缓冲时间。

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:数据更底层,灵活性高,适合自定义计算
我个人建议:初期用 Glassnode 快速验证想法,后期迁移到 CoinMetrics 做精细化回测。

4.4 数据清洗与合并

三个指标的数据格式可能不一致,需要统一处理。我习惯的做法是:

  1. 将所有时间戳统一为 UTC 日期格式(YYYY-MM-DD)
  2. 按日期做左连接,确保数据对齐
  3. 处理缺失值(用前向填充或插值)
# 合并三个数据源
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())
关键点:链上数据有时会有「空洞」(比如节点维护导致数据缺失)。千万别直接 dropna,用前向填充更合理——因为链上行为是连续的,昨天的数据可以近似代表今天。

4.5 本章知识体系

下面这张图概括了我们今天讲的核心逻辑:

链上数据获取流程 Glassnode API CoinMetrics API 备选/补充 链上交易量 活跃地址数 大额转账数据 数据清洗与合并 恐慌贪婪指数输入

从图中可以看到,两个数据源是互补关系。Glassnode 提供现成指标,CoinMetrics 提供原始数据。最终三个指标经过清洗合并后,成为恐慌贪婪指数的核心输入。

我的建议:不要只依赖一个数据源。我曾在回测中发现 Glassnode 的某个指标突然断更,幸好有 CoinMetrics 的数据做备份。多一个数据源,多一份安心。

好了,链上数据这块就讲到这里。下一节我们会把这些数据组合起来,真正开始构建恐慌贪婪指数。到时候你会发现——原来市场情绪是可以「量化」的。


公众号:蓝海数据掘金营,微信deep3321