Info on developing arbitrage
The strategy constantly scans for any arbitrage opportunity by comparing the order books on two markets that are trading equivalent assets (e.g., WETH-USDC vs. ETH-USD). Whenever it finds any price dislocation between the two markets (i.e. it's profitable to buy from one and sell to the other), it would calculate the optimal order size to make the arbitrage trade, and trade away the price difference by sending opposing market orders to both markets.
Here's a high-level view of the logic flow inside the built-in arbitrage strategy.
There are a few significant parts to the arbitrage strategy in terms of its logic flow:
- Sanity checks before scanning for arbitrage opportunities
- Scanning for profitable arbitrage trades
- Calculating the optimal arbitrage size
- Executing the arbitrage orders
Before the strategy looks at the two markets for profitable trades, it needs to check whether it is safe to do any trades first.
There are a few conditions that the strategy would check for at every tick before proceeding to look at the market order books:
Are both markets connected and ready?
If any of the left or right markets is not ready or is disconnected, then no arbitrage trade is possible.
Are there pending market orders on the markets that are still being processed?
If there are outstanding market orders still being processed in the markets, no other arbitrage trade is possible.
Has there been a recent arbitrage trade within the cooldown period?
If an arbitrage trade has happened recently, within the cooldown period (the
next_trade_delay_intervalinit argument in arbitrage.pyx), then no arbitrage is possible for this tick. This wait is needed because asset balances on markets often need some delay before they are updated, after the last trade.
After the sanity checks have passed, the strategy would look at the top of the two markets' order books to see if any profitable arbitrage is possible. This is only possible if one of the following happens:
- The price of the bid order book on the left market is higher than the price of the ask order book on the right market; or
- The price of the bid order book on the right market is higher than the price of the ask order book on the left market.
In either case, the arbitrage strategy would sell into the higher bid book and buy from the lower ask book. If none of the above is true at the current tick, then the arbitrage strategy would wait for the next tick and repeat the same process.
The profitable arbitrage check logic can be found in the function
c_calculate_arbitrage_top_order_profitability() inside arbitrage.pyx.
After an arbitrage opportunity is found, the next step calculates the optimal order size for the arbitrage trade.
Arbitrage opportunities are always limited in size - as you buy higher and higher into the ask book and sell lower and lower into the bid book, the amount of profit decreases for every increment of order size. Eventually, the price you buy and sell into the two books would become the same, and you would no longer make more money by increasing the order size further. So the arbitrage strategy would calculate the maximum order size you can make by examining the order books on the two markets.
Another thing the arbitrage strategy takes into account is the transaction fee of the markets. For example, some markets have a fixed or semi-fixed fee for every trade, s.t. you'd need a certain minimum order size for the arbitrage before it would make any profit. So the arbitrage strategy would try to take that into account and calculate the correct order size that produces the most profits.
Finally, the arbitrage strategy will look at the balance of assets available for trading in both the left and right markets - the arbitrage order size cannot exceed the number of assets that can be traded.
The optimal arbitrage size calculation logic can be found in the functions
c_find_profitable_arbitrage_orders() inside arbitrage.pyx.
If the calculated arbitrage size is greater than 0, the arbitrage strategy would simultaneously send both the market buy and market sell orders to the two markets. However, arbitrage opportunities are usually rare and quickly exploited by traders, so it is important to send both orders out without any wait.
The order execution logic can be found in the function
c_process_market_pair_inner() inside arbitrage.pyx.