![](/img/trans.png)
[英]How to get all tick ranges with non-zero liquidity to finally calculate Total Value Locked Uniswap V3?
[英]How to calculate Uniswap v3 pool's Total Value Locked (TVL) on chain?
锁定在 Uniswap v3 池中的总价值并不总是那么容易获得。 流动性本身并不是衡量池中实际代币数量的好方法。 Uniswap v3 流动性描述了虚拟代币数量的集中流动性价值,而不是实际数量。
作为最简单的选择,您可以通过调用矿池合约上的balanceOf
function 来获取链上金额:
balanceToken0 = poolContract.functions.balanceOf(token0Address).call()
该值还将包括无人认领的费用。 在 Uniswap v3 中,这些费用不属于流动性的一部分。 如果您想获得有助于流动性的代币数量,那么调用balanceOf
是不够的。 它为您提供了两种不同的链上计算选项:
a) 迭代所有具有非零流动性的报价区间。
b) 遍历所有未平仓头寸。
下面是一些快速且未优化的 Python 代码,用于实现方法 (a)。 它需要MIN_TICK
、 MAX_TICK
、 TICK_SPACING
以及URL
、 POOL_ADDRESS
和V3_ABI
。
from collections import namedtuple
from web3 import Web3
web3 = Web3(Web3.HTTPProvider(URL))
pool = Web3.toChecksumAddress(POOL_ADDRESS)
contract = web3.eth.contract(address=POOL_ADDRESS, abi=V3_ABI)
Tick = namedtuple("Tick", "liquidityGross liquidityNet feeGrowthOutside0X128 feeGrowthOutside1X128 tickCumulativeOutside secondsPerLiquidityOutsideX128 secondsOutside initialized")
amounts0 = 0
amounts1 = 0
liquidity = 0
slot0 = contract.functions.slot0().call()
sqrtPriceCurrent = slot0[0] / (1 << 96)
def calculate_token0_amount(liquidity, sp, sa, sb):
sp = max(min(sp, sb), sa)
return liquidity * (sb - sp) / (sp * sb)
def calculate_token1_amount(liquidity, sp, sa, sb):
sp = max(min(sp, sb), sa)
return liquidity * (sp - sa)
for tick in range(MIN_TICK, MAX_TICK, TICK_SPACING):
tickRange = Tick(*contract.functions.ticks(tick).call())
liquidity += tickRange.liquidityNet
sqrtPriceLow = 1.0001 ** (tick // 2)
sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2)
amounts0 += calculate_token0_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh)
amounts1 += calculate_token1_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh)
print(amounts0, amounts1) # for better output, should correct for the amount of decimals before printing
TICK_SPACING 的值可以从矿池合约的tickSpacing()
function 中读取。 或者,如果您知道矿池的隔夜利息水平,您可以使用一个常量:1% 的矿池总是有 200 作为刻度间隔,等等。
MIN_TICK 和 MAX_TICK 的值可以从tickBitmap()
调用中获得,并分别查看最低和最高的初始化刻度。 它非常复杂,更适合单独的问题。 在最坏的情况下,如果您可能需要覆盖跨度为 -887272 和 +887272 的整个刻度范围。 因此,一开始您可以使用这些值向下/向上舍入到刻度间距值。
编辑: 1.0001 ^ tick
的平方根等于 1.0001 ^ (tick / 2),在这些行中使用这一事实使计算变得简单:
sqrtPriceLow = 1.0001 ** (tick // 2)
sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.