|
1 | 1 | import copy |
2 | 2 | import math |
| 3 | +from datetime import timedelta |
3 | 4 |
|
4 | 5 | import pytest |
5 | 6 | from hypothesis import given, strategies as st, assume, settings, reproduce_failure |
|
11 | 12 | from hydradx.model.amm.agents import Agent |
12 | 13 | from hydradx.model.amm.xyk_amm import XykState |
13 | 14 |
|
| 15 | +settings.register_profile("long", deadline=timedelta(milliseconds=500), print_blob=True) |
| 16 | +settings.load_profile("long") |
14 | 17 |
|
15 | 18 | def test_xyk_init(): |
16 | 19 | tokens = {'A': 1000, 'B': 2000} |
@@ -79,15 +82,54 @@ def test_spot(liq_A, liq_B, fee): |
79 | 82 | st.floats(min_value=0.001, max_value=0.5) |
80 | 83 | ) |
81 | 84 | def test_swap(liq_A, liq_B, fee, swap_pct): |
| 85 | + from hydradx.model.amm.xyk_amm import simulate_swap |
| 86 | + # Test sells |
82 | 87 | tokens = {'A': liq_A, 'B': liq_B} |
83 | | - xyk = XykState(tokens=tokens) |
84 | | - |
85 | | - k_init = xyk.calculate_k() |
86 | 88 | swap_quantity = tokens['A'] * swap_pct |
87 | 89 | agent = Agent(holdings={'A': swap_quantity}) |
88 | | - |
89 | | - # Swap A for B |
90 | | - |
91 | | - xyk.swap(agent, 'A', 'B', sell_quantity=swap_quantity) |
92 | | - k_final = xyk.calculate_k() |
93 | | - assert k_init == pytest.approx(k_final, rel=1e-12) |
| 90 | + for f in [0.0, fee]: |
| 91 | + xyk = XykState(tokens=tokens, trade_fee=f) |
| 92 | + k_init = xyk.calculate_k() |
| 93 | + for buy_tkn, sell_tkn in [('B', 'A'), ('A', 'B')]: |
| 94 | + new_state, new_agent = simulate_swap(xyk, agent, sell_tkn, buy_tkn, sell_quantity=swap_quantity) |
| 95 | + if f == 0.0: |
| 96 | + k_final = new_state.calculate_k() |
| 97 | + else: |
| 98 | + fee_taken = (xyk.liquidity[buy_tkn] - new_state.liquidity[buy_tkn]) * f/(1 - f) |
| 99 | + k_final = math.sqrt(new_state.liquidity[sell_tkn] * (new_state.liquidity[buy_tkn] - fee_taken)) |
| 100 | + if k_init != pytest.approx(k_final, rel=1e-12): |
| 101 | + raise AssertionError("K value changed after swap") |
| 102 | + init_A_total = xyk.liquidity['A'] + agent.get_holdings('A') |
| 103 | + final_A_total = new_state.liquidity['A'] + new_agent.get_holdings('A') |
| 104 | + init_B_total = xyk.liquidity['B'] + agent.get_holdings('B') |
| 105 | + final_B_total = new_state.liquidity['B'] + new_agent.get_holdings('B') |
| 106 | + if init_A_total != pytest.approx(final_A_total, rel=1e-12): |
| 107 | + raise AssertionError("A total quantity changed after swap") |
| 108 | + if init_B_total != pytest.approx(final_B_total, rel=1e-12): |
| 109 | + raise AssertionError("B total quantity changed after swap") |
| 110 | + |
| 111 | + # Test buys, feeless |
| 112 | + swap_A_quantity = tokens['A'] * swap_pct |
| 113 | + swap_B_quantity = tokens['B'] * swap_pct |
| 114 | + agent = Agent(enforce_holdings=False) |
| 115 | + for f in [0.0, fee]: |
| 116 | + xyk = XykState(tokens=tokens, trade_fee=f) |
| 117 | + k_init = xyk.calculate_k() |
| 118 | + for buy_tkn, sell_tkn in [('B', 'A'), ('A', 'B')]: |
| 119 | + buy_quantity = swap_A_quantity if buy_tkn == 'A' else swap_B_quantity |
| 120 | + new_state, new_agent = simulate_swap(xyk, agent, sell_tkn, buy_tkn, buy_quantity=buy_quantity) |
| 121 | + if f == 0.0: |
| 122 | + k_final = new_state.calculate_k() |
| 123 | + else: |
| 124 | + fee_taken = buy_quantity * f/(1 - f) |
| 125 | + k_final = math.sqrt(new_state.liquidity[sell_tkn] * (new_state.liquidity[buy_tkn] - fee_taken)) |
| 126 | + if k_init != pytest.approx(k_final, rel=1e-12): |
| 127 | + raise AssertionError("K value changed after swap") |
| 128 | + init_A_total = xyk.liquidity['A'] + agent.get_holdings('A') |
| 129 | + final_A_total = new_state.liquidity['A'] + new_agent.get_holdings('A') |
| 130 | + init_B_total = xyk.liquidity['B'] + agent.get_holdings('B') |
| 131 | + final_B_total = new_state.liquidity['B'] + new_agent.get_holdings('B') |
| 132 | + if init_A_total != pytest.approx(final_A_total, rel=1e-12): |
| 133 | + raise AssertionError("A total quantity changed after swap") |
| 134 | + if init_B_total != pytest.approx(final_B_total, rel=1e-12): |
| 135 | + raise AssertionError("B total quantity changed after swap") |
0 commit comments