Skip to content

Commit

Permalink
Fixing stableswap spot price calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
poliwop committed Jul 4, 2023
1 parent c3bea45 commit c66ac7f
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
5 changes: 4 additions & 1 deletion hydradx/model/amm/stableswap_amm.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
30 changes: 30 additions & 0 deletions hydradx/tests/test_stableswap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit c66ac7f

Please sign in to comment.