Cryptocurrency has always been something that is interesting to me, and after discussing the concept of arbitrage with some friends, I decided to try to write a crypto bot to do this automatically.
I decided to build on the Avalanche blockchain, as that network had the lowest monetary barrier of entry at the time.
The idea was to constantly scan various liquidity pools on the network, and compare the exchange rates of different tokens. The bot would then detect if an opportunity existed to stabilize a large enough price discrepancy across multiple pools to generate a guaranteed profit.
The formula to calculate whether or not an opportunity exists and how much value to trade in response is non-trivial, and I could not find it anywhere, so I ended up creating it myself.
A successful transaction of this bot can be seen here, and more successful transactions can be seen by following that wallet address.
Unfortunately, I eventually discovered that arbitrage on the Avalanche ecosystem has a much higher barrier of entry than anticipated.
There are extremely powerful mining pools that have the capability of reordering transactions within a single block, and these pools collude with high profile arbitrage bots to ensure that their transactions are prioritized whenever possible.
What this means is that even though it is possible to create successful arbitrage transactions, if you are not colluding with these mining pools, your transactions will statistically be beaten enough of the time that you will not be profitable in the long run due to accumulating transaction fees when losing to other bots.
A short write up of calculating the formula can be seen below:
- The number after each variable represents which pool it belongs to in the sequence.
- The prime (') after a variable denotes that it is the version after the liquidity has been altered by the trade.
- a represents input liquidity.
- b represents output liquidity.
- c represents the commission multiplier. (i.e. 0.997 for a 0.3% fee)
- x represents the amount of tokens added to the input liquidity.
- p represents the exchange rate between x0 and the tokens received at the end.
- x0 is unknown and needs to be solved for.
a0' = a0 + x0
b0' = a0 * b0 / (a0 + c0 * x0)
x1 = b0 - b0'
a1' = a1 + x1
b1' = a1 * b1 / (a1 + c1 * x1)
tokensReceived = b1 - b1'
profit = tokensReceived - x0
profit = b1 - (a1 * b1 / (a1 + c1 * x1)) - x0
profit = b1 - (a1 * b1 / (a1 + c1 * (b0 - (a0 * b0 / (a0 + c0 * x0))))) - x0
- To maximize profit, find its derivative:
d(profit)/dx = ((a0 * a1 * b0 * b1 * c0 * c1) / (a0 * a1 + c0 * x0 * (a1 + b0 * c1))^2) - 1
- The derivative can then be set equal to zero and x0 can be solved for:
((a0 * a1 * b0 * b1 * c0 * c1) / (a0 * a1 + c0 * x0 * (a1 + b0 * c1))^2) - 1 = 0
((a0 * a1 * b0 * b1 * c0 * c1) / (a0 * a1 + c0 * x0 * (a1 + b0 * c1))^2) = 1
x0 = (-a0 * a1^2 * c0 - sqrt(a0 * a1^3 * b0 * b1 * c0^3 * c1 + 2 * a0 * a1^2 * b0^2 * b1 * c0^3 * c1^2 + a0 * a1 * b0^3 * b1 * c0^3 * c1^3) - a0 * a1 * b0 * c0 * c1) / (a1^2 * c0^2 + 2 * a1 * b0 * c0^2 * c1 + b0^2 * c0^2 * c1^2)