← Volver a los artículos
July 18, 2026
5 min de lectura

Uniswap v3 para quants: liquidez concentrada y matemática de ticks desde primeros principios

Uniswap v3 para quants: liquidez concentrada y matemática de ticks desde primeros principios
#uniswap
#defi
#amm
#liquidez concentrada
#creación de mercado
#lvr
#quant
#ethereum

Una posición de LP en Uniswap v3 es, en el fondo, una orden de rango de un libro de órdenes límite disfrazada. Depositas liquidez entre dos precios y con eso te comprometes a comprar el activo mientras cae dentro de tu rango y a venderlo mientras sube — exactamente lo que hace una grilla de órdenes límite pasivas en un CLOB. Pero el contrato no almacena precios, cantidades ni un libro de órdenes. Almacena tres números: un precio en raíz cuadrada en punto fijo Q64.96, un índice de tick entero, y un valor de liquidez agregada LL. Si quieres razonar sobre una posición v3 de la misma forma en que razonarías sobre cotizaciones en un modelo de creación de mercado — inventario, precios de ejecución, selección adversa — necesitas poder traducir entre esas primitivas on-chain y los conceptos de trading que codifican. Este artículo construye esa traducción desde primeros principios, siguiendo el whitepaper de Uniswap v3 (Adams, Zinsmeister, Salem, Keefer, Robinson, 2021) y los contratos centrales, y termina donde hoy empieza toda discusión seria sobre LPs: loss-versus-rebalancing.

De x·y = k a las reservas virtuales

Uniswap v2 es el creador de mercado de producto constante: un pool mantiene reservas xx del token0 y yy del token1 y hace cumplir

xy=kx \cdot y = k

en cada swap. El precio marginal del token0 en unidades del token1 es P=y/xP = y/x, y la liquidez se distribuye uniformemente sobre todo el eje de precios (0,)(0, \infty). Eso es capital-ineficiente al extremo: un par de stablecoins que cotiza entre 0.999 y 1.001 mantiene más del 99% de su capital posicionado en precios que nunca se van a imprimir.

La jugada de v3 es dejar que cada LP restrinja su capital a un rango [pa,pb][p_a, p_b]. Dentro del rango, la posición debe comportarse exactamente como un pool v2 — misma curva de vinculación, mismo precio marginal — pero usando solo las reservas necesarias para cubrir ese rango. El whitepaper formaliza esto con reservas virtuales: la posición actúa como si mantuviera reservas estilo v2 (xv,yv)(x_v, y_v) situadas sobre una curva xvyv=L2x_v \cdot y_v = L^2, mientras que las reservas reales son las virtuales menos lo que la posición mantendría en los límites del rango:

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

Esta es la ecuación 2.2 del whitepaper, y es la ecuación más importante de v3. La curva trasladada toca los ejes: en P=pbP = p_b la reserva real de xx llega a cero (la posición es 100% token1), y en P=paP = p_a la reserva real de yy llega a cero (100% token0). Fuera del rango la posición queda inerte — una bolsa fija de un solo token, sin ganar nada.

Curva de producto constante de Uniswap v2 frente a la curva trasladada de v3 mostrando reservas virtuales y reales

El parámetro LL, llamado liquidez, es el invariante que reemplaza a kk. Se define como L=kL = \sqrt{k}, y tiene una interpretación limpia que el whitepaper hace explícita: la liquidez es "reservas virtuales por unidad de raíz cuadrada del precio". En cualquier precio PP dentro del rango, las reservas virtuales son

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

Por qué la variable de estado es √P

El núcleo de v3 no rastrea el precio. Rastrea P\sqrt{P}, almacenado como sqrtPriceX96, un número sin signo en punto fijo Q64.96:

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

donde PP es el precio crudo: unidades base del token1 por unidad base del token0, decimales incluidos (más sobre esto abajo). La razón de la raíz cuadrada no es golf de gas, es álgebra. Diferencia las identidades de reservas virtuales y obtienes las dos ecuaciones fundamentales de swap, implementadas en la librería 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)

Ambos deltas de token son lineales respecto a la raíz cuadrada del precio (o su recíproco), con LL como constante de proporcionalidad. Un swap dentro de un mismo tick por lo tanto no necesita inversión de curva ni iteración de Newton — solo una multiplicación para mover P\sqrt{P}, y luego dos multiplicaciones para calcular los montos. Cuando un swap es lo suficientemente grande como para empujar el precio a través de un tick inicializado, el pool lo cruza, suma o resta la liquidez neta referenciada ahí (liquidityNet), y continúa con el nuevo LL agregado. Globalmente, el pool es un AMM de producto constante por tramos: LL constante entre ticks inicializados, saltos en los ticks.

Para un market maker, este es el modelo mental correcto: el perfil de L(P)L(P) agregado del pool es el equivalente en DEX a la profundidad del libro de órdenes. Donde la profundidad de un CLOB se cotiza en unidades por nivel de precio, la profundidad de un AMM es LL por tick — y la conversión es exactamente la identidad Δy=LΔP\Delta y = L\Delta\sqrt{P} de arriba.

Ticks: una grilla de precios espaciada logarítmicamente

Los rangos no pueden empezar y terminar en precios arbitrarios; deben ajustarse a ticks. El tick ii corresponde al precio

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

de modo que cada tick está a un punto básico de sus vecinos — no en términos absolutos, sino relativos. Este espaciado logarítmico es deliberado: una grilla aditiva fija sería absurdamente gruesa para un token que cotiza a $0.0001 y absurdamente fina a $100{,}000, mientras que una grilla geométrica da una resolución uniforme de 1 pb en cualquier escala de precio. La librería TickMath convierte en ambos sentidos — getSqrtRatioAtTick y getTickAtSqrtRatio — usando manipulación de bits sobre constantes precomputadas en lugar de invocar una exponencial. Los índices de tick están acotados por MIN_TICK = -887272 y MAX_TICK = 887272, lo que cubre el rango de precios [2128,2128][2^{-128}, 2^{128}]: suficientemente amplio para cualquier par de tokens que pueda existir en aritmética uint256.

No todos los ticks son utilizables. Cada nivel de comisión impone un espaciado de tick (tick spacing), y las posiciones solo pueden usar ticks divisibles por él:

Nivel de comisión Espaciado de tick Ancho mínimo de rango Uso típico
0.01% 1 ~1 pb stable/stable
0.05% 10 ~10 pb pares stable, ETH/stables
0.30% 60 ~60 pb majors
1.00% 200 ~2% exóticos / volátiles

Los niveles 0.05%/0.30%/1% se lanzaron en mayo de 2021; el nivel 0.01% se agregó por votación de gobernanza en noviembre de 2021. Un espaciado más grueso en los pools de comisión alta mantiene bajo el número de ticks potencialmente cruzables y acota los costos de gas de los swaps.

Una trampa de decimales que muerde a todos alguna vez: el precio crudo on-chain es token1 por token0 en unidades base. En el pool mainnet de USDC/WETH, el token0 es USDC (6 decimales) y el token1 es WETH (18 decimales), así que un precio humano de $3{,}000 por ETH corresponde a un precio crudo de 1012/30003.333×10810^{12}/3000 \approx 3.333 \times 10^{8} WETH-wei por unidad de USDC, que vive en el tick

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

con sqrtPriceX961.4465×1033\texttt{sqrtPriceX96} \approx 1.4465 \times 10^{33}. Si tu dashboard de monitoreo muestra un tick cercano a 196k para USDC/WETH, ahora sabes por qué — y que el precio humano es (sqrtPriceX96/296)210dec0dec1\left(\texttt{sqrtPriceX96}/2^{96}\right)^2 \cdot 10^{\,\text{dec}_0 - \text{dec}_1} invertido según se necesite.

Montos de tokens a partir de (L, rango de precio): las fórmulas exactas

El entregable central de esta sección: dada una posición con liquidez LL en [pa,pb][p_a, p_b] y precio actual PP, ¿qué mantiene? Integrar las ecuaciones de swap a lo largo del rango da tres casos:

Precio por debajo del rango (PpaP \le p_a) — la posición es 100% token0:

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

Precio por encima del rango (PpbP \ge p_b) — la posición es 100% token1:

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

Precio dentro del rango (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)

Esto es exactamente lo que calculan SqrtPriceMath.getAmount0Delta y getAmount1Delta (con redondeo dirigido — el contrato siempre redondea en contra del usuario, un detalle que importa si replicas esto en un backtester y te preguntas por discrepancias a nivel de 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)

Ejemplo resuelto: ETH/USDC, rango [2500, 3500]

Supongamos que ETH cotiza a P=3000P = 3000 USDC y quieres depositar 1 ETH en el rango [2500,3500][2500, 3500]. Raíces cuadradas: 2500=50\sqrt{2500} = 50, 3000=54.7723\sqrt{3000} = 54.7723, 3500=59.1608\sqrt{3500} = 59.1608.

La pata de ETH fija 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 pata de USDC se deduce entonces:

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}

Así que mintear esta posición requiere 1 ETH + 3,523.69 USDC, valor total $6,523.69, y nota que las patas no son 50/50 — la división depende de dónde se encuentre PP dentro del rango (un rango asimétrico es precisamente la forma de expresar una visión direccional, o de colocar una "orden de rango" pura en un solo token).

Ahora recorramos el precio hasta los límites:

  • En P=2500P = 2500 la posición se ha convertido por completo en ETH: x=738.37×(1/501/59.1608)=2.2867x = 738.37 \times (1/50 - 1/59.1608) = 2.2867 ETH, valorado en $5,716.68. Compraste 1.2867 ETH en la caída a un precio promedio ponderado por liquidez de 3523.69 / 1.2867 \approx \2{,}739$.
  • En P=3500P = 3500 se ha convertido por completo en USDC: y=738.37×(59.160850)=6,764.06y = 738.37 \times (59.1608 - 50) = 6{,}764.06 USDC. Vendiste tu ETH en la subida a un promedio de $3,240.

Esa es la lectura de orden de rango hecha concreta: la posición es una escalera de bids desde 3000 hacia abajo hasta 2500 y de asks desde 3000 hacia arriba hasta 3500, con tamaño por tick proporcional a LL. Y la concentración es lo que se te paga: una posición estilo v2 de rango completo con el mismo capital de $6,523.69 tendría Lv2=V/(2P)=59.55L_{v2} = V/(2\sqrt{P}) = 59.55 — la posición concentrada cotiza 12.4× más profundidad por tick, y (mientras está en rango) gana comisiones a 12.4× la tasa por dólar de capital.

Contabilidad de comisiones: feeGrowthGlobal y feeGrowthInside

Las comisiones de v3 no se capitalizan dentro de la posición (una ruptura deliberada respecto a v2, donde las comisiones se reinvertían en k\sqrt{k}). Se acumulan aparte, por token, y la contabilidad es una pequeña obra maestra de teneduría de libros O(1) que vale la pena entender porque todo pipeline de analítica de LP la reimplementa.

El pool mantiene dos acumuladores globales, feeGrowthGlobal0X128 y feeGrowthGlobal1X128: comisiones acumuladas por unidad de liquidez desde la creación del pool, en punto fijo Q128.128. En cada swap, el monto de la comisión (tomado del token de entrada) se divide entre el LL actual en rango y se suma al acumulador. Este es el mecanismo detrás de la regla cardinal de la economía de v3: las comisiones se acumulan solo para la liquidez que está en rango en el momento del swap. Las posiciones fuera de rango no son simplemente inventario inerte — ganan exactamente cero mientras están inactivas.

Para atribuir la porción correcta de crecimiento global a un rango finito, cada tick inicializado ii almacena feeGrowthOutside0/1X128 — el crecimiento de comisiones que ocurrió en el otro lado del tick respecto al precio actual (el valor invierte su interpretación cada vez que se cruza el tick, lo que es lo que hace que el esquema sea O(1)). Entonces, para una posición en [i,iu][i_\ell, i_u] con tick actual 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)

Cada posición almacena una instantánea feeGrowthInsideLast, y las comisiones no cobradas son simplemente

fees owed=Lfinsidenowfinsidelast2128\text{fees owed} = L \cdot \frac{f_{\text{inside}}^{\text{now}} - f_{\text{inside}}^{\text{last}}}{2^{128}}

actualizada de forma perezosa cada vez que se toca la posición. Dos consecuencias prácticas. Primero, los deltas de feeGrowthInside son la única forma honesta de medir el ingreso por comisiones de una posición — muestrear el volumen a nivel de pool y prorratear por tu participación en el TVL lo hace mal cada vez que el precio se mueve alrededor de los límites de tu rango. Segundo, como las comisiones quedan como tokensOwed en lugar de capitalizarse, los retornos realizados de LP tienen un término de drag de efectivo que v2 no tenía; los vaults de auto-compounding existen precisamente para arbitrar esto (menos su propia comisión).

Diagrama de feeGrowthGlobal, feeGrowthOutside en los ticks límite del rango, y la resta de feeGrowthInside

El payoff: un straddle corto que te pagan por sostener (quizás)

Dentro del rango, el valor de la posición en función del precio es

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)

Cóncavo en PP — el término 2LP2L\sqrt{P} es toda la historia. Fuera del rango se vuelve lineal: pendiente x(pa)x(p_a) por debajo (estás largo en una bolsa fija de ETH), pendiente 0 por encima (estás plano en USDC). Recorramos nuestro ejemplo resuelto a lo largo del rango y comparémoslo contra simplemente mantener (HODL) los tokens depositados:

PP (USDC/ETH) Valor LP Valor HODL Divergencia
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

El LP tiene un desempeño inferior al HODL en ambas direcciones y solo lo iguala en el precio de minteo. Alza limitada, participación amplificada a la baja, valor relativo máximo en el strike... este es el payoff de un straddle corto (más precisamente, una vez que se netean las colas lineales contra el benchmark de HODL, una posición corta en una tira de opciones con strikes distribuidos a lo largo de [pa,pb][p_a, p_b]). El flujo de comisiones es la prima. Concentrar el rango es elegir strikes más ajustados: más prima por unidad de tiempo mientras se está en rango, divergencia más rápida y profunda cuando el precio se mueve. Todo LP de v3 es un trader corto en volatilidad, lo haya elegido o no — el primo on-chain del trade-off de riesgo de inventario que Avellaneda–Stoikov formaliza para los market makers de libro de órdenes, con el ancho del rango jugando el rol del spread cotizado.

Valor de la posición LP versus HODL a lo largo del rango de precios mostrando el payoff cóncavo similar a un straddle corto

El nombre tradicional para la brecha en esa tabla es pérdida impermanente (divergencia), pero IL-versus-HODL es un benchmark defectuoso: mezcla la pérdida que tomaste como proveedor de liquidez con el riesgo de mercado que habrías cargado de todas formas. La descomposición más aguda viene de Milionis, Moallemi, Roughgarden y Zhang (2022), "Automated Market Making and Loss-Versus-Rebalancing" (arXiv:2208.06046). Se compara al LP no contra HODL sino contra un portafolio de rebalanceo que mantiene, en cada instante, las mismas cantidades de token que el pool — pero que opera al precio de mercado externo sin fricciones en lugar de contra arbitrajistas. La diferencia es LVR ("lever"): el componente del P&L del LP que es pura selección adversa, pagado a los arbitrajistas que aprovechan las cotizaciones obsoletas del AMM tras cada movimiento de precio. Bajo un precio de movimiento browniano geométrico con volatilidad σ\sigma, el LVR se acumula a la tasa instantánea

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

— una "fórmula de Black–Scholes para AMMs", como lo plantean los autores, con x(P)|x'(P)| la profundidad marginal del pool en el precio actual. Para el pool de producto constante de rango completo esto colapsa en el famoso σ28\frac{\sigma^2}{8} del valor del pool por unidad de tiempo: al 5% de volatilidad diaria, aproximadamente 3.1 pb del pool se filtran hacia los arbitrajistas cada día, con o sin comisiones. La concentración multiplica x(P)|x'(P)| — nuestro ejemplo de 12.4× de profundidad arriba es también una máquina de LVR de ~12.4× mientras está en rango. Las comisiones deben superar ese sangrado para que la posición sea +EV, y el LVR (a diferencia del "IL") es un costo corriente cubrible y predecible, lo que lo convierte en la unidad de cuenta correcta. El cálculo completo de rentabilidad — APR de comisiones versus LVR versus volatilidad realizada, cuándo hacer LP supera a las opciones cortas con delta-hedge — es el tema de la próxima inmersión profunda en pérdida impermanente y LVR, y la mecánica de cobertura recibe su propio tratamiento en estrategias de LP en v3 y cobertura.

Otro costo vive una capa más abajo: como las cotizaciones del AMM se actualizan solo cuando alguien opera, toda posición de LP también está expuesta a los juegos de mempool que se juegan alrededor de esas operaciones — ataques sandwich contra los que swapean y pagan tus comisiones, y bundles de arbitraje que realizan tu LVR bloque a bloque. Ese ecosistema se mapea en el artículo sobre MEV y ataques sandwich.

Leyendo el estado del pool on-chain

Todo lo anterior es observable a partir de tres llamadas económicas contra el contrato del pool.

slot0() empaqueta el estado activo en un solo slot de storage: sqrtPriceX96, el tick actual, los índices de observación del oráculo, y las banderas de comisión de protocolo/bloqueo. liquidity() devuelve el LL agregado actual en rango — nota que esto no es el TVL; es el parámetro de profundidad activo en el tick actual y salta de forma discontinua cuando el precio cruza un tick inicializado. ticks(int24) devuelve el estado por tick: liquidityGross (LL total que referencia el tick), liquidityNet (LL con signo que se suma al cruzar de izquierda a derecha), y los acumuladores feeGrowthOutside. Iterar liquidityNet sobre los ticks inicializados (el tickBitmap te dice cuáles existen sin escanear los 1.7 millones) reconstruye el perfil de profundidad completo L(i)L(i) — tu instantánea del libro de órdenes.

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)

Las posiciones en sí viven en dos lugares. El pool central las indexa por (owner, tickLower, tickUpper) — un slot agregado por cada tripleta owner-rango. El retail y la mayoría de los fondos, en cambio, mintean a través de la periferia NonfungiblePositionManager (mainnet: 0xC36442b4a4522E871399CD717aBDD847Ab11FE88), que envuelve cada posición en un NFT ERC-721 y expone positions(tokenId) devolviendo la tupla completa: tokens, nivel de comisión, rango, LL, feeGrowthInsideLast, y tokensOwed. Para el monitoreo de portafolio, esa única llamada más el feeGrowthInside actual del pool (recalculado a partir de ticks() como en la sección anterior) te da valor mark-to-market y comisiones acumuladas sin tocar un indexador — aunque para cualquier cosa histórica vas a necesitar la reproducción de eventos de swap o un subgraph, porque el crecimiento de comisiones depende de la trayectoria y la cadena solo almacena los acumuladores actuales.

Dos detalles operativos que vale la pena interiorizar antes de desplegar capital. Primero, el espaciado de tick cuantiza tu espacio de estrategias: en el nivel de 0.05% puedes colocar rangos de 10 pb de ancho y correr algo cercano a una verdadera orden límite (mintear justo arriba/abajo del spot, cobrar la comisión, quemar después del cruce — el whitepaper enmarca explícitamente este caso de uso de "orden de rango"), mientras que en el nivel de 1% tu rango mínimo es de ~2% de ancho y la analogía con el LOB se vuelve más gruesa. Segundo, una orden de rango es una orden límite sin prioridad de cancelación: si el precio cruza tu rango y vuelve, el inventario hace un viaje de ida y vuelta y devuelves el edge (quedándote con las comisiones). Los rangos pasivos son cotizaciones que no puedes retirar — que es exactamente por qué la pregunta de la frecuencia de rebalanceo, y el lente del LVR para responderla, importan tanto.

Dónde te deja esto

El stack de v3, comprimido: los precios son ticks sobre una grilla geométrica de 1.0001; la profundidad es LL, convertible a montos de token con nada más que diferencias de raíces cuadradas; las comisiones son un acumulador por LL que diferencias a través de los límites de tu rango; y la posición resultante es una orden de rango corta en volatilidad cuyo costo corriente tiene un nombre, una fórmula, y un número de arXiv. Con las primitivas en mano, las preguntas interesantes se vuelven cuantitativas: qué tan ancho, con qué frecuencia rebalancear, y si las comisiones compensan el LVR para un pool y régimen dados — que es precisamente hacia donde va esta serie a continuación.

Referencias

  • Adams, H., Zinsmeister, N., Salem, M., Keefer, R., Robinson, D. (2021). Uniswap v3 Core (whitepaper).
  • Librerías centrales de 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

Mantente a la vanguardia

Suscríbete a nuestro boletín para recibir información exclusiva sobre trading con IA, análisis de mercado y actualizaciones de la plataforma.

Respetamos tu privacidad. Puedes darte de baja en cualquier momento.