← Retour aux articles
July 18, 2026
5 min de lecture

Uniswap v3 pour les quants : liquidité concentrée et mathématiques des ticks depuis les premiers principes

Uniswap v3 pour les quants : liquidité concentrée et mathématiques des ticks depuis les premiers principes
#uniswap
#defi
#amm
#liquidité concentrée
#tenue de marché
#lvr
#quant
#ethereum

Une position LP sur Uniswap v3 est en réalité un ordre à cours limité déguisé, positionné sur une fourchette. Déposer de la liquidité entre deux prix revient à s'engager à acheter l'actif pendant la descente à travers votre fourchette, et à le vendre pendant la montée — exactement ce que fait une grille d'ordres limites au repos sur un carnet d'ordres (CLOB). Mais le contrat ne stocke ni prix, ni quantités, ni carnet d'ordres. Il stocke trois nombres : une racine carrée de prix en virgule fixe Q64.96, un indice de tick entier, et une valeur de liquidité agrégée LL. Si vous voulez raisonner sur une position v3 comme vous raisonneriez sur des cotations dans un modèle de tenue de marché — inventaire, prix d'exécution, sélection adverse — vous devez être capable de traduire entre ces primitives on-chain et les concepts de trading qu'elles encodent. Cet article construit cette traduction depuis les premiers principes, en suivant le whitepaper d'Uniswap v3 (Adams, Zinsmeister, Salem, Keefer, Robinson, 2021) et les contrats du cœur du protocole, et se termine là où toute discussion sérieuse sur le LP commence désormais : la loss-versus-rebalancing.

De x·y = k aux réserves virtuelles

Uniswap v2 est le teneur de marché à produit constant : un pool détient des réserves xx de token0 et yy de token1 et impose

xy=kx \cdot y = k

à chaque swap. Le prix marginal du token0 en unités de token1 est P=y/xP = y/x, et la liquidité est répartie uniformément sur tout l'axe des prix (0,)(0, \infty). C'est extrêmement inefficace en capital : une paire de stablecoins qui s'échange entre 0,999 et 1,001 conserve plus de 99% de son capital positionné à des prix qui ne s'imprimeront jamais.

L'innovation de v3 est de permettre à chaque LP de restreindre son capital à une fourchette [pa,pb][p_a, p_b]. À l'intérieur de la fourchette, la position doit se comporter exactement comme un pool v2 — même courbe de liaison, même prix marginal — mais en n'utilisant que les réserves nécessaires pour couvrir cette fourchette. Le whitepaper formalise cela avec les réserves virtuelles : la position agit comme si elle détenait des réserves de style v2 (xv,yv)(x_v, y_v) situées sur une courbe xvyv=L2x_v \cdot y_v = L^2, tandis que les réserves réelles sont les réserves virtuelles moins ce que la position détiendrait aux bornes de la fourchette :

(x+Lpb)(y+Lpa)=L2\left(x + \frac{L}{\sqrt{p_b}}\right)\left(y + L\sqrt{p_a}\right) = L^2

C'est l'équation 2.2 du whitepaper, et c'est l'équation la plus importante de v3. La courbe translatée touche les axes : à P=pbP = p_b, la réserve réelle xx atteint zéro (la position est à 100% en token1), et à P=paP = p_a, la réserve réelle yy atteint zéro (100% en token0). En dehors de la fourchette, la position devient inerte — un sac fixe d'un seul token, ne rapportant rien.

Courbe à produit constant d'Uniswap v2 comparée à la courbe translatée de v3 montrant les réserves virtuelles et réelles

Le paramètre LL, appelé liquidité, est l'invariant qui remplace kk. Il est défini comme L=kL = \sqrt{k}, et possède une interprétation limpide que le whitepaper rend explicite : la liquidité est « les réserves virtuelles par unité de racine carrée de prix ». À tout prix PP à l'intérieur de la fourchette, les réserves virtuelles sont

xv=LP,yv=LPx_v = \frac{L}{\sqrt{P}}, \qquad y_v = L\sqrt{P}

Pourquoi la variable d'état est √P

Le cœur de v3 ne suit pas le prix. Il suit P\sqrt{P}, stocké sous forme sqrtPriceX96, un nombre non signé en virgule fixe Q64.96 :

sqrtPriceX96=P296\texttt{sqrtPriceX96} = \sqrt{P} \cdot 2^{96}

PP est le prix brut : les unités de base du token1 par unité de base du token0, décimales incluses (nous y reviendrons plus bas). La raison de la racine carrée n'est pas une optimisation de gas, c'est de l'algèbre. Différenciez les identités de réserves virtuelles et vous obtenez les deux équations fondamentales de swap, implémentées dans la bibliothèque SqrtPriceMath :

Δy=LΔP,Δx=LΔ ⁣(1P)\Delta y = L \cdot \Delta\sqrt{P}, \qquad \Delta x = L \cdot \Delta\!\left(\frac{1}{\sqrt{P}}\right)

Les deux deltas de tokens sont linéaires par rapport à la racine carrée du prix (ou son inverse), avec LL comme constante de proportionnalité. Un swap à l'intérieur d'un seul tick ne nécessite donc aucune inversion de courbe, aucune itération de Newton — juste une multiplication pour déplacer P\sqrt{P}, puis deux multiplications pour calculer les montants. Quand un swap est assez important pour pousser le prix au-delà d'un tick initialisé, le pool le traverse, ajoute ou retire la liquidité nette référencée à cet endroit (liquidityNet), et continue avec le nouveau LL agrégé. Globalement, le pool est un AMM à produit constant par morceaux : LL constant entre les ticks initialisés, sauts au niveau des ticks.

Pour un teneur de marché, c'est le bon modèle mental : le profil de L(P)L(P) agrégé du pool est l'équivalent DEX de la profondeur du carnet d'ordres. Là où la profondeur d'un CLOB est cotée en unités par niveau de prix, la profondeur d'un AMM est LL par tick — et la conversion est exactement l'identité Δy=LΔP\Delta y = L\Delta\sqrt{P} ci-dessus.

Les ticks : une grille de prix espacée logarithmiquement

Les fourchettes ne peuvent pas commencer et se terminer à des prix arbitraires ; elles doivent s'aligner sur des ticks. Le tick ii correspond au prix

p(i)=1.0001ip(i)=1.0001i/2p(i) = 1.0001^i \quad\Longrightarrow\quad \sqrt{p(i)} = 1.0001^{i/2}

de sorte que chaque tick est à un point de base de ses voisins — non pas en termes absolus, mais en termes relatifs. Cet espacement logarithmique est délibéré : une grille additive fixe serait absurdement grossière pour un token qui s'échange à 0,0001 $ et absurdement fine à 100 000 $, alors qu'une grille géométrique offre une résolution uniforme de 1 point de base à chaque échelle de prix. La bibliothèque TickMath effectue la conversion dans les deux sens — getSqrtRatioAtTick et getTickAtSqrtRatio — en utilisant de la manipulation de bits sur des constantes précalculées plutôt qu'en appelant une exponentielle. Les indices de tick sont bornés par MIN_TICK = -887272 et MAX_TICK = 887272, ce qui couvre la plage de prix [2128,2128][2^{-128}, 2^{128}] : suffisamment large pour toute paire de tokens pouvant exister en arithmétique uint256.

Tous les ticks ne sont pas utilisables. Chaque palier de frais impose un espacement de tick (tick spacing), et les positions ne peuvent utiliser que des ticks divisibles par celui-ci :

Palier de frais Espacement de tick Largeur min. de fourchette Usage typique
0,01% 1 ~1 pb stable/stable
0,05% 10 ~10 pb paires stables, ETH/stables
0,30% 60 ~60 pb majors
1,00% 200 ~2% exotique / volatil

Les paliers 0,05%/0,30%/1% ont été déployés au lancement en mai 2021 ; le palier 0,01% a été ajouté par vote de gouvernance en novembre 2021. Un espacement plus grossier sur les pools à frais élevés limite le nombre de ticks potentiellement traversables et borne les coûts de gas des swaps.

Un piège lié aux décimales qui surprend tout le monde au moins une fois : le prix brut on-chain est le token1 par token0 en unités de base. Dans le pool USDC/WETH du mainnet, le token0 est l'USDC (6 décimales) et le token1 est le WETH (18 décimales), donc un prix humain de 3 000 $ par ETH correspond à un prix brut de 1012/30003,333×10810^{12}/3000 \approx 3,333 \times 10^{8} WETH-wei par unité d'USDC, qui se situe au tick

i=log1.0001 ⁣(3,333×108)=196,256i = \left\lfloor \log_{1.0001}\!\left(3,333\times10^{8}\right) \right\rfloor = 196{,}256

avec sqrtPriceX961,4465×1033\texttt{sqrtPriceX96} \approx 1,4465 \times 10^{33}. Si votre tableau de bord de monitoring affiche un tick proche de 196k pour USDC/WETH, vous savez maintenant pourquoi — et que le prix humain est (sqrtPriceX96/296)210dec0dec1\left(\texttt{sqrtPriceX96}/2^{96}\right)^2 \cdot 10^{\,\text{dec}_0 - \text{dec}_1} inversé selon les besoins.

Montants de tokens à partir de (L, fourchette de prix) : les formules exactes

Le livrable central de cette section : étant donné une position de liquidité LL sur [pa,pb][p_a, p_b] et un prix courant PP, que détient-elle ? Intégrer les équations de swap sur la fourchette donne trois cas :

Prix en dessous de la fourchette (PpaP \le p_a) — la position est à 100% en token0 :

x=L(1pa1pb),y=0x = L\left(\frac{1}{\sqrt{p_a}} - \frac{1}{\sqrt{p_b}}\right), \qquad y = 0

Prix au-dessus de la fourchette (PpbP \ge p_b) — la position est à 100% en token1 :

x=0,y=L(pbpa)x = 0, \qquad y = L\left(\sqrt{p_b} - \sqrt{p_a}\right)

Prix dans la fourchette (pa<P<pbp_a < P < p_b) :

x=L(1P1pb),y=L(Ppa)x = L\left(\frac{1}{\sqrt{P}} - \frac{1}{\sqrt{p_b}}\right), \qquad y = L\left(\sqrt{P} - \sqrt{p_a}\right)

Ce sont exactement les calculs effectués par SqrtPriceMath.getAmount0Delta et getAmount1Delta (avec un arrondi dirigé — le contrat arrondit toujours en défaveur de l'utilisateur, un détail qui compte si vous répliquez cela dans un backtester et vous interrogez sur des écarts au niveau du wei).

from math import sqrt

def position_amounts(L: float, pa: float, pb: float, P: float):
    """Token amounts held by a v3 position (float model; core uses Q96 ints)."""
    sa, sb, sp = sqrt(pa), sqrt(pb), sqrt(P)
    if P <= pa:
        return L * (1/sa - 1/sb), 0.0
    if P >= pb:
        return 0.0, L * (sb - sa)
    return L * (1/sp - 1/sb), L * (sp - sa)

Exemple détaillé : ETH/USDC, fourchette [2500, 3500]

Supposons que l'ETH s'échange à P=3000P = 3000 USDC et que vous vouliez déposer 1 ETH dans la fourchette [2500,3500][2500, 3500]. Racines carrées : 2500=50\sqrt{2500} = 50, 3000=54,7723\sqrt{3000} = 54,7723, 3500=59,1608\sqrt{3500} = 59,1608.

La jambe ETH fixe LL :

L=xPpbpbP=1×54,7723×59,160859,160854,7723=738,37L = \frac{x \cdot \sqrt{P}\,\sqrt{p_b}}{\sqrt{p_b} - \sqrt{P}} = \frac{1 \times 54,7723 \times 59,1608}{59,1608 - 54,7723} = 738,37

La jambe USDC en découle ensuite :

y=L(Ppa)=738,37×(54,772350)=3,523,69 USDCy = L\left(\sqrt{P} - \sqrt{p_a}\right) = 738,37 \times (54,7723 - 50) = 3{,}523,69 \text{ USDC}

Ainsi, minter cette position nécessite 1 ETH + 3 523,69 USDC, pour une valeur totale de 6 523,69 $, et notez que les deux jambes ne sont pas réparties 50/50 — la répartition dépend de la position de PP à l'intérieur de la fourchette (une fourchette asymétrique est précisément la manière d'exprimer une vue directionnelle, ou de placer un « range order » pur avec un seul token).

Maintenant, parcourons le prix jusqu'aux bornes :

  • À P=2500P = 2500, la position s'est entièrement convertie en ETH : x=738,37×(1/501/59,1608)=2,2867x = 738,37 \times (1/50 - 1/59,1608) = 2,2867 ETH, valant 5 716,68 $. Vous avez acheté 1,2867 ETH pendant la descente à un prix moyen pondéré par la liquidité d'environ 3523,69/1,286727393523,69 / 1,2867 \approx 2\,739 $.
  • À P=3500P = 3500, elle s'est entièrement convertie en USDC : y=738,37×(59,160850)=6764,06y = 738,37 \times (59,1608 - 50) = 6\,764,06 USDC. Vous avez vendu votre ETH pendant la montée à une moyenne de 3 240 $.

C'est la lecture en « range order » rendue concrète : la position est une échelle de bids allant de 3000 à 2500 et d'asks allant de 3000 à 3500, avec une taille par tick proportionnelle à LL. Et la concentration est ce pour quoi vous êtes payé : une position full-range de style v2 avec le même capital de 6 523,69 $ aurait Lv2=V/(2P)=59,55L_{v2} = V/(2\sqrt{P}) = 59,55 — la position concentrée cote 12,4× plus de profondeur par tick, et (tant qu'elle reste dans la fourchette) génère des frais à 12,4× le taux par dollar de capital.

Comptabilité des frais : feeGrowthGlobal et feeGrowthInside

Les frais de v3 ne se composent pas dans la position (une rupture délibérée par rapport à v2, où les frais étaient réinvestis dans k\sqrt{k}). Ils s'accumulent en parallèle, par token, et la comptabilité est un petit chef-d'œuvre de tenue de registre en O(1) qui mérite d'être compris car chaque pipeline d'analytics LP la réimplémente.

Le pool maintient deux accumulateurs globaux, feeGrowthGlobal0X128 et feeGrowthGlobal1X128 : les frais cumulés par unité de liquidité depuis la création du pool, en virgule fixe Q128.128. À chaque swap, le montant des frais (prélevé sur le token d'entrée) est divisé par le LL actuellement dans la fourchette et ajouté à l'accumulateur. C'est le mécanisme derrière la règle cardinale de l'économie de v3 : les frais ne s'accumulent que pour la liquidité qui est dans la fourchette au moment du swap. Les positions hors fourchette ne sont pas simplement de l'inventaire inerte — elles ne gagnent strictement rien tant qu'elles sont inactives.

Pour attribuer la bonne part de la croissance globale à une fourchette finie, chaque tick initialisé ii stocke feeGrowthOutside0/1X128 — la croissance des frais survenue de l'autre côté du tick par rapport au prix actuel (la valeur change d'interprétation à chaque fois que le tick est traversé, ce qui rend le mécanisme O(1)). Ensuite, pour une position sur [i,iu][i_\ell, i_u] avec un tick courant ici_c :

fbelow(i)={fo(i)icifgfo(i)ic<ifabove(iu)={fo(iu)ic<iufgfo(iu)iciuf_{\text{below}}(i_\ell) = \begin{cases} f_o(i_\ell) & i_c \ge i_\ell \\ f_g - f_o(i_\ell) & i_c < i_\ell \end{cases} \qquad f_{\text{above}}(i_u) = \begin{cases} f_o(i_u) & i_c < i_u \\ f_g - f_o(i_u) & i_c \ge i_u \end{cases} finside=fgfbelow(i)fabove(iu)f_{\text{inside}} = f_g - f_{\text{below}}(i_\ell) - f_{\text{above}}(i_u)

Chaque position stocke un instantané feeGrowthInsideLast, et les frais non collectés sont simplement

frais dus=Lfinsidemaintenantfinsidedernier2128\text{frais dus} = L \cdot \frac{f_{\text{inside}}^{\text{maintenant}} - f_{\text{inside}}^{\text{dernier}}}{2^{128}}

mis à jour paresseusement chaque fois que la position est touchée. Deux conséquences pratiques. Premièrement, les deltas de feeGrowthInside sont la seule manière honnête de mesurer les revenus de frais d'une position — échantillonner le volume au niveau du pool et le proratiser par votre part de la TVL donne un résultat erroné dès que le prix erre autour des bornes de votre fourchette. Deuxièmement, comme les frais restent stockés en tant que tokensOwed plutôt que de se composer, les rendements LP réalisés comportent un terme de traînée de trésorerie (cash-drag) que v2 n'avait pas ; les vaults à auto-compounding existent précisément pour arbitrer cela (moins leurs propres frais).

Diagramme de feeGrowthGlobal, feeGrowthOutside aux ticks limites de la fourchette, et la soustraction feeGrowthInside

Le payoff : un short straddle que vous êtes payé pour détenir (peut-être)

À l'intérieur de la fourchette, la valeur de la position en fonction du prix est

V(P)=x(P)P+y(P)=L(2PpaPpb)V(P) = x(P) \cdot P + y(P) = L\left(2\sqrt{P} - \sqrt{p_a} - \frac{P}{\sqrt{p_b}}\right)

Concave en PP — le terme 2LP2L\sqrt{P} résume toute l'histoire. En dehors de la fourchette, elle devient linéaire : pente x(pa)x(p_a) en dessous (vous êtes long sur un sac fixe d'ETH), pente 0 au-dessus (vous êtes plat en USDC). Faisons parcourir notre exemple détaillé à travers la fourchette et comparons-le au simple fait de détenir les tokens déposés :

PP (USDC/ETH) Valeur LP Valeur HODL Divergence
2500 5 716,68 6 023,69 −307,02
2750 6 200,4 6 273,69 −73,3
3000 6 523,69 6 523,69 0
3250 6 706,3 6 773,69 −67,4
3500 6 764,06 7 023,69 −259,63

Le LP sous-performe le HODL dans les deux directions et ne l'égale qu'au prix de mint. Upside plafonné, participation à la baisse amplifiée, valeur relative maximale au strike... c'est le payoff d'un short straddle (plus précisément, une fois les queues linéaires nettées contre le benchmark HODL, une position short sur une bande d'options frappées à travers [pa,pb][p_a, p_b]). Le flux de frais est la prime. Concentrer la fourchette revient à choisir des strikes plus serrés : plus de prime par unité de temps tant qu'on reste dans la fourchette, mais une divergence plus rapide et plus profonde quand le prix bouge. Chaque LP de v3 est un trader short-volatilité, qu'il l'ait choisi ou non — le pendant on-chain de l'arbitrage risque-inventaire que Avellaneda–Stoikov formalise pour les teneurs de marché de carnet d'ordres, la largeur de la fourchette jouant le rôle du spread coté.

Valeur de la position LP comparée au HODL sur la fourchette de prix montrant le payoff concave semblable à un short straddle

Le nom traditionnel de l'écart dans ce tableau est la perte impermanente (divergence loss), mais IL-versus-HODL est un benchmark défectueux : il confond la perte subie en tant que fournisseur de liquidité avec le risque de marché que vous auriez de toute façon porté. La décomposition plus fine vient de Milionis, Moallemi, Roughgarden et Zhang (2022), « Automated Market Making and Loss-Versus-Rebalancing » (arXiv:2208.06046). Comparez le LP non pas au HODL mais à un portefeuille de rebalancement qui détient, à chaque instant, les mêmes quantités de tokens que le pool — mais qui trade au prix de marché externe sans friction plutôt que contre des arbitragistes. La différence est le LVR (« lever » — levier) : la composante du P&L du LP qui est de la pure sélection adverse, payée aux arbitragistes qui exploitent les cotations obsolètes de l'AMM après chaque mouvement de prix. Sous un prix en mouvement brownien géométrique de volatilité σ\sigma, le LVR s'accumule au taux instantané

(σ,P)=σ2P22x(P)\ell(\sigma, P) = \frac{\sigma^2 P^2}{2}\,|x'(P)|

— une « formule de Black-Scholes pour les AMM », selon les mots des auteurs, avec x(P)|x'(P)| la profondeur marginale du pool au prix actuel. Pour le pool à produit constant full-range, cela se réduit au fameux σ28\frac{\sigma^2}{8} de la valeur du pool par unité de temps : à 5% de volatilité journalière, environ 3,1 points de base de la valeur du pool s'échappent vers les arbitragistes chaque jour, frais ou pas. La concentration multiplie x(P)|x'(P)| — notre exemple de profondeur 12,4× ci-dessus est aussi une machine à LVR ~12,4× tant qu'on reste dans la fourchette. Les frais doivent dépasser cette hémorragie pour que la position soit à EV positive, et le LVR (contrairement à l'« IL ») est un coût courant couvrable et prévisible, ce qui en fait la bonne unité de compte. Le calcul complet de rentabilité — APR des frais contre LVR contre volatilité réalisée, quand le LP bat une position short sur options delta-hedgée — fait l'objet du prochain approfondissement sur la perte impermanente et le LVR, et la mécanique de couverture reçoit son propre traitement dans stratégies LP v3 et couverture.

Un coût supplémentaire se situe une couche plus bas : parce que les cotations d'un AMM ne se mettent à jour que lorsque quelqu'un trade, chaque position LP est également exposée aux jeux de mempool joués autour de ces trades — attaques sandwich contre les swappeurs qui paient vos frais, et bundles d'arbitrage qui réalisent votre LVR bloc par bloc. Cet écosystème est cartographié dans l'article sur le MEV et les attaques sandwich.

Lire l'état du pool on-chain

Tout ce qui précède est observable à partir de trois appels peu coûteux au contrat du pool.

slot0() compacte l'état actif dans un seul slot de stockage : sqrtPriceX96, le tick actuel, les index d'observation de l'oracle, et les drapeaux de frais protocolaires/verrouillage. liquidity() retourne le LL agrégé actuellement dans la fourchette — notez que ce n'est pas la TVL ; c'est le paramètre de profondeur actif au tick courant et il saute de manière discontinue quand le prix traverse un tick initialisé. ticks(int24) retourne l'état par tick : liquidityGross (le LL total référençant le tick), liquidityNet (le LL signé ajouté en traversant de gauche à droite), et les accumulateurs feeGrowthOutside. Itérer sur liquidityNet à travers les ticks initialisés (le tickBitmap vous indique lesquels existent sans avoir à scanner les 1,7 million de ticks) reconstruit le profil de profondeur complet L(i)L(i) — votre instantané de carnet d'ordres.

from web3 import Web3

w3 = Web3(Web3.HTTPProvider(RPC_URL))
pool = w3.eth.contract(address=POOL, abi=POOL_ABI)  # USDC/WETH 0.05%

sqrt_price_x96, tick, *_ = pool.functions.slot0().call()
L = pool.functions.liquidity().call()

raw_price = (sqrt_price_x96 / 2**96) ** 2          # token1/token0, base units
eth_usdc  = 1 / (raw_price * 10**(18 - 6))          # human USDC per ETH
depth_1tick = L * (1.0001**0.5 - 1) * (sqrt_price_x96 / 2**96)

Les positions elles-mêmes vivent à deux endroits. Le pool central les indexe par (owner, tickLower, tickUpper) — un slot agrégé par triplet propriétaire-fourchette. Les particuliers et la plupart des fonds mintent plutôt via le contrat périphérique NonfungiblePositionManager (mainnet : 0xC36442b4a4522E871399CD717aBDD847Ab11FE88), qui enveloppe chaque position dans un NFT ERC-721 et expose positions(tokenId) retournant le tuple complet : tokens, palier de frais, fourchette, LL, feeGrowthInsideLast, et tokensOwed. Pour le suivi de portefeuille, cet unique appel plus le feeGrowthInside actuel du pool (recalculé à partir de ticks() comme dans la section précédente) vous donne la valeur mark-to-market et les frais accumulés sans toucher à un indexeur — bien que pour tout ce qui est historique, vous aurez besoin de rejouer les événements de swap ou d'un subgraph, car la croissance des frais dépend du chemin parcouru et la chaîne ne stocke que les accumulateurs actuels.

Deux détails opérationnels à intérioriser avant de déployer du capital. Premièrement, l'espacement des ticks quantifie votre espace de stratégie : sur le palier 0,05% vous pouvez placer des fourchettes de 10 points de base et vous rapprocher d'un véritable ordre à cours limité (minter juste au-dessus/en dessous du spot, collecter le frais, burn après le franchissement — le whitepaper décrit explicitement ce cas d'usage de « range order »), tandis que sur le palier 1% votre fourchette minimale fait environ 2% de large et l'analogie avec le carnet d'ordres devient grossière. Deuxièmement, un range order est un ordre à cours limité sans priorité d'annulation : si le prix traverse votre fourchette et revient, vous faites un aller-retour sur l'inventaire et redonnez l'edge (en gardant les frais). Les fourchettes passives sont des cotations que vous ne pouvez pas retirer — ce qui explique précisément pourquoi la question de la fréquence de rebalancement, et le prisme du LVR pour y répondre, comptent autant.

Ce qu'il faut en retenir

La pile v3, condensée : les prix sont des ticks sur une grille géométrique en 1,0001 ; la profondeur est LL, convertible en montants de tokens à travers rien de plus que des différences de racines carrées ; les frais sont un accumulateur par unité de LL que l'on différencie à travers les bornes de sa fourchette ; et la position qui en résulte est un range order short-vol dont le coût courant a un nom, une formule, et un numéro arXiv. Avec ces primitives en main, les questions intéressantes deviennent quantitatives : quelle largeur, quelle fréquence de rebalancement, et si les frais couvrent le LVR pour un pool et un régime donnés — ce qui est précisément là où cette série se dirige ensuite.

Références

  • Adams, H., Zinsmeister, N., Salem, M., Keefer, R., Robinson, D. (2021). Uniswap v3 Core (whitepaper).
  • Bibliothèques du cœur d'Uniswap v3 : TickMath.sol, SqrtPriceMath.sol, Position.sol, Tick.sol.
  • Milionis, J., Moallemi, C., Roughgarden, T., Zhang, A. L. (2022). Automated Market Making and Loss-Versus-Rebalancing. arXiv:2208.06046.
blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Gardez une longueur d'avance sur le marché

Abonnez-vous à notre newsletter pour des insights exclusifs sur le trading IA, des analyses de marché et des mises à jour de la plateforme.

Nous respectons votre vie privée. Désabonnement possible à tout moment.