myco-bonding-curve/tests/test_concentrated_2clp.py

97 lines
3.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Tests for 2-CLP concentrated liquidity pool."""
import numpy as np
import pytest
from src.primitives.concentrated_2clp import (
compute_invariant,
virtual_offset_x,
virtual_offset_y,
calc_out_given_in,
calc_in_given_out,
spot_price,
price_bounds,
)
class TestInvariant:
def test_balanced_pool(self):
"""Balanced pool should have positive invariant."""
L = compute_invariant(1000.0, 1000.0, 0.9, 1.1)
assert L > 0
def test_invariant_increases_with_reserves(self):
"""More reserves → larger invariant."""
L1 = compute_invariant(100.0, 100.0, 0.9, 1.1)
L2 = compute_invariant(200.0, 200.0, 0.9, 1.1)
assert L2 > L1
def test_narrow_range_higher_invariant(self):
"""Narrower price range → higher L for same balances (more concentrated)."""
L_wide = compute_invariant(1000.0, 1000.0, 0.5, 2.0)
L_narrow = compute_invariant(1000.0, 1000.0, 0.95, 1.05)
assert L_narrow > L_wide
def test_virtual_reserves_satisfy_cpmm(self):
"""(x + a)(y + b) should equal L²."""
x, y = 500.0, 800.0
sa, sb = 0.8, 1.2
L = compute_invariant(x, y, sa, sb)
a = virtual_offset_x(L, sb)
b = virtual_offset_y(L, sa)
product = (x + a) * (y + b)
assert abs(product - L**2) < 1e-6
class TestSwaps:
def test_invariant_preserved(self):
"""Swap should preserve L."""
x, y = 1000.0, 1000.0
sa, sb = 0.9, 1.1
L_before = compute_invariant(x, y, sa, sb)
dy = calc_out_given_in(x, y, sa, sb, 100.0, token_in=0)
L_after = compute_invariant(x + 100.0, y - dy, sa, sb)
assert abs(L_after - L_before) / L_before < 1e-10
def test_round_trip(self):
"""calc_in_given_out inverts calc_out_given_in."""
x, y = 1000.0, 1000.0
sa, sb = 0.9, 1.1
amount_in = 50.0
amount_out = calc_out_given_in(x, y, sa, sb, amount_in, token_in=0)
recovered = calc_in_given_out(x, y, sa, sb, amount_out, token_out=1)
assert abs(recovered - amount_in) < 1e-8
def test_spot_price_in_range(self):
"""Spot price should be within [α, β]."""
x, y = 1000.0, 1000.0
sa, sb = 0.9, 1.1
sp = spot_price(x, y, sa, sb)
alpha, beta = price_bounds(sa, sb)
assert alpha <= sp <= beta
def test_concentrated_less_slippage(self):
"""Narrower range = less slippage for same-size swap."""
x, y = 1000.0, 1000.0
# Narrow range
out_narrow = calc_out_given_in(x, y, 0.95, 1.05, 50.0)
# Wide range
out_wide = calc_out_given_in(x, y, 0.5, 2.0, 50.0)
# Narrow range should give better price (more output)
assert out_narrow > out_wide
def test_both_directions(self):
"""Swap in both directions should work."""
x, y = 1000.0, 1000.0
sa, sb = 0.9, 1.1
# x → y
dy = calc_out_given_in(x, y, sa, sb, 100.0, token_in=0)
assert dy > 0
# y → x
dx = calc_out_given_in(x, y, sa, sb, 100.0, token_in=1)
assert dx > 0