From c66ac7f4163fc9fae3acc95436875cdedd8740fe Mon Sep 17 00:00:00 2001 From: poliwop Date: Tue, 4 Jul 2023 13:52:43 -0500 Subject: [PATCH] Fixing stableswap spot price calculation --- hydradx/model/amm/stableswap_amm.py | 5 ++++- hydradx/tests/test_stableswap.py | 30 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/hydradx/model/amm/stableswap_amm.py b/hydradx/model/amm/stableswap_amm.py index eb901983..1b397b72 100644 --- a/hydradx/model/amm/stableswap_amm.py +++ b/hydradx/model/amm/stableswap_amm.py @@ -108,14 +108,17 @@ def calculate_y(self, reserves: list, d: float, max_iterations=128): return y + # price is denominated in the first asset @property def spot_price(self): x, y = self.liquidity.values() return self.price_at_balance([x, y], self.d) + # price is denominated in the first asset def price_at_balance(self, balances: list, d: float): x, y = balances - return (x / y) * (self.ann * x * y ** 2 + d ** 3) / (self.ann * x ** 2 * y + d ** 3) + c = self.amplification * self.n_coins ** (2 * self.n_coins) + return (x / y) * (c * x * y ** 2 + d ** 3) / (c * x ** 2 * y + d ** 3) def modified_balances(self, delta: dict = None, omit: list = ()): balances = copy.copy(self.liquidity) diff --git a/hydradx/tests/test_stableswap.py b/hydradx/tests/test_stableswap.py index 9ac9f498..e379525e 100644 --- a/hydradx/tests/test_stableswap.py +++ b/hydradx/tests/test_stableswap.py @@ -57,6 +57,36 @@ def test_swap_invariant(initial_pool: StableSwapPoolState): raise AssertionError('Some assets were lost along the way.') +@given(st.integers(min_value=1000,max_value=1000000), + st.integers(min_value=1000,max_value=1000000), + st.integers(min_value=10,max_value=1000) + ) +def test_spot_price(token_a: int, token_b: int, amp: int): + tokens = {"A": token_a, "B": token_b} + initial_pool = StableSwapPoolState( + tokens=tokens, + amplification=amp, + trade_fee=0.0, + unique_id='stableswap' + ) + + spot_price_initial = initial_pool.spot_price + + trade_size=1 + agent = Agent(holdings={"A": 100000, "B": 100000}) + initial_pool.execute_swap(initial_pool, agent, tkn_sell="A", tkn_buy="B", sell_quantity=trade_size) + delta_a = initial_pool.liquidity["A"] - tokens["A"] + delta_b = tokens["B"] - initial_pool.liquidity["B"] + exec_price = delta_a / delta_b + + spot_price_final = initial_pool.spot_price + + if spot_price_initial > exec_price: + raise AssertionError('Initial spot price should be lower than execution price.') + if exec_price > spot_price_final: + raise AssertionError('Execution price should be lower than final spot price.') + + @given(stableswap_config(trade_fee=0)) def test_round_trip_dy(initial_pool: StableSwapPoolState): d = initial_pool.calculate_d()