Degen Code

Degen Code

Numerical Optimization — Part V: Closed-Form Solutions

The Answer Hiding in Plain Sight

May 20, 2026
∙ Paid

In Part IV, while deriving analytical gradients for the Newtonian methods benchmark, we paused on the simple case of two V2 pools with the same token pair. The profit function P(x) and its derivative dP/dx​ both had clean algebraic expressions. Setting the derivative to zero and solving algebraically gave us the optimal trade size in a single step:

\(\frac{dP}{dx} = f^2 \cdot \frac{R_{ETH}^B \cdot R_{USDC}^B}{(R_{USDC}^B + x_{eff})^2} \cdot \frac{R_{USDC}^A \cdot R_{ETH}^A}{(R_{ETH}^A + ETH_{eff})^2} - 1\)

Setting this to zero and solving numerically gave the optimal trade size: x* ≈ 7,011 USDC, P ≈ 50 USDC.

This is not itself a closed-form solution — it’s numerical root-finding on the gradient, which is faster than iterative optimization on P(x) but still not an explicit formula. The key observation, though, was that the gradient equation dP/dx = 0 is an algebraic equation in x, not a transcendental one. That means it admits a closed-form solution, but we didn’t derive it.

Deriving the Closed-Form Solution

Let’s close that loop now. Rewriting Part IV’s derivative in our reserve notation (a = ETH in Pool A, b = USDC in Pool A, c = ETH in Pool B, d = USDC in Pool B, f = fee factor), and noting that x_eff​ = fx and ETH_eff​ = f⋅eth where eth = f⋅c⋅x/(d+f⋅x):

\(\frac{dP}{dx} = f^2 \cdot \frac{c \cdot d}{(d + fx)^2} \cdot \frac{a \cdot b}{(a + f \cdot \text{eth})^2} - 1 = 0\)

Move the 1 to the other side:

\(f^2 \cdot \frac{c \cdot d}{(d + fx)^2} \cdot \frac{a \cdot b}{(a + f \cdot \text{eth})^2} = 1\)

Substitute:

\(f^2 \cdot \frac{c \cdot d}{(d + fx)^2} \cdot \frac{a \cdot b}{\left(a + \frac{f^2 c x}{d + fx}\right)^2} = 1\)

Clean up the nested denominator:

\(a + \frac{f^2 c x}{d + fx} = \frac{a(d + fx) + f^2 c x}{d + fx} = \frac{ad + afx + f^2 c x}{d + fx} = \frac{ad + fx(a + fc)}{d + fx}\)

Substitute back, then transform the fraction in the denominator:

\(\frac{a \cdot b}{\left(\frac{ad + fx(a + fc)}{d + fx}\right)^2} = a \cdot b \cdot \frac{(d + fx)^2}{(ad + fx(a + fc))^2}\)

Cancel terms:

\(\begin{aligned} f^2 \cdot \frac{c \cdot d}{\cancel{(d + fx)^2}} \cdot a \cdot b \cdot \frac{\cancel{(d + fx)^2}}{(ad + fx(a + fc))^2} = 1 \\ \frac{f^2 \cdot a \cdot b \cdot c \cdot d}{(ad + fx(a + fc))^2} = 1 \end{aligned} \)

Take the square root of both sides, only considering the positive root of 1:

\(\frac{f\sqrt{abcd}}{ad + fx(a + fc)} = 1\)

Solve for x:​​

\(\begin{array} f\sqrt{abcd} = ad + fx(a + fc) \\ fx(a + fc) = f\sqrt{abcd} - ad \\ x^* = \frac{f\sqrt{abcd} - ad}{f(a + fc)} \end{array}\)

This takes us from the Part IV problem setup to its closed-form solution.

Other Closed-Form Solutions

Multiple independent derivations of closed-form solutions exist for different liquidity pool designs.

I’m sure other solutions exist that I have not yet seen, so treat this section as a survey useful primarily as introduction.

Angeris et al. (2019) — Single Pool vs. Reference Market

Paper: An Analysis of Uniswap Markets (arXiv:1911.03380)

Setting: A single constant product pool with reserves R_α​, R_β​, product k = R_α⋅R_β​, fee 1−γ, and an infinitely liquid external reference market with price m_p​.

Result: The optimal arbitrage trade is:

\(\begin{aligned} &\Delta_\alpha^* = \left(R_\alpha - \sqrt{\frac{k}{\gamma \cdot m_p}}\right)^+ \\ &\text{where} \ (x)^+ = \max(x, 0) \end{aligned}\)

Significance: This is the foundational result. It shows the arbitrage problem is convex and admits a simple closed-form. The no-arbitrage condition γ⋅m_p​ ≤ m_u ​≤ γ^(−1)⋅m_p​ follows directly. The arbitrageur trades until the pool price equals the market price (adjusted for fees).

Limitation: Only applies to single-pool arbitrage against an external market. Does not address cyclic arbitrage across multiple pools.

Angeris & Chitra (2020) — CFMM Framework

Paper: Improved Price Oracles: Constant Function Market Makers (arXiv:2003.10001)

Setting: General constant function market makers, including constant mean markets (Balancer) and Curve.

Key results:

  • The trading set of any CFMM used in practice is convex

  • The optimal arbitrage problem is efficiently solvable

  • Lower bounds on total reserve value via Fenchel conjugate

Significance: Provides the general convex optimization framework. Shows that efficient solutions always exist for CFMM arbitrage. The multi-asset formulation generalizes the single-pool result.

Limitation: While convexity guarantees efficient numerical solutions, closed-form expressions are not available for all CFMM types (e.g., Curve reserve values).

Willetts & Harrington (2024) — Multi-Token Pools

Paper: Closed-form solutions for generic N-token AMM arbitrage (arXiv:2402.06731)

Setting: N-token geometric mean market maker pools (Balancer) with fees.

Key result: For a pool with N tokens, reserves R, weights w, and fee γ, given a known trade signature s (which tokens are bought vs. sold), the optimal arbitrage trade for each active token i is:

\(\Phi_i = \gamma^{-d_i}\left(\breve{k}\left(\frac{\breve{w}_i \gamma^{d_i}}{m_{p,i}}\right)^{1-\breve{w}_i}\prod_{j \neq i}\left(\frac{m_{p,j}}{\breve{w}_j \gamma^{d_j}}\right)^{\breve{w}_j} - R_i\right)\)

​​Trade signature search: For N-token pools, one must search over possible trade signatures. The number of valid signatures grows as roughly 3^N, but:

  • For N ≤ 5, exhaustive search is faster than convex optimization

  • The search is embarrassingly parallel across signatures (GPU-friendly)

  • Heuristics can reduce the search space

Significance: First closed-form for multi-asset pools. In simulation, it outperforms CVXPY convex optimization and captures arbitrage opportunities sooner. In competitive dueling simulations, the closed-form arbitrageur wins even when the convex optimizer gets priority.

Limitation: Requires knowing the trade signature a priori. Exhaustive signature search becomes expensive for N > 7. Extends to amplified liquidity (Curve-style) via virtual reserves.

Hartigan (2026) — Multi-Hop Paths via Möbius Transformations

Article: “The Geometry of Arbitrage: Generalizing Multi-Hop DEX Paths via Möbius Transformations” (Medium: Jeffrey Hartigan)

Setting: Multi-hop cyclic arbitrage through V2 (constant product) pools.

Origin: ​Hartigan derived the closed-form solution for the two-pool case in a different article, and assumed the result was a special case. He wrotes that multi-hop paths would “likely produce higher-degree polynomials that didn’t admit clean analytic solutions”.

Then while manually working out the input-output function for a 4-hop route, he noticed a continued-fraction structure forming. No matter how many pools he chained, the transfer function always collapsed into the same form:

\(\frac{Kx}{M + Nx}\)

He recognized this as a Möbius transformation, which has a unique composition property that we will discuss in depth.

Key result: The K/M/N recurrence and general formula:

\(x^* = \frac{\sqrt{KM} - M}{N}\)

Performance claims (from Hartigan’s article):

  • 50–60x faster than binary search on CPU (single path)

  • Maps trivially to GPU tensor operations (promote K, M, N to batch tensors)

  • At ~10,000 parallel routes, GPU overtakes CPU

  • At 1,000,000 routes, GPU evaluates entire search space in ~50ms

  • Zero iterations regardless of path length

Significance: Hartigan’s article is the primary source for the Möbius transformation insight and the K/M/N recurrence. It shows that the algebraic structure of constant product AMMs makes multi-hop cyclic arbitrage exactly solvable, and makes the deep connection between financial liquidity and the geometry of the complex plane — the 2×2 matrices used to compose swap hops are the same mathematical objects that describe how the Riemann sphere maps onto itself and how relativistic velocities compose.

Two notes on the N coefficient:

  1. The listed recurrence in Hartigan’s article (N′ = N⋅r_i​ + M⋅f_i​) has an error — it doesn’t match the matrix multiplication from which it derives. The matrix bottom-left entry gives N′ = f_i​⋅K + r_i​⋅N instead. The article’s own note that “N uses K before it is updated” directly contradicts the formula it accompanies: the formula references M, but the note references K. Since both the matrix derivation and Hartigan’s independently-verified 2-hop result confirm K, the note is correct and the formula has a likely typo (K written as M). The listed formula yields N = f⋅(a+d) for the 2-hop case, while both the matrix and Hartigan’s independently-verified 2-hop result give N = f⋅(b⋅f+d). Notably, Hartigan’s own verification section is internally inconsistent with his recurrence: his 2-hop coefficients (N = k⋅(b⋅k+d)) cannot be produced by applying his listed recurrence to the same setup.

  2. Hartigan’s N = f⋅(b⋅f + d) and our N = f⋅(a + f⋅c) are both correct when considered for a given pool structure — they correspond to the same cyclic arbitrage starting from different tokens. Hartigan’s convention starts with Pool A (sell ETH, buy USDC), while ours starts with Pool B (input USDC, buy ETH). Because the matrix product M_2⋅M_1 ≠ M_1⋅M_2 in general, the N coefficient depends on which pool is the first hop. The K and M values are the same regardless of starting point.

Limitation: Only applies to constant product (V2) AMMs. Does not address V3 concentrated liquidity, Curve, or budget-constrained multi-path problems.

Community Derivations — Two-Pool Cyclic Formula

Source: Ethereum StackExchange

Setting: Two V2 pools with the same token pair, cyclic path: input → AMM A → AMM B → output.

Notation: AMM A has input reserve y_a​, output reserve x_a​; AMM B has input reserve x_b​, output reserve y_b​. Fee factor f = 1−γ.

Result:

\(\begin{aligned} &k = f \cdot x_b + f^2 \cdot x_a \\ &a_q = k^2 \\ &b_q = 2k \cdot y_a \cdot x_b \\ &c_q = (y_a \cdot x_b)^2 - f^2 \cdot x_a \cdot y_b \cdot y_a \cdot x_b \\ &r = \frac{-b_q + \sqrt{b_q^2 - 4a_q c_q}}{2a_q} \end{aligned}\)

​​​Note: a_q​, b_q​, c_q​ are the quadratic equation coefficients, not pool reserves — a naming collision that makes this form confusing compared to the reserve-labeled version.

Variable mapping to our notation: The community formula’s variables are defined by direction in the path, not by pool label:

  • x_a​ = output reserve of AMM A (first hop) = ETH in Pool B = c

  • y_a​ = input reserve of AMM A (first hop) = USDC in Pool B = d

  • x_b​ = input reserve of AMM B (second hop) = ETH in Pool A = a

  • y_b​ = output reserve of AMM B (second hop) = USDC in Pool A = b

With this mapping, k = f⋅a+f^2⋅c = f⋅(a+f⋅c), which is exactly the correct N from the Möbius recurrence. This is not a coincidence — the community quadratic and the Möbius formula solve the same dP/dx = 0 equation, and the k in the community formula plays the same structural role as N in the Möbius formula.

Why it looks different from the Möbius formula: This is the raw quadratic formula applied to the numerator of dP/dx=0 after clearing denominators. The numerator is a cubic that factors as (d+fx)×(quadratic); the community formula solves the quadratic, while the Möbius approach recognizes that the equation K⋅M = (M+N⋅x)^2 can be unwound via K⋅M​ — collapsing the quadratic to a simple division. Both give the same answer. The community form requires no insight about Möbius transformations — just mechanical algebra. It generalizes poorly beyond two pools (higher-degree numerators), which is why the Möbius approach is preferred for multi-hop paths.

Significance: This is what many practitioners implement first, because it requires no insight about Möbius transformations — just mechanical algebra.

Wachter (2022) — ETH Zurich Thesis

Paper: Distributed Computing: Arbitrage Opportunities on Decentralized Exchanges

Setting: Cyclic arbitrage on Uniswap V2 and V3.

Key result for V2: Setting the derivative of the profit function to zero and solving yields a closed-form expression for the optimal input. In Wachter’s notation (where k_i​ denotes the constant product Rx_i​ ⋅ Ry_i​ for pool i), the solution is a ratio of reserve products and square roots thereof — algebraically equivalent to the other forms surveyed above, but expressed with different intermediate variables.

V3 approach: For V3 pools with tick boundaries, ternary search (O(log n)) is used since closed-form is unavailable.

Significance: Provides the V2 closed-form and explicitly acknowledges that V3 requires iterative methods.

Deriving the Solutions

User's avatar

Continue reading this post for free, courtesy of BowTiedDevil.

Or purchase a paid subscription.
© 2026 BowTiedDevil · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture