BlockVectra

Robinhood Chain 代币化股票市场(Stock Token Market)数据集

Robinhood Chain 的旗舰核心应用场景:将传统美股及 ETF 资产代币化上链并在生态中流通与交易。

This content is sourced from upstream and is currently available in Chinese only.

Robinhood Chain 的旗舰核心应用场景:将传统美股及 ETF 资产代币化上链并在生态中流通与交易。

本数据集以已合并的代币化股票注册表(007_stock_tokens.sql 中的 {db}.stock_tokens)、ERC-20 余额数据(027_erc20_balances.sql:{db}.erc20_balance_moves 是建在 {db}.erc20_transfers FINAL 上的余额变动视图,{db}.erc20_balances 是每 6 小时整表刷新的紧凑余额表,最多滞后一个刷新周期)以及去中心化交易池(008_dex.sql 中的 {db}.dex_swaps_enriched / {db}.dex_pools)为基础,提供按自然日收盘汇总的股票代币市场大盘统计表 {db}.stock_token_daily,以及最新收盘日的综合活跃度排行视图 {db}.stock_token_leaderboard。


1. 为什么采用「已收尾日期的幂等刷新(Idempotent Refresh from FINAL)」

1.1 底层 ReplacingMergeTree 的物理特性

底层数据源表({db}.erc20_transfers、{db}.dex_swaps,以及 {db}.erc20_balance_moves 底层所读的 {db}.erc20_transfers)均为 ReplacingMergeTree(version, is_deleted);{db}.erc20_balance_moves 自 2026-09 磁盘瘦身改版起是普通 VIEW(对 {db}.erc20_transfers FINAL 做 UNION ALL 展开 debit/credit 两侧,见 docs/design/0005-erc20-balances.md),列名与去重/重组语义都和旧物化台账一致:

  1. 断点续跑(Backfill Resume):回填任务重启时,边界重叠插入同版本相同主键的物理行,依赖 FINAL 自动折叠去重。
  2. 链重组(Reorg Tombstones):被回滚的分叉交易以 is_deleted = 1 伴随更高 version 的墓碑行重新写入,依赖 FINAL 滤除。

如果使用基于物理 INSERT 触发的普通物化视图(Insert-trigger MV)进行累计求和(sum/count),在物理写入阶段 FINAL 去重尚未发生,会导致回填重叠和回滚交易被双重甚至多重计数(Double Counting)。

1.2 集合状态指标的非累加性

诸如「日终非零持币地址数(holder_count)」与「持仓前 10 大地址占比(top10_holder_share_bps)」属于非累加性(Non-additive)状态指标,无法通过单笔流式增量维护,必须在某日截断点基于全量台账去重计算。

1.3 方案设计

  • 采用 已收尾日期的幂等刷新(Closed-day Idempotent Refresh):每日定时调度任务仅在 UTC 自然日完全结束且经过充分缓冲时间(默认 --min-lag-hours 2.0)后,基于底层各表的 FINAL 视图进行计算写入。
  • 目标表 {db}.stock_token_daily 使用 ReplacingMergeTree(version) 引擎,按月分区 PARTITION BY toYYYYMM(day),排序键为 (day, token)。
  • 重复刷新某一日的数据会生成更高版本号的确定性计算结果,FINAL 合并时自动覆盖旧记录,保证全链路幂等。

2. 金额安全与整数精度规则(Money Safety & Integer Precision)

本数据集严格遵守项目金额安全与防溢出原则:

  1. 无浮点计算:所有原生代币量(mint_raw_amount、burn_raw_amount、dex_raw_volume)均为链上原始无符号整数 UInt256。
  2. 净发行变量符号:net_supply_change 定义为带符号大整数 Int256(即 toInt256(mint_raw_amount) - toInt256(burn_raw_amount)),真实反映当日发行量的净增减。
  3. 持仓集中度基点(Basis Points):top10_holder_share_bps 表示持仓排名前 10 的有效地址所持代币占总有效流通量的比例,单位为基点(1 bps = 0.01%,10000 bps = 100.00%)。计算完全在 ClickHouse 中通过纯整数算术完成: $$\text{top10_holder_share_bps} = \operatorname{intDiv}(\text{top10_balance_sum} \times 10000, \text{total_balance_sum})$$ 完全避免了引入 Float64 浮点误差。
  4. 零地址哨兵过滤:在统计 transfers、unique_senders、unique_receivers 时,零地址(0x00...00)作为铸造与销毁哨兵不计入真实发送者/接收者集合;持币地址统计严格要求 holder != 0x00...00 且 balance > 0。

3. 表与视图定义

对应 SQL 脚本:schema/clickhouse/derived/032_stock_market.sql。

3.1 每日市场指标表 {db}.stock_token_daily

CREATE TABLE IF NOT EXISTS {db}.stock_token_daily
(
    day                     Date            COMMENT 'UTC 统计日期',
    token                   FixedString(20) COMMENT '股票代币合约地址',
    symbol                  String          COMMENT '代币符号(如 TSLA, SPY)',
    transfers               UInt64          COMMENT '当日纯转账与铸销事件总数',
    unique_senders          UInt64          COMMENT '当日去重非零发送地址数',
    unique_receivers        UInt64          COMMENT '当日去重非零接收地址数',
    mint_raw_amount         UInt256         COMMENT '当日铸造原始数量(from 为零地址)',
    burn_raw_amount         UInt256         COMMENT '当日销毁原始数量(to 为零地址)',
    net_supply_change       Int256          COMMENT '当日净发行变化量(mint - burn)',
    holder_count            UInt64          COMMENT '当日结束时余额大于零的持币地址数',
    top10_holder_share_bps  UInt32          COMMENT '日终 Top 10 持币地址占比基点(10000 = 100.00%)',
    dex_swap_count          UInt64          COMMENT '当日涉及该代币的 DEX Swap 交易总笔数',
    dex_raw_volume          UInt256         COMMENT '当日 DEX Swap 交易该代币的原始成交量',
    refreshed_at            DateTime('UTC') COMMENT '计算刷新时间',
    version                 UInt64          COMMENT '刷新版本号',
    -- 查询便利别名(不占存储)
    mint_amount             UInt256 ALIAS mint_raw_amount,
    burn_amount             UInt256 ALIAS burn_raw_amount,
    dex_swap_volume         UInt256 ALIAS dex_raw_volume,
    top_10_holder_share_bps UInt32  ALIAS top10_holder_share_bps
)
ENGINE = ReplacingMergeTree(version)
PARTITION BY toYYYYMM(day)
ORDER BY (day, token);

3.2 最新收盘日榜单视图 {db}.stock_token_leaderboard

CREATE VIEW IF NOT EXISTS {db}.stock_token_leaderboard AS
SELECT
    token,
    symbol,
    transfers,
    holder_count,
    unique_senders,
    unique_receivers,
    mint_raw_amount,
    burn_raw_amount,
    net_supply_change,
    top10_holder_share_bps,
    dex_swap_count,
    dex_raw_volume,
    dense_rank() OVER (ORDER BY transfers DESC) AS rank_by_transfers,
    dense_rank() OVER (ORDER BY holder_count DESC) AS rank_by_holders,
    day
FROM {db}.stock_token_daily FINAL
WHERE day = (SELECT max(day) FROM {db}.stock_token_daily FINAL)
ORDER BY transfers DESC, holder_count DESC;

4. 安装与补算

4.1 安装 DDL

通过 clickhouse-client 将 {db} 替换为目标数据库并应用:

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

4.2 自动调度刷新

032_stock_market.sql 中自带了可刷新物化视图 mv_stock_token_daily:

REFRESH EVERY 1 DAY OFFSET 1 HOUR RANDOMIZE FOR 30 MINUTE APPEND

ClickHouse 会在每日 UTC 01:00(错峰 30 分钟)自动触发重算昨日(yesterday())的完整市场指标并写入目标表。

4.3 手动刷新与历史回填脚本

使用专用无第三方依赖脚本 scripts/derived/refresh_stock_market.sh:

  • 单日刷新(默认刷新昨日,需收尾超过 2 小时):

    CH_URL=http://127.0.0.1:8123 CH_USER=indexer CH_PASSWORD=indexer CH_DB=robinhood \
      scripts/derived/refresh_stock_market.sh
  • 指定单日强制刷新:

    CH_URL=http://127.0.0.1:8123 CH_USER=indexer CH_PASSWORD=indexer CH_DB=robinhood \
      scripts/derived/refresh_stock_market.sh --date 2026-09-25
  • 历史日期区间连续回填:

    CH_URL=http://127.0.0.1:8123 CH_USER=indexer CH_PASSWORD=indexer CH_DB=robinhood \
      scripts/derived/refresh_stock_market.sh --from-date 2026-06-01 --to-date 2026-09-24

5. 本地验证与实测数据

在本地 Docker ClickHouse(http://127.0.0.1:8123)的真实链上数据(区块高度 72,039,000 ~ 72,040,999,真实日期 2026-09-25)上进行了全字段严格对账,独立编写 Python 脚本从 FINAL 表直查原始日志与分录台账,对以下代币的所有字段比对无误(100% Exact Match):

5.1 验证结果(2026-09-25)

指标字段TSLA (0x322f...3b2d)SPY (0x117c...4c0c)AAPL (0xaf3d...93f9)比对状态
transfers21613425EXACT MATCH
unique_senders304013EXACT MATCH
unique_receivers314115EXACT MATCH
mint_raw_amount000EXACT MATCH
burn_raw_amount000EXACT MATCH
net_supply_change000EXACT MATCH
holder_count17137EXACT MATCH
top10_holder_share_bps9971 (99.71%)9999 (99.99%)10000 (100.00%)EXACT MATCH
dex_swap_count1300EXACT MATCH
dex_raw_volume1467707085064855435700EXACT MATCH

5.2 铸销与净供应量合成验证(2026-09-24)

为进一步检验铸造、销毁和负向/正向净供应变动的精确度,在测试日 2026-09-24 构造了铸造 1000、转账 200、销毁 300 的真实场景,刷新后对账结果:

  • transfers: 3
  • mint_raw_amount: 1000
  • burn_raw_amount: 300
  • net_supply_change: +700
  • holder_count: 1
  • top10_holder_share_bps: 10000 全部断言 100% 通过。

6. 示例查询

例 1:查询最新收盘日股票代币综合活跃榜

SELECT
    symbol,
    rank_by_transfers,
    transfers,
    rank_by_holders,
    holder_count,
    top10_holder_share_bps,
    dex_swap_count,
    toString(dex_raw_volume) AS dex_volume_raw,
    day
FROM robinhood.stock_token_leaderboard
ORDER BY rank_by_transfers ASC
LIMIT 10;

例 2:TSLA 历史 30 天每日供应变化与 DEX 交易量

SELECT
    day,
    transfers,
    toString(mint_raw_amount) AS mint_volume,
    toString(burn_raw_amount) AS burn_volume,
    net_supply_change,
    holder_count,
    top10_holder_share_bps,
    dex_swap_count,
    toString(dex_raw_volume) AS dex_volume
FROM robinhood.stock_token_daily FINAL
WHERE token = unhex('322f0929c4625ed5bad873c95208d54e1c003b2d')
  AND day >= today() - 30
ORDER BY day DESC;

例 3:持币集中度最高(Top-10 持币比例最低/最分散)的代币筛选

SELECT
    symbol,
    holder_count,
    top10_holder_share_bps,
    transfers
FROM robinhood.stock_token_leaderboard
WHERE holder_count >= 10
ORDER BY top10_holder_share_bps ASC
LIMIT 10;

On this page