Visualizing Concentrated Liquidity with Python Simulation
Chen Xu, Ph.D, CFA4 min read·Just now--
Uniswap V3 is easier to understand as a local state-transition system than as a static LP diagram.
Uniswap V3 is often introduced with static pictures: a liquidity range, a current price, and a payoff shape. But many of the interesting behaviors of concentrated liquidity do not live in that static picture. They appear locally, when price moves inside a narrow region, when the pool crosses a tick boundary, and when two swaps that seem symmetric on paper produce different state transitions in practice.
To study that local behavior, I built a small Python-driven simulator around real Uniswap V3 execution. Solidity defines the protocol truth; Python drives controlled scenarios, records state changes, and visualizes the results. That makes it possible to inspect sqrtPriceX96, tick movement, token deltas, and gas step by step.
In this note, I focus on one narrow question: what does concentrated liquidity look like from very close up? Even in a tiny local experiment, three things become clear quickly. Price is continuous while tick is discrete. A pool can remain inside the same tick label while its true price keeps moving. And opposite swaps that look symmetric at first glance are not necessarily symmetric in their local effect.
Continuous price, discrete tick
I started with a small alternating swap path near a boundary-adjacent region. At first glance, the tick path looks almost trivial: the pool simply flips between ticks 54 and 55.
But tick is only a discretized projection of the local price state. The actual pool price lives in sqrtPriceX96, which continues to move even when the tick label does not.
sqrtPriceX96, not tick alone, is the more faithful local state variable.In my local experiment, when the pool sits at tick 54, the continuous price inferred from sqrtPriceX96 is on average about 0.51 bps above the price implied by the tick itself. At tick 55, that gap almost disappears, falling to roughly 0.01 bps.
The key intuition is simple: tick is a label, not the full state. The real local price state is continuous.
Opposite swaps are not as symmetric as they look
A natural intuition is that opposite swaps of the same size should cancel each other out locally. In practice, that intuition is too crude.
To make the comparison cleaner, I anchored both directions to the same token0 quantity from the same baseline state at tick 55:
swapExact0For1(1e14)swap1ForExact0(1e14)
In continuous-price terms, the two moves are almost mirror images:
swapExact0For1moves price by about -0.50 bpsswap1ForExact0moves price by about +0.50 bps
So in continuous-price space, the local impact is nearly symmetric.
But the tick response is not:
swapExact0For1moves the pool from tick 55 to tick 54swap1ForExact0leaves the pool at tick 55
So even when continuous price impact is nearly symmetric, the discrete tick outcome can still differ.
What this means
This small experiment already suggests a better way to think about Uniswap V3.
Concentrated liquidity is easier to understand as a local state-transition system than as a static LP picture. Tick alone is not enough; the true pool price lives in sqrtPriceX96. And symmetric-looking swaps do not guarantee symmetric local outcomes, even when both directions are anchored to the same token0 quantity.
The static LP view is not wrong. It is just incomplete. If you want to understand concentrated liquidity from close up — or reason about protocols built on top of it — you need to pay attention to the local mechanics.
In the next note, I’ll show how I built the small simulator behind these experiments, using Solidity as the source of truth and Python as the scenario engine.