- polygon 上的 usdc-weth(fee:0.05), pool address: 0x45dda9cb7c25131df268515131f647d726f50608[1], 这也是上次分析所用的池子
- ethereum 上的 usdc-eth(fee:0.05), pool address: 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640[2],由于这个池包含native token,为数据处理带来了一些麻烦
- 获取uniswap的数据
- 获取用户现金数据
- 计算价格序列, 也就是 eth 的价格.
- 获取每分钟, 每个 tick 上获取了多少手续费
- 获取统计周期内, 所有 position 的列表
- 获取地址和 position 的对应关系
- 计算每个 position 的收益率
- 基于 position 和地址的对应关系, 计算每个用户地址作为 LP 的收益率
- 将用户的现金和 LP 合并, 并计算总体收益率
- ethereum rpc: eth客户端的标准rpc接口. 获取数据效率比较低. 需要多开一些线程.
- Google BigQuery: 从BigQuery的数据集下载数据. 虽然每天更新一次, 但对于胜在使用方便, 价格便宜.
- Trueblocks chifra: Chifra服务可以scrape链上的交易, 并重新组织. 从而轻松的导出交易, 余额等信息. 但这需要自己搭建节点和服务.
- minute: 将 uniswap swap 的交易信息, 重采样为每分钟的数据. 用于回测
- tick: 记录 Pool 中每一笔交易. 包括 swap 和对流动性的操作.


而对于高级用户, 尤其是一些基金, 他们会选择绕过 proxy, 直接操作 pool 合约. 这种情况下, position 不会有 token id. 这种情况下, 我们会用address-LowerTick-UpperTick的格式, 给这个 LP position 创造一个 id.对于 burn 和 collect, 也可以用这种方式为 pool 的 event 找到对应的 position id. 但是这里有个麻烦, 有时候两个 event 的金额并不相同, 会有一点点偏差. 比如这个交易

- 地址在起始时刻的余额
- 地址在统计期间的转帐记录.



- 对于通过 Proxy 投资的 LP, 每个 position 都会拥有一个 nft, 也就是拥有一个 token id, 这可以作为 position 的 id.
- 而对于直接操作 pool 投资的 LP, 我们会为他编造一个 id, 格式为address_LowerTick_UpperTick. 这样, 所有的 position 都有了自己的标识.

- 将 mint 和 burn 的 liquidity 相加, 得到一个数字 L
- 如果 L>0, 也就是 mint>burn, 认为在统计开始之前, 就有了一些流动性, 此时会在统计开始的时刻(2023.1.1 0:0:0)补偿一个 mint 操作.
- 如果 L<0, 认为在统计结束的时候, 仍然持有 liquidity.

- 当 mint 交易发生, 让流动性增加
- 当 burn 交易发生, 让流动性减少. 并将流动性的价值折算到手续费字段(pool 合约的代码也是这样操作的)
- 当 collect 交易发生. 会触发计算, 计算范围是从上次 collect 到当前时间, 我们会计算每分钟的净值和手续费收入, 得到一个列表.

注意:
- 回填的时候还要根据当前小时的流动性, 对手续费的分配进行加权, 否则会出现这个小时手续费偏高的情况.
- 由于统计的数据是 2023 年全年, 而不是完整数据, 因此存在第五节中提到的沉没流动性的现象. 这会让实际手续费比理论手续费多很多. 使得收益率变得异常高.
- 这里的收益率需要细化到每一分钟,
- 由于 position 会在中途有资金的转入和转出. 单纯开始和结束的净值相除并不能体现收益情况.

- 指定当前分钟是 n, 前一分钟是 n-1
- 假定当前分钟的所有转帐操作, 都发生在第 n:0.000 秒. 那么在余下的时间, LP 的净值是不变的, 也就是说第 n:0.001 秒的净值等于 n:59.999 秒的净值.
- 手续费的累加发生在这一分钟的末尾.也就是第 n:59.999 秒.
- 上一分钟末尾(n-1:59.999)的价格和手续费, 就是这一分钟(n:0.000)开始的价格和手续费

- 对于净值列来说是瞬时值, 也就是当前分钟/小时最后的值.
- 而手续费列是累加值. 也就是当前分钟/小时期间所累计的手续费
- 当 LP 被 burn 掉, 然后 token 转移走的情况下, 在这个小时末尾净值会是 0
- 而对于手续费来说, 由于他是累加的, 在这个小时的末尾, 手续费会大于 0.

