diff --git a/hydradx/model/amm/arbitrage_agent.py b/hydradx/model/amm/arbitrage_agent.py index 39b334f6..6492823d 100644 --- a/hydradx/model/amm/arbitrage_agent.py +++ b/hydradx/model/amm/arbitrage_agent.py @@ -116,7 +116,8 @@ def calculate_arb_amount_ask(init_state: OmnipoolState, tkn, numeraire, ask: lis asset_fee = state.asset_fee[tkn].compute(tkn=tkn) lrna_fee = state.lrna_fee[numeraire].compute(tkn=numeraire) - cex_price = ask[0] / (1 - cex_fee) + # cex_price = ask[0] / (1 - cex_fee) + cex_price = ask[0] * (1 + cex_fee) # If buying the min amount moves the price too much, return 0 if min_amt < 1e-18: @@ -163,26 +164,38 @@ def calculate_arb_amount_ask(init_state: OmnipoolState, tkn, numeraire, ask: lis return amt -def execute_arb(state, agent, all_swaps, cex_fee=0.0): - +def execute_arb(state, cex, agent, all_swaps): for tkn_pair in all_swaps: swaps = all_swaps[tkn_pair] for swap in swaps: if swap[0] == 'buy': + init_asset = agent.holdings[tkn_pair[0]] + init_numeraire = agent.holdings[tkn_pair[1]] # omnipool leg state.swap(agent, tkn_buy=tkn_pair[0], tkn_sell=tkn_pair[1], buy_quantity=swap[1]['amount']) # CEX leg - agent.holdings[tkn_pair[0]] -= swap[1]['amount'] - agent.holdings[tkn_pair[1]] += swap[1]['amount'] * swap[1]['price'] * (1 - cex_fee) + cex.swap(agent, tkn_buy=tkn_pair[1], tkn_sell=tkn_pair[0], sell_quantity=swap[1]['amount']) + final_asset = agent.holdings[tkn_pair[0]] + final_numeraire = agent.holdings[tkn_pair[1]] + if init_numeraire >= final_numeraire: + raise + if init_asset != final_asset: + raise elif swap[0] == 'sell': + init_asset = agent.holdings[tkn_pair[0]] + init_numeraire = agent.holdings[tkn_pair[1]] # omnipool leg state.swap(agent, tkn_buy=tkn_pair[1], tkn_sell=tkn_pair[0], sell_quantity=swap[1]['amount']) # CEX leg - agent.holdings[tkn_pair[0]] += swap[1]['amount'] - agent.holdings[tkn_pair[1]] -= swap[1]['amount'] * swap[1]['price'] / (1 - cex_fee) - + cex.swap(agent, tkn_buy=tkn_pair[0], tkn_sell=tkn_pair[1], buy_quantity=swap[1]['amount']) + final_asset = agent.holdings[tkn_pair[0]] + final_numeraire = agent.holdings[tkn_pair[1]] + if init_numeraire >= final_numeraire: + raise + if init_asset != final_asset: + raise def calculate_profit(init_agent, agent): profit = {tkn: agent.holdings[tkn] - init_agent.holdings[tkn] for tkn in agent.holdings} diff --git a/hydradx/notebooks/Misc/arbitrage.ipynb b/hydradx/notebooks/Misc/arbitrage.ipynb index 49e8930e..9c3b5c27 100644 --- a/hydradx/notebooks/Misc/arbitrage.ipynb +++ b/hydradx/notebooks/Misc/arbitrage.ipynb @@ -2,13 +2,13 @@ "cells": [ { "cell_type": "code", - "execution_count": 9, + "execution_count": 1, "id": "initial_id", "metadata": { "collapsed": true, "ExecuteTime": { - "end_time": "2023-10-18T19:25:17.176503089Z", - "start_time": "2023-10-18T19:25:17.115140615Z" + "end_time": "2023-10-18T21:23:49.530824832Z", + "start_time": "2023-10-18T21:23:49.491307125Z" } }, "outputs": [], @@ -25,7 +25,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 2, "outputs": [], "source": [ "f = open('data/hdxusd_orderbook.json', 'r')\n", @@ -40,15 +40,15 @@ "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2023-10-18T19:25:17.176752943Z", - "start_time": "2023-10-18T19:25:17.166847366Z" + "end_time": "2023-10-18T21:23:49.547459081Z", + "start_time": "2023-10-18T21:23:49.533619758Z" } }, "id": "30c3ae5c6fb4044d" }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 3, "outputs": [], "source": [ "\n", @@ -142,23 +142,23 @@ "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2023-10-18T19:25:17.176891984Z", - "start_time": "2023-10-18T19:25:17.167008493Z" + "end_time": "2023-10-18T21:23:49.595145927Z", + "start_time": "2023-10-18T21:23:49.552585931Z" } }, "id": "68064af1cadd64fc" }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 4, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "3.7604754221748347\n", + "3.7604658414949\n", "0.00458237037037037\n", - "{('DOT', 'USDT'): [('sell', {'price': 3.7398, 'amount': 14.061}), ('sell', {'price': 3.7406, 'amount': 93.629}), ('sell', {'price': 3.7407, 'amount': 43.0}), ('sell', {'price': 3.7408, 'amount': 40.0}), ('sell', {'price': 3.741, 'amount': 390.018}), ('sell', {'price': 3.7417, 'amount': 3957.426}), ('sell', {'price': 3.7418, 'amount': 3334.869}), ('sell', {'price': 3.7429, 'amount': 374.508}), ('sell', {'price': 3.743, 'amount': 1347.0}), ('sell', {'price': 3.7432, 'amount': 1055.139461517334})], ('HDX', 'USDT'): []}\n" + "{('DOT', 'USDT'): [('sell', {'price': 3.7398, 'amount': 14.061}), ('sell', {'price': 3.7406, 'amount': 93.629}), ('sell', {'price': 3.7407, 'amount': 43.0}), ('sell', {'price': 3.7408, 'amount': 40.0}), ('sell', {'price': 3.741, 'amount': 390.018}), ('sell', {'price': 3.7417, 'amount': 3957.426}), ('sell', {'price': 3.7418, 'amount': 3334.869}), ('sell', {'price': 3.7429, 'amount': 374.508}), ('sell', {'price': 3.743, 'amount': 1347.0}), ('sell', {'price': 3.7432, 'amount': 1055.4145698547363})], ('HDX', 'USDT'): []}\n" ] } ], @@ -169,21 +169,21 @@ "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2023-10-18T19:25:17.190510706Z", - "start_time": "2023-10-18T19:25:17.167128399Z" + "end_time": "2023-10-18T21:23:49.595561869Z", + "start_time": "2023-10-18T21:23:49.594894378Z" } }, "id": "ef086a726e0e13be" }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 5, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "{'USDT': 2083.132005214691, 'DOT': 0.0, 'HDX': 0}\n" + "{'USDT': 2083.1319987773895, 'DOT': 0.0, 'HDX': 0}\n" ] } ], @@ -191,7 +191,7 @@ "state = init_state.copy()\n", "init_agent = Agent(holdings={'USDT': 1000000000, 'DOT': 1000000000, 'HDX': 1000000000}, unique_id='bot')\n", "agent = init_agent.copy()\n", - "execute_arb(state, agent, all_swaps, cex_fee=cex_fee)\n", + "execute_arb(state, cex, agent, all_swaps)\n", "\n", "profit = calculate_profit(init_agent, agent)\n", "\n", @@ -208,22 +208,22 @@ "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2023-10-18T19:25:17.261225047Z", - "start_time": "2023-10-18T19:25:17.187559171Z" + "end_time": "2023-10-18T21:23:49.595771681Z", + "start_time": "2023-10-18T21:23:49.595107623Z" } }, "id": "8d4817129c26f839" }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 5, "outputs": [], "source": [], "metadata": { "collapsed": false, "ExecuteTime": { - "end_time": "2023-10-18T19:25:17.261393437Z", - "start_time": "2023-10-18T19:25:17.230869947Z" + "end_time": "2023-10-18T21:23:49.596098616Z", + "start_time": "2023-10-18T21:23:49.595250278Z" } }, "id": "3d544d9681f2269a" diff --git a/hydradx/tests/test_arbitrage_agent.py b/hydradx/tests/test_arbitrage_agent.py index a5e63753..e05e1f62 100644 --- a/hydradx/tests/test_arbitrage_agent.py +++ b/hydradx/tests/test_arbitrage_agent.py @@ -150,7 +150,8 @@ def test_calculate_arb_amount_ask( initial_state.swap(agent, tkn_buy=numeraire, tkn_sell=tkn, sell_quantity=amt) test_price = initial_state.price(initial_state, tkn, numeraire) sell_spot = test_price * ((1 - lrna_fee) * (1 - asset_fee)) - cex_price = ask[0] / (1 - cex_fee) + # cex_price = ask[0] / (1 - cex_fee) + cex_price = ask[0] * (1 + cex_fee) if abs(sell_spot - cex_price) > p and amt != ask[1]: raise @@ -272,9 +273,9 @@ def test_get_arb_swaps( initial_agent = Agent(holdings={'USDT': 1000000000, 'DOT': 1000000000, 'HDX': 1000000000}, unique_id='bot') agent = initial_agent.copy() - execute_arb(op_state, agent, arb_swaps, cex_fee=cex_fee) + execute_arb(op_state, cex, agent, arb_swaps) profit = calculate_profit(initial_agent, agent) for tkn in profit: - if profit[tkn] < 0: + if profit[tkn] / initial_agent.holdings[tkn] < -1e-10: raise