Crypto OS
Non-Technical Crypto OS第四阶段 · Token、市场与研究

第 23 章 · 链上数据如何观察真实世界

怎样不靠别人的结论,自己看清正在发生什么?

练习的能力
Onchain LiteracyResearch
动手
用一个链上数据平台做出你自己的第一张图:某协议近 90 天的收入与活跃地址。
AI Lab
让 AI 写出取数口径与查询,自己跑一遍,核对它的口径有没有把激励算进收入。

一个现实问题

你在研究同一个协议,手上有三份材料。

第一份是它的官方季度报告,写着上个季度收入 2400 万美元。 第二份是一家研究机构的报告,同一个季度,写着 900 万美元。 第三份是社交平台上一个人做的表格,写着这个协议净亏损 1800 万美元。

三个数字,同一个协议,同一个季度。相差一个数量级,而且符号都不一样。

你的第一反应可能是「一定有人在撒谎」。但如果你逐个去查,会发现一件更麻烦的事:三份材料里的每一个数字,都能在链上找到对应的交易。

它们不是在编数字,它们在回答三个不同的问题:

  • 第一份算的是用户一共付了多少费
  • 第二份算的是其中归协议的那部分
  • 第三份把协议当期发出去的代币激励也算了进来,得到一个净额。

三个都对,因为「收入」这个词从来没有被定义过。

这就是这个行业里最普遍的一种混乱:数据是公开的,口径是私有的。

链上的每一笔交易都对所有人可见,这是 Crypto 相对于几乎所有其他行业的巨大优势。但公开的是原始事实,不是结论。从事实到结论中间的那一步——你决定把哪些交易算进来——决定了最终的数字。

而那一步,通常不写在报告里。

所以这一章要解决的问题是:怎样绕开所有人的结论,自己从原始事实出发,做出一个你能为它辩护的数字。

这是整个 Part A 里技能密度最高的一章,也是毕业项目里你会用得最多的一项能力。

思想实验

先离开链上,看一家咖啡店。

这家店在一个外卖平台上卖咖啡。上个月的账是这样的:

  • 顾客通过平台一共付了 100 万元
  • 平台抽走 20%,也就是 20 万元。
  • 店里为了拉新,发了一批 15 万元的代金券,顾客用券抵扣了咖啡钱。
  • 这些代金券是店主自己印的,印刷成本几乎为零。

现在请回答:这家店上个月的「收入」是多少?

至少有五个答案,每个都能自圆其说:

A  100 万   顾客支付的总额
B   80 万   扣掉平台抽成后进店的钱
C   65 万   再扣掉代金券的面值
D   80 万   代金券是自己印的,没有现金流出,不该扣
E   65 万   券会在未来被兑换成真咖啡,成本是真的

D 和 E 的分歧特别值得停下来看。代金券到底算不算成本?

如果只看这个月的现金,它不算——店主没有掏一分钱。如果看长期,它算——那 15 万的券迟早要用真咖啡去兑付。

这就是链上代币激励的处境。 协议用自己发行的代币去奖励用户,当期没有任何现金流出,但这些代币会稀释所有持有人(第 20 章讲过)。算不算进成本,取决于你在回答什么问题。

再看两个更容易混的数字。

「店里有多少钱」不等于「店赚了多少钱」。

假设店里的保险柜里放着 500 万元,其中 480 万是顾客存的充值余额。保险柜里的总额是一个很漂亮的数字,但它是顾客的钱,不是店的钱,而且顾客随时可以取走。

链上有一个指标就是这个保险柜的总额。 它经常被当作协议规模的代表,而它衡量的其实是「别人放在这里多少钱」。

「今天来了多少人」也需要拆。

上个月门店进来 6000 人次。其中 4500 次是来领免费券的,领完就走,从没买过一杯全价咖啡。剩下 1500 次里,有 300 个人来了五次。

所以「6000」这个数字可以是:6000 人次、1800 个独立的人、300 个真实回头客,或者 1500 笔真实交易。每一个都是真的,每一个描述的东西完全不同。

把咖啡店换成协议,把顾客换成地址,这三组问题一模一样地成立。区别只有一个:链上的每一笔都记录在案,你可以自己去数。

你来决定

你要回答一个具体问题:这个协议上个月赚了多少钱。你从哪里开始?

观察结果

四个选项指向同一个结论:

链上数据的难点不在取数,在定义。

技术上,查询一个协议 90 天的手续费收入,写对了查询就是几秒钟的事。真正花时间的是回答这六个问题:

口径六问具体要定什么
算哪些地址主合约?所有版本?所有链上的部署?代理合约还是实现合约?
算哪些事件哪几类交易算作「使用」?失败的交易算不算?内部转账算不算?
算总额还是净额用户支付的总费用,还是扣掉分给流动性提供者之后的部分?
激励怎么处理协议发出去的代币激励,算成本还是不算?按什么价格折算?
时间怎么切按自然月还是滚动 30 天?按区块时间还是 UTC 日期?
去重怎么做地址去重还是人去重?托管地址怎么算?同一个人的多个地址怎么办?

六个问题里任何一个答案不同,最终数字就不同。而绝大多数引用链上数据的文章,六个问题一个都没交代。

于是同一个协议的同一个月,可以合法地产生下面这些数字:

这个数字叫什么它算的是什么常见误用
用户支付总费用所有用户掏出来的钱被直接称为「协议收入」
归协议的部分扣掉分给流动性提供者之后被漏掉,导致高估数倍
净收入再扣掉当期代币激励几乎从不出现在宣传材料里
锁仓总额别人放在这个协议里多少钱被当成协议的规模或价值
交易量经过这个协议的资金流水被当成需求,但可以被刷
活跃地址有交互的地址数被当成用户数

这一章要教你的,就是每次看到一个数字时,先把它归到这张表的某一行,再决定要不要用。

最后说一件必须单独强调的事。第 19 章讲过流通市值和完全稀释估值的区别,在数据实践中它是最常见的一类错误:引用一个估值数字时,如果不说明是哪一种,整段分析都不成立。 这两个数字在同一个项目上可以差十倍以上,而且很多数据源默认展示的是其中一个却不标注。

建立模型

这一章的模型是一套流程,六步。每一步都有一个必须交付的东西。

  1. 定问题
  2. 定口径
  3. 找数据源
  4. 取数
  5. 交叉验证
  6. 标注不确定性
多数人从第四步开始,所以结论经不起追问。前两步只花十分钟,但它们决定了后面所有工作有没有价值。

逐步展开:

要交付什么做不到会怎样
1 定问题一句能被证伪的问题,带时间范围「研究一下这个协议」永远做不完
2 定口径六问的六个答案,写成文字数字出来了但没法解释,也没法复现
3 找数据源至少两个独立来源一个来源出错你永远不会知道
4 取数一份可复现的查询或步骤记录下个月要重来一遍
5 交叉验证两个来源的差异及其解释差异被忽略,而差异往往最有信息量
6 标注不确定性一份「我不确定的地方」清单读者无法判断该信多少

第五步值得单独说。交叉验证的价值不在于确认两个数字一样,而在于当它们不一样时去解释为什么。

两个来源差 3%,可能是时间切分的边界问题。差 40%,几乎一定是口径不同,而找出那个不同,你就理解了这个协议的一个结构性特征。差异是信息,不是噪音。

第六步是把研究和宣传区分开的那一步。一份诚实的数据分析必须包含一段「我不确定」,比如:这个协议在另外两条链上也有部署,我没有覆盖;激励我按当期均价折算,价格波动会影响结论;有三个大额地址我无法判断是不是同一个实体。

一份写清楚自己盲区的分析,比一份看起来无懈可击的分析更值得相信。

最后给出六个核心指标的定义和它们各自的陷阱。这张表建议抄进自己的笔记,毕业项目会一直用。

指标它真正衡量什么主要陷阱
持有人持有某代币的地址数地址不等于人;空投产生大量一次性地址;托管地址背后是很多人
锁仓总额存在协议里的资产价值是别人的钱不是协议的;同一笔钱可以在多个协议里被重复计算;随币价涨跌而变,看起来像增长
费用用户支付的总额大部分常常分给流动性提供者,不归协议
收入归协议的那部分是否扣除代币激励必须说明;很多口径不扣
净流量一段时间内流入减流出内部转账和做市商调仓会污染;要分清交易所地址和用户地址
未平仓量未平掉的衍生品合约规模币本位与美元本位走势不同;不同场所口径不一;不代表方向

它叫什么

持有人Holder

持有某个代币的地址数量。

注意它衡量的是地址,不是人。一个人可以有一千个地址,一个交易所托管地址背后可能是几十万人。

有用的拆法:过去 30 天有交互的地址、只有一笔转入之后再没动过的地址、创建时间的分布。第 22 章的 Lab 用的就是这套拆法。

锁仓总额TVL / Total Value Locked

存放在一个协议合约里的资产总价值。

它有三个必须知道的性质:这是用户的钱不是协议的钱;它会随着资产价格上涨而上涨,看起来像业务增长其实不是;同一笔资金在可组合的协议之间可以被重复计入多个协议的 TVL。

它是一个有用的规模指标,但它不是收入,也不是价值。第 26 章的标题就是为它写的。

费用Fees

用户为使用协议支付的总金额。

关键在于这笔钱最后去了哪里。在多数交易类协议里,绝大部分费用分给了提供流动性的人,只有一小部分归协议。

把费用直接称为收入,是这个行业里最常见的一处放大。

收入Revenue

费用中归协议本身的那一部分。

再往下还有一层:扣掉当期代币激励之后的净收入。这一层几乎从不出现在宣传材料里,但它才是回答「这个协议是在赚钱还是在花钱买增长」的那个数字。

引用收入时必须说明是哪一层,否则这个数字无法被理解。

净流量Netflow

一段时间内某类地址的流入减去流出。

最常见的用法是观察交易所地址的净流量。它的陷阱很多:交易所内部的钱包整理会产生大额转账但没有实际意义;做市商的调仓会被误读为用户行为;冷热钱包之间的转移完全是内部操作。

做净流量分析之前,必须先做地址分类,而地址分类本身就是一项需要验证的工作。

未平仓量Open Interest

尚未平仓的衍生品合约总规模。第 18、21 章用过它。

两个陷阱:计价口径(币本位和美元本位在价格剧烈波动时走势可以相反)和场所覆盖(不同数据源统计的交易场所不同)。

它衡量的是杠杆的规模,不包含方向信息。把它单独拿来判断多空是误用。

动手

动手做出你自己的第一张链上数据图一个链上数据平台(支持 SQL 查询的那一类)+ 一个区块浏览器0 元,这类平台通常有免费额度;全程只查不动,不涉及任何真实资金

目标很具体:做出一张图,显示某个协议近 90 天的收入活跃地址,并且你能为图上的每一个数字辩护。

这个 Lab 比前面几章的长,建议分两次做完。

选一个协议,写下你的问题。

挑一个有明确手续费机制的协议(交易所、借贷协议、永续合约平台都可以)。避开结构过于复杂的。

写下一句话的问题,比如:「这个协议在过去 90 天里,每天归协议的收入是多少,每天有多少个独立地址和它交互?」

这句话要写在文档最上面,后面每一步都回头对照它。

写下你的口径,六问逐条回答。

这一步不要跳,它是这个 Lab 的核心。

算哪些地址:主合约 0x…(在链上找到,不要从文章里抄),只算主网,
            不含其他链的部署(这一条要写进不确定性清单)
算哪些事件:Swap / Borrow / …(写出具体事件名),失败交易不算
总额还是净额:算归协议的部分 = 总费用 × 协议分成比例
              分成比例来自合约参数 …(记下参数名和当前值)
激励处理:本次不扣激励,单独列一条激励支出曲线做对照
时间切分:按 UTC 自然日,区间为最近 90 个完整日
去重方式:按 from 地址去重,不做人的归并(写进不确定性清单)

找到合约地址,用区块浏览器核对。

不要从任何文章或推文里复制合约地址。去官方文档找,然后在区块浏览器上打开,确认三件事:它有没有被标注为代理合约?有没有更新的版本?最近还有没有交易?

在浏览器上随便打开一笔交易,看它触发了哪些事件,把事件名和字段抄下来。你的查询要抓的就是这些事件。

写第一个查询:每日费用。

不同平台的表名和字段名不一样,但结构都是这样:

select
  date_trunc('day', block_time) as day,
  sum(fee_amount_usd)           as fees_usd,
  count(*)                      as tx_count
from <平台的事件表>
where contract_address = <你核对过的合约地址>
  and block_time >= now() - interval '90' day
group by 1
order by 1

先只跑三天的数据。把结果和区块浏览器上那三天的实际交易对一下,数量级对不上就回去找原因,不要往下走。

写第二个查询:每日活跃地址。

select
  date_trunc('day', block_time)  as day,
  count(distinct tx_from)        as active_addresses
from <平台的事件表>
where contract_address = <合约地址>
  and block_time >= now() - interval '90' day
group by 1
order by 1

注意一个细节:tx_from 是发起交易的地址,如果用户通过聚合器或者合约钱包访问这个协议,这个字段会是聚合器的地址而不是用户的。先去看几笔真实交易,确认你取的是哪一层。 这是活跃地址统计里最常见的一个错。

把两条曲线画到一张图上。 收入用柱状,活跃地址用折线,双 Y 轴。

然后看形状:两条线是同向的吗?有没有某几天收入暴涨但地址数没变(可能是几笔大额交易),或者地址数暴涨但收入没变(可能是激励活动或者刷量)?

这些背离的日子是最值得深挖的地方。 挑一天,去区块浏览器上看那天的交易,找出原因。

交叉验证。 把你算出的 90 天总收入,和至少两个外部来源对比:协议的官方仪表盘、一个第三方数据聚合站。

填这张表:

来源90 天数字与我的差异差异的解释
我自己的查询
官方仪表盘
第三方平台

第四列是这个 Lab 最有价值的产出。 如果差异超过 20% 而你解释不了,说明口径里还有一条你没想清楚。

写不确定性清单。 至少三条,比如:没有覆盖其他链上的部署;活跃地址按发起地址统计,通过聚合器的用户被计到了聚合器头上;激励支出按当期均价折算,价格波动会影响结论。

做完之后你会有三样东西:一张图、一份可复现的查询、一份诚实的盲区清单。

这三样加起来,就是一份合格的一手研究的最小单元。 第 26、31 章会在这个基础上继续搭,毕业项目的数据部分就是把这个流程重复几遍。

AI Lab

AI Lab让 AI 写出取数口径和查询,你自己跑一遍并抓它的口径错误Level 2 · AI Copilot

先把上一个 Lab 自己做一遍,再来做这个。顺序反了,你将无法判断它给的东西对不对。

给 AI 这样一个任务:

我要统计某协议过去 90 天的协议收入和每日活跃地址。

第一步,先不要写查询。先输出一份取数口径文档,回答六个问题:
1. 算哪些合约地址(主网 + 其他链,分别列出)
2. 算哪些事件,失败交易怎么处理
3. 算用户支付总费用还是归协议的净额,分成比例来自哪个参数
4. 代币激励怎么处理,如果扣除按什么价格折算
5. 时间怎么切分,边界怎么处理
6. 活跃地址按什么字段去重,通过聚合器的用户怎么算

第二步,基于这份口径写查询,写出你用的表名和字段名。

第三步,单独列出:这个查询覆盖不到什么?哪些地方可能低估或高估?

规则:
- 每一个合约地址、参数名、事件名都要标注出处。
- 不确定的写「需要人工核对」,不要给一个看起来合理的值。

拿到之后,第一件事是去区块浏览器核对合约地址和事件名,然后再把查询跑一遍。

这类任务上模型有五个高频错误,按危险程度排序:

  1. 把激励算进收入,或者完全忽略激励支出。 这是这一章开头三份报告分歧的来源,也是最贵的一个错。
  2. 把费用当收入。 不区分用户支付总额和归协议的部分,一个错误就能把数字放大好几倍。
  3. 编造合约地址和字段名。 格式完全正确,看起来毫无破绽,但在链上不存在。这类错误只能靠核对发现。
  4. 混用估值口径。 引用市值时不说明是流通市值还是完全稀释估值,第 19 章讲过这两个数字可以差十倍。
  5. 漏掉多链部署和多个版本。 只算了主网的一个合约,得到一个系统性偏低的数字。

把你实际遇到的错误记进自己的清单。这五条不是模型独有的毛病——同样的五个错误在人写的研报里同样常见,只是没人逐条核对过。

进阶做法:把自己写的口径文档和 AI 写的并排放,看它想到了什么你没想到的,你想到了什么它漏掉的。第 31 章会把这个对照变成一条固定的研究流水线。

AI 说完之后,你必须自己验证

  • 它给的合约地址,你在区块浏览器上核对过吗:是不是代理合约,是不是最新版本
  • 它写的事件名和字段名,在真实交易里存在吗
  • 它算的是用户支付的总费用,还是归协议的部分,它说清楚了吗
  • 最关键的一条:它有没有把代币激励算进收入,或者把激励支出完全忽略
  • 它有没有把 FDV 和流通市值混用,或者引用估值时不标注是哪一种
  • 它的时间切分用的是区块时间还是别的,边界怎么处理的
  • 活跃地址它按哪个字段去重,通过聚合器来的用户会被算到谁头上
  • 它有没有主动列出这个查询覆盖不到的部分

真实案例

同一个协议的三个收入数字随时可以验证

本章开头那个场景不是虚构的结构:任何一个有代币激励的协议,都可以同时给出「用户支付总费用」「归协议的部分」「扣掉激励后的净额」三个数字。

三者可以相差一个数量级,而且第三个经常是负的。

有意思的是,三个数字各有各的正确用途:第一个衡量使用规模,第二个衡量商业模式,第三个衡量它是在赚钱还是在买增长。问题从来不是用哪个,而是用的时候有没有说清楚。

被重复计算的锁仓总额可组合协议常见

一笔资金存进一个借贷协议,拿到一个凭证代币;这个凭证代币再存进另一个协议做抵押;抵押借出的资产又存进第三个协议。

同一笔原始资金,在三个协议的锁仓总额里各计了一次。行业整体的数字里,它被算了三遍。

这不是谁在作弊,这是可组合性的自然结果。但它意味着锁仓总额在跨协议汇总时会系统性放大,而这个放大倍数会在杠杆扩张时上升、在收缩时下降——第 21 章的反馈结构在数据层面的一个投影。

活跃地址暴涨的那一周激励活动期间

一个协议在某周活跃地址数上涨了十几倍,宣传材料把它作为增长的证据。

把那周的地址拉出来看:绝大多数地址创建于活动开始后的三天内,每个地址只完成了刚好达到领取门槛的最小交互,活动结束后再没有任何活动。

这个现象在链上是完全可见的,而且只需要两个查询就能验证:地址创建时间分布,和活动结束后 30 天的留存。第 28 章会把它变成一套固定的判断方法。

口径写清楚的那些数据源行业正在改善

这个行业里有一批数据项目选择把取数逻辑开源:每个协议的收入怎么算、分成比例取自哪个参数、激励算不算,全部写在公开仓库里,任何人都可以提出修改。

这改变了一件事:争论可以针对口径进行,而不是针对数字。 两个人对同一个协议的收入有分歧时,可以直接指出是第几行的定义不同。

选择数据源时,这应该是第一个筛选条件:它的口径写在哪里? 找不到口径说明的数据,不管看起来多权威,都不要引用。

改一个变量

如果这个协议同时部署在五条链上,你只统计了主网

你的所有数字都会系统性偏低,而且偏低的比例会随时间变化——如果协议正在往其他链迁移,你会得到一条虚假的下降曲线。

处理方式有两种,都合法:把口径明确限定为「主网」并在标题里写出来,或者把五条链全部覆盖。

不合法的是第三种:只统计主网,但把结论说成整个协议的情况。 这是链上数据分析里最常见的一类系统性错误,而它通常不是故意的。

如果你把当期发出的代币激励也算进成本,按当天收盘价折算

收入曲线可能从正变负。但更值得注意的是另一件事:这条曲线的形状会和代币价格高度相关。

价格上涨时,同样数量的激励折算成更多美元,成本上升,净收入下降;价格下跌时反过来。于是你会得到一条主要由币价驱动的「净收入」曲线。

这不是错,这是这个口径的固有性质。处理办法是同时给出两条曲线:一条按当期价格折算,一条按代币数量计。把口径的副作用暴露出来,比假装它不存在要诚实。

如果一半的用户通过聚合器访问这个协议

按交易发起地址统计,这一半用户全部被计到了少数几个聚合器地址头上。你的活跃地址数会大幅低估,而且低估的程度取决于聚合器的市场份额。

解决办法是往下取一层:解析交易内部的调用,找到真正的发起方。这在支持内部调用数据的平台上可以做到,但查询会复杂很多。

做不到的时候,正确的做法是把这一条写进不确定性清单,而不是当作没有。 这一章反复强调的就是这件事:知道自己漏了什么,比漏得少更重要。

如果你想统计的不是地址数,而是真实的人数

你会发现链上做不到,至少无法可靠地做到。

可以逼近的方法有几种:把有资金往来的地址聚成一簇、按行为模式聚类、用链下的身份线索去关联。每一种都会引入新的误差,而且每一种都在做一件和隐私直接冲突的事——第 5 章讲过链上公开账本的隐私代价。

所以实践中的做法是换一个能回答的问题:不问「有多少人」,改问「有多少个过去 30 天活跃、且不是在同一小时批量创建的地址」。

把答不了的问题换成答得了的问题,并且说清楚换过,是研究里最有用的一个习惯。

带走的问题

4
用户是谁?

这一章给了这一问一套可执行的答案:不要接受任何未经拆分的用户数。

拆成四层去查:活跃地址、独立地址、有真实支付的地址、活动结束 30 天后还在的地址。四个数字一起看,「用户是谁」才有答案。第 28 章会把这四层变成固定流程。

5
谁在支付?

链上的好处是这一问可以被验证到具体地址:钱从哪个地址出来、经过哪些合约、最后停在哪里。

问的时候要特别注意一种情况:如果这笔钱是协议自己发的代币,那么付钱的其实是全体持有人。 这在链上看起来和真实收入完全一样,只能靠读合约区分。

6
收入从哪里产生?

把收入拆成三层:用户支付总额、归协议的部分、扣除激励后的净额。

引用任何一个收入数字时,先说清楚是哪一层。这一个习惯,能让你的分析比这个行业里绝大多数材料更经得起追问。

12
如果补贴停止,还有用户吗?

这一问在链上有一个标准答案的取法:找到激励活动的结束日,统计活动期间新增地址在之后 30、60、90 天的留存。

三个数字画成一条线,答案自己就出来了,不需要任何人的观点。这就是这一章说的「一手事实」的意思。

本章自测

一句话带走

链上数据是这个行业里少数可以自己验证的一手事实。

做完这一章的动手环节了?勾上它查看全部进度

本页目录