Skip to content
This repository has been archived by the owner on Oct 30, 2024. It is now read-only.

πŸ‘Ύ my cli tool to get data and arbitrage edges for given tokens and exchanges pools

Notifications You must be signed in to change notification settings

autistic-symposium/amm-arbitrage-tool-py

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

33 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸͺ™βœ¨ bdex


A package and CLI tool to get data and arbitrage for specified tokens/exchange pools.


Token pairs:

  • WETH/DAI

Exchanges:




Setting your environment

Add your Alchemy API key and endpoint to a file named .env:

cp .env_example .env
vim .env

Create a virtual environment:

virtualenv venv
source venv/bin/activate

Install dependencies:

make install_deps

Install the CLI:

make install



Running the CLI

You can run the CLI with:

bdex

Screen Shot 2022-04-04 at 1 35 46 AM


Checking the latest block

We leverage Alchemy API endpoint eth_blockNumber_hex to get the latest block:

bdex -c

Screen Shot 2022-03-31 at 1 15 25 PM



πŸ’‘ The block number can be checked against ETHstat.


Screen Shot 2022-03-31 at 1 15 19 PM


πŸ’‘ We are crafting the checksum address string by hand without directly Keccak-256 hashing the methods and parameters.


Getting the token balance for an exchange

We leverage Alchemy API endpoint eth_call to retrieve the current token balance for a specific exchange:

bdex -b TOKEN EXCHANGE

Screen Shot 2022-03-31 at 10 26 21 PM


Getting all token balances for all the exchanges

We loop over the previous method for a list of tokens and exchanges:

bdex -a

Screen Shot 2022-03-31 at 10 26 51 PM


[Extra] Getting all token balances for all exchanges with Python's web3 library

To be able to compare our results from the previous steps, we implemented an alternative way to fetch pair balances utilizing the Python web3 library:

bdex -w

Screen Shot 2022-03-31 at 10 27 25 PM



πŸ’‘ For this library, it's necessary to supply the contracts' ABI (in our case, for DAI and WETH, located at ./docs)

πŸ’‘ A third option to verify token balances is through Etherscan tokenholdings dashboard.


Getting trading prices for all the exchanges

To get the current price for WETH/DAI in all exchanges (e.g., as shown in the projects' dashboards), run:

bdex -p QUANTITY TOKEN1 TOKEN2

Quote for trading 1 WETH:


Screen Shot 2022-04-03 at 8 27 55 PM


Quote for trading 10 WETH:


Screen Shot 2022-04-03 at 8 28 20 PM


Quote for trading 100 WETH:


Screen Shot 2022-04-03 at 8 28 46 PM


How the price is calculated

An AMM replaces the buy and sell orders in an order book market with a liquidity pool of two assets, both valued relative to each other. As one asset is traded for the other, the relative prices of the two assets shift, and the new market rate for both is determined.

The constant product is:

token_a_pool_size * token_b_pool_size = constant_product

All the exchanges are forks from UniswapV2, so they all use the same price formula for trading:

market_price_token1 = token2_balance / token1_balance

For example, in a pool with 2,000,000 DAI and 1,000 WETH, the constant product is 2,000,000,000 and the market price for WETH is $2,000.


Buy price (e.g., buying WETH in a WETH/DAI pool)

To find the buy price for a certain quantity, first, we calculate how much WETH needs to remain in balance to keep the constant product unchanged:

token1_balance_buy = constant_product / (token2_balance + quantity)

Then we calculate how much WETH goes out to keep this constant:

 t1_amount_out_buy = token1_balance - token1_balance_buy

The buy price to reflect this ratio is:

buy_price = quantity / t1_amount_out_buy

Sell price (e.g., selling WETH in a WETH/DAI pool)

To find how much we can sell a certain quantity of WETH for DAI, first, we calculate the ratio of DAI in the new pool, as we add WETH:

token2_balance_buy = constant_product / (token1_balance + quantity)

We then calculate how much DAI will go out:

t2_amount_out_buy = token2_balance + token2_balance_buy

We calculate the DAI balance reflected with the income WETH:

token1_balance_sell = constant_product / (token2_balance - quantity)

And what's the proportion of WETH in the new balance:

t1_amount_in_sell = token1_balance + token1_balance_sell

We can now calculate the sell price to reflect the balance change, keeping the constant:

sell_price = t2_amount_out_buy / t1_amount_in_sell

Getting arbitrage

Run an algorithm to search for arbitrage in the supported exchanges for a certain buy quantity:

bdex -x QUANTITY

Arbitrage opportunies for 10 WETH:


Screen Shot 2022-04-04 at 6 02 09 PM


Arbitrage opportunies for 1 WETH:


Screen Shot 2022-04-04 at 6 02 31 PM


Arbitrage opportunies for 0.01 WETH:


Screen Shot 2022-04-04 at 6 03 20 PM




Running arbitrage algorithm in a loop

To run the arbitrage algorithm for a certain amount of minutes:

bdex -r MIN

Screen Shot 2022-04-04 at 1 05 07 PM



Results are saved into results/<arbitrage_TIMESTAMP>.txt.


Here is a sample of the results running this algorithm for 100 minutes for trading 1 WETH:

{'buy_exchange': 'SUSHISWAP', 'sell_exchange': 'UNISWAP', 'arbitrage': '7.01', 'buy_price': 3475.14, 'sell_price': 3482.15}
{'buy_exchange': 'SUSHISWAP', 'sell_exchange': 'SHEBASWAP', 'arbitrage': '4.27', 'buy_price': 3475.14, 'sell_price': 3479.41}
{'buy_exchange': 'SHEBASWAP', 'sell_exchange': 'UNISWAP', 'arbitrage': '2.06', 'buy_price': 3480.09, 'sell_price': 3482.15}
{'buy_exchange': 'CROSWAP', 'sell_exchange': 'UNISWAP', 'arbitrage': '13.06', 'buy_price': 3469.09, 'sell_price': 3482.15}
{'buy_exchange': 'CROSWAP', 'sell_exchange': 'SUSHISWAP', 'arbitrage': '5.79', 'buy_price': 3469.09, 'sell_price': 3474.88}
{'buy_exchange': 'CROSWAP', 'sell_exchange': 'SHEBASWAP', 'arbitrage': '10.32', 'buy_price': 3469.09, 'sell_price': 3479.41}
...

Running arbitrage algorithm in a loop in a Docker container

To run the algorithm in a separated container, first install Docker, then build the Docker image:

docker build -t bdex .

Finally, run the container (in a separate terminal tab):

docker run -v $(pwd):/results -it bdex sleep infinity

Results are available at results/<arbitrage_TIMESTAMP>.txt.

πŸ’‘ You can inspect your container at any time with these commands:

docker ps
docker exec -it <container_id> /bin/bash
docker inspect bdex

Cleaning up:

docker volumes prune



Development

Install dependencies:

pip3 -r requirements-dev.txt

Linting

make lint

Running tests

make test