BlockVectra

DEX 代币日度价格数据集(dex_price_daily / v_dex_price_daily)

对应 SQL:schema/clickhouse/derived/031_dex_prices.sql。

对应 SQL:schema/clickhouse/derived/031_dex_prices.sql。

从合并后的 DEX 交易与池子数据(008_dex.sql,包含 Uniswap V3 与 V4)派生每日、每资产对的交易量、交易笔数、精确有理数 OHLC 价格(开盘/收盘/最高/最低),并通过视图提供经代币精度换算后的成交量加权平均价(VWAP)展示。


1. 安装与补算

1.1 安装方式

与衍生数据集一致,替换库名占位符 {db} 后执行:

sed 's/{db}/robinhood/g' schema/clickhouse/derived/031_dex_prices.sql | clickhouse-client --multiquery

如果使用 HTTP 接口(不支持多语句批处理),请按 ; 拆分逐条发送。

1.2 调度与幂等刷新机制

  • 每日定时刷新(物化视图): mv_dex_price_daily 是定时刷新物化视图(REFRESH EVERY 1 DAY OFFSET 1 HOUR RANDOMIZE FOR 30 MINUTE APPEND),每天 UTC 01:00 对过去 3 天的已关闭日期([today() - 3, today()))基于底层 FINAL 表重新从头聚合。
  • 历史回填(Backfill): 建表后可执行文件中附带的 INSERT INTO {db}.dex_price_daily ... WHERE toDate(s.block_timestamp) < today() 对历史上所有已结算日期进行一次性补算。
  • 幂等性与重组修复: 目标表采用 ENGINE = ReplacingMergeTree(refreshed_at),主键为 (day, token, quote_token)。无论物化视图周期刷新还是多次手动回填,同一天同一交易对的新计算行都会以最新的 refreshed_at 覆盖旧行,在 FINAL 读取和后台合并时完全消除重复,天然吸收区块链重组和补算重叠。

2. 链上计价代币(Quote Tokens)研究与选型

通过在生产 ClickHouse(只读、max_threads=2)和 RPC 节点对 Robinhood Chain(Chain ID 4663,高度 ~72M)的数千万笔交易日志和池子进行统计,确认本链没有以太坊主网常见的原生 USDC / USDT 跨链流通,而是以以下三种代币构成核心流动性结算体系:

  1. USDG(0x5fc5360d0400a0fd4f2af552add042d716f1d168):
    • 官方与 Paxos / Global Dollar Network 合作发行的原生合规美元稳定币,decimals = 6。
    • 所有股票代币(TSLA、AAPL、NVDA 等)和主要法币交易对均以 USDG 为基准计价代币。
  2. WETH(0x0bd7d308f8e1639fab988df18a8011f41eacad73):
    • 标准 ERC-20 封装以太坊代币,decimals = 18。Uniswap V3 池子绝大多数以此作为报价币。
  3. 原生 ETH(0x0000000000000000000000000000000000000000):
    • Uniswap V4 单例(PoolManager)中原生货币直接作为 Currency 使用全零地址,无需经过 WETH 封装,decimals = 18。在 V4 中有大量山寨币/社区代币直接与原生 ETH 配对。

报价优先级规则

为了确保交易对报价方向符合金融直觉(例如 WETH/USDG 输出以 USDG 计价的 WETH 价格,而非以 WETH 计价的 USDG 价格):

  • 优先级 2:USDG(法币稳定币,最高优先级报价币)
  • 优先级 1:WETH 与 原生 ETH(加密基准资产)
  • 优先级 0:其他代币(作为 Base Token)

当池中包含两个代币时:

  • 若仅有一个为计价币,计价币自动作为 quote_token,另一代币作为 token。
  • 若两者均为计价币(如 WETH 与 USDG 配对),优先级更高的 USDG 作为 quote_token,WETH 作为 token。
  • 若两者优先级相同(如原生 ETH 与 WETH 配对),按地址排序区分,保证确定性。
  • 若两者均非计价币,不作为标准基准报价对入库。

3. 设计与正确性保证(严格金钱安全)

3.1 为什么必须对 CLOSED 周期基于 FINAL 聚合

dex_swaps 属于 ReplacingMergeTree(version, is_deleted)。在回填中断重试、分段并发写入或链重组时,底层日志会包含同一事件的多版本插入或带更高 version 的 is_deleted = 1 墓碑行。 若使用针对每笔写入即时触发的累加物化视图(SUM/COUNT),会对未去重的物理行重复累加,造成金额和笔数虚高。 因此必须采用方案 (b):仅针对已完结的 UTC 自然日(toDate(block_timestamp) < today()),在 FINAL 且 is_deleted = 0 的权威快照上计算每日指标,实现完全幂等与自愈。

3.2 绝对零浮点:精确有理数与整数算术

  • 底层表 dex_price_daily 全程使用整数: 成交量为绝对值总和 UInt256。所有价格点(开盘 first_price、收盘 last_price、最低 min_price、最高 max_price)均直接保留单笔 Swap 发生时的原始成交金额分子与分母: $$\text{Price} = \frac{\text{quote_amount_raw}}{\text{base_amount_raw}}$$ 分子 quote_amount_raw(UInt256)与分母 base_amount_raw(UInt256)原样落盘,杜绝任何有损精度舍入。
  • 最低/最高价确定性极值排序: ClickHouse 内置极值比较时使用纯整数商及高精度余数商元组: tuple(intDiv(quote_raw, base_raw), intDiv((quote_raw % base_raw) * 10^25, base_raw), block_number, log_index),既防止了 UInt256 乘法溢出,又能在 25 位小数精度下准确确定单笔成交极值,且无任何浮点数介入。

3.3 视图 VWAP 的 Decimal 展示换算

v_dex_price_daily 视图从 {db}.tokens 读取代币精度 $d_{\text{base}}$ 与 $d_{\text{quote}}$。 真实成交量加权平均价公式为: $$\text{VWAP}{\text{human}} = \frac{\sum Q{\text{raw}}}{\sum B_{\text{raw}}} \times \frac{10^{d_{\text{base}}}}{10^{d_{\text{quote}}}}$$

  • 10 的次幂全部通过字符串构造:toUInt256(concat('1', repeat('0', ...))),严禁使用会转化为 Float64 的 pow(10, n)。
  • 通过整数商与余数构造字符串后,再通过 toDecimal256(..., 18) 输出为精确的 18 位定点小数,满足展示需求。

4. 表结构与视图定义

4.1 表 dex_price_daily

字段类型说明
dayDateUTC 结算日期
tokenFixedString(20)标的资产代币地址(Base Token)
quote_tokenFixedString(20)计价货币代币地址(Quote Token)
swap_countUInt64当日有效成交笔数
base_volume_rawUInt256标的代币原始成交总量(绝对值之和)
quote_volume_rawUInt256计价代币原始成交总量(绝对值之和)
first_price_numeratorUInt256当日第一笔交易计价代币原始金额(开盘价分子)
first_price_denominatorUInt256当日第一笔交易标的代币原始金额(开盘价分母)
last_price_numeratorUInt256当日最后一笔交易计价代币原始金额(收盘价分子)
last_price_denominatorUInt256当日最后一笔交易标的代币原始金额(收盘价分母)
min_price_numeratorUInt256当日最低成交价对应交易的计价代币金额(最低价分子)
min_price_denominatorUInt256当日最低成交价对应交易的标的代币金额(最低价分母)
max_price_numeratorUInt256当日最高成交价对应交易的计价代币金额(最高价分子)
max_price_denominatorUInt256当日最高成交价对应交易的标的代币金额(最高价分母)
refreshed_atDateTime('UTC')聚合计算刷新时间戳(兼作 ReplacingMergeTree 版本列)

4.2 视图 v_dex_price_daily

在基础表之上关联 {db}.tokens,补充可读符号并在展示层格式化:

  • token_symbol / token_name: 标的代币名称与符号
  • quote_symbol / quote_name: 计价币名称与符号(USDG / WETH / ETH)
  • base_volume: 标的代币人类可读交易量(Decimal(76, 18))
  • quote_volume: 计价代币人类可读交易量(Decimal(76, 18))
  • vwap: 成交量加权平均价(Decimal(76, 18))
  • first_price / last_price / min_price / max_price: 经精度调整的人类可读 OHLC 价格(Decimal(76, 18))
  • 以及对应的原始有理数分子/分母字段

5. 本地全链路独立验证(精确对账证据)

5.1 验证方法

在本地 ClickHouse 独立 Scratch 数据库中,加载 Robinhood Chain 真实区块历史交易与池子(包含 Uniswap V3 与 V4 真实交易):

  1. 应用 sql/tokens.sql,并从 RPC 链上节点查询各代币真实 name、symbol、decimals 写入 tokens 表。
  2. 运行 031_dex_prices.sql 生成 dex_price_daily 与视图 v_dex_price_daily。
  3. 编写独立的 Python 验证程序(采用 Python decimal.Decimal,精度设为 100 位,不依赖 ClickHouse 计算逻辑),直接从最底层单笔 dex_swaps 原始行逐笔模拟累加和价格比较,核对 3 个典型池子及全部交易对。

5.2 对账结果(3 个池子 2026-09-25 真实数据,100% 精确匹配)

池子 1:Agrippa / ETH(Uniswap V4 原生代币池)

  • 标的代币:0x1785EC2BD68C72042711A9EF36AF93C9AECB5BA3(18 decimals)
  • 计价代币:0x0000000000000000000000000000000000000000(原生 ETH,18 decimals)
指标ClickHouse 结果独立 Python Decimal 计算对账状态
swap_count7070EXACT MATCH
base_volume_raw205795031621476504045885807205795031621476504045885807EXACT MATCH
quote_volume_raw72411321373726186977241132137372618697EXACT MATCH
first_price (分子/分母)1998242000000 / 873165529688832393451998242000000 / 87316552968883239345EXACT MATCH
last_price (分子/分母)16721066000870489 / 36428891723173693302705616721066000870489 / 364288917231736933027056EXACT MATCH
min_price (分子/分母)1998242000000 / 873165529688832393451998242000000 / 87316552968883239345EXACT MATCH
max_price (分子/分母)99000000000000000 / 210849597985473738624198099000000000000000 / 2108495979854737386241980EXACT MATCH
vwap (Decimal18)0.0000000351861368090.000000035186136809EXACT MATCH

池子 2:GRAILS / WETH(Uniswap V3 池)

  • 标的代币:0xC410396E1087E75B3FC1CEFE7A48BCF6E88A878C(18 decimals)
  • 计价代币:0x0BD7D308F8E1639FAB988DF18A8011F41EACAD73(WETH,18 decimals)
指标ClickHouse 结果独立 Python Decimal 计算对账状态
swap_count4747EXACT MATCH
base_volume_raw199322493804688194436351258199322493804688194436351258EXACT MATCH
quote_volume_raw11619775315469342341161977531546934234EXACT MATCH
first_price (分子/分母)500000000000000 / 99971646275875362838747500000000000000 / 99971646275875362838747EXACT MATCH
last_price (分子/分母)199000000000000 / 31214184411439729473297199000000000000 / 31214184411439729473297EXACT MATCH
min_price (分子/分母)500000000000000 / 99971646275875362838747500000000000000 / 99971646275875362838747EXACT MATCH
max_price (分子/分母)25831314425596850 / 403427113490495242000000025831314425596850 / 4034271134904952420000000EXACT MATCH
vwap (Decimal18)0.0000000058296357290.000000005829635729EXACT MATCH

池子 3:PEAR / USDG(Uniswap V4 跨精度稳定币计价池)

  • 标的代币:0x383562778894760D53A247C97686284931BB28CC(18 decimals)
  • 计价代币:0x5FC5360D0400A0FD4F2AF552ADD042D716F1D168(USDG,6 decimals)
指标ClickHouse 结果独立 Python Decimal 计算对账状态
swap_count33EXACT MATCH
base_volume_raw4517260685130932755212145172606851309327552121EXACT MATCH
quote_volume_raw2832397928323979EXACT MATCH
first_price (分子/分母)982036 / 1526082920877114310237982036 / 1526082920877114310237EXACT MATCH
last_price (分子/分母)1070867 / 17525863263300000000001070867 / 1752586326330000000000EXACT MATCH
min_price (分子/分母)1070867 / 17525863263300000000001070867 / 1752586326330000000000EXACT MATCH
max_price (分子/分母)982036 / 1526082920877114310237982036 / 1526082920877114310237EXACT MATCH
vwap (Decimal18)0.0006270167026939910.000627016702693991EXACT MATCH

此外,本地测试集中的全部 9/9 个交易对在上述核对中均达到了 100% 精确匹配。


6. 常用示例查询

6.1 查询指定代币的历史每日 VWAP 与交易量

SELECT
    day,
    token_symbol,
    quote_symbol,
    swap_count,
    base_volume,
    quote_volume,
    vwap,
    min_price,
    max_price
FROM robinhood.v_dex_price_daily
WHERE token_symbol = 'TSLA'
  AND quote_symbol = 'USDG'
ORDER BY day DESC
LIMIT 30;

6.2 查询某日全链交易量最大的代币价格看板

SELECT
    token_symbol,
    quote_symbol,
    swap_count,
    quote_volume,
    vwap,
    first_price AS open_price,
    last_price  AS close_price,
    min_price   AS low_price,
    max_price   AS high_price
FROM robinhood.v_dex_price_daily
WHERE day = '2026-09-24'
ORDER BY quote_volume_raw DESC
LIMIT 20;

6.3 使用原始有理数分子分母进行自定义超高精度算术

SELECT
    day,
    hex(token) AS token_hex,
    hex(quote_token) AS quote_token_hex,
    toString(first_price_numerator)   AS first_num,
    toString(first_price_denominator) AS first_den,
    toString(last_price_numerator)    AS last_num,
    toString(last_price_denominator)  AS last_den
FROM robinhood.dex_price_daily FINAL
WHERE day = '2026-09-24'
ORDER BY swap_count DESC
LIMIT 10;

本页目录