Arbitrage and Winning a Cryptocurrency Trading Competition at MIT
There are numerous cryptocurrencies and crypto assets, and a variety of markets on which they are exchanged. Arbitrage opportunities arise among these various markets, and a corner of the Internet is financially capitalizing on these opportunities by programming algorithms that automatically execute trades.
MIT students recently had the opportunity to peer into this profitable world of crypto trading, and compete in our own small version of it.
MIT, where I am currently a graduate student, has a January term during which classes are offered that may not fit in to more traditional curriculums. One of those classes was a crypto trading workshop, sponsored by Celo and MIT’s Bitcoin club. The class included sessions with professionals who make their living from crypto trading, with lessons that covered the economics of trading and arbitrage opportunities of crypto markets.
At the same time, students competed in a month-long competition to trade Celo’s cryptocurrencies most profitably.
This post is an overview of what we learned about the markets and arbitrage strategies that make crypto trading profitable, as well as how I used those strategies to win the crypto trading competition to take home some cash.
I’ll share what we learned about
- Crypto markets and arbitrage
- How Celo uses a price stability protocol to control the volatility of its crypto assets and maintain a stable token (i.e. a cryptocurrency that is pegged to a fiat currency such as the US dollar)
- Implementing a winning algorithmic arbitrage strategy
Crypto markets and exchanges
Bitcoin (BTC), Litecoin (LTC), and Ethereum (ETH) are among the most well known cryptocurrencies, but there are more than 1600 other crypto assets. Many of the newer ones are ERC-20 tokens, which means they are implemented as “smart contracts” on the Ethereum blockchain.
Cryptocurrencies are exchanged both on and off their blockchains.
Most trading occurs on large centralized exchanges, such as Binance and Coinbase. These exchanges allow users to trade one cryptocurrency for another, as well as trade between crypto and fiat currencies (e.g. US dollars, Euros). They do this by matching the trade orders of their traders in a similar manner to how order books are used for traditional securities trading. Someone can place a trade order to buy token A for token B at a given exchange rate, and the exchange will match that order with someone else’s order to sell token A for token B at a compatible rate. With enough sellers and buyers, and an overall high volume of such trades, prices for tokens are established. The prices are the equilibrium points for where supply meets demand, as found in traditional economic models.
Like traditional financial markets, many of the large exchanges support limit and stop orders. They also provide APIs — application programming interfaces that make it possible to write code that trades on behalf of its programmer. While people can submit manual trades on these platforms, more advanced traders write algorithms in order to automatically submit trades as quickly as possible once profitable trading opportunities are found.
Centralized exchanges have been subject to notorious hacks. For example, Mt. Gox was a Bitcoin exchange based in Japan that lost an estimated $450 million in Bitcoin due to a hack in 2014. Most of the lost bitcoins were their customers’.
The reason that centralized exchanges are so attractive to hackers and a liability for their traders is that they store the funds that are involved in their transactions. They act as a central authority for the trades executed on their platforms by managing the funds, trades, and withdrawals of their users. Users must create accounts and deposit funds in these centralized exchanges, and all the ensuing trades occur within the exchange and off the blockchain. This may seem problematic and antithetical to decentralized blockchain philosophies, but it has also made centralized exchanges cheap, fast, and high volume places of trade. Despite the famous hacks, centralized exchanges are still the most widely used means of crypto exchange.
There are also decentralized exchanges (DEX), such as Etherdelta and IDEX. These are open source platforms with no central authority, where traders can exchange currencies on a peer-to-peer basis. They allow users to maintain control of their funds (and anonymity), which makes them more resistant to hacks. They are also more difficult to use, and so have lower trade volume than centralized exchanges, which has kept their fees higher. Most trades are still conducted on centralized exchanges.
Alternative Markets and Liquidity Systems
The x∗y=k model.
While most exchanges maintain order books and facilitate matches between buyers and sellers, these alternative systems use smart contracts to hold liquidity reserves of various tokens, and execute trades directly against these reserves.
A simple way to understand this liquidity supply is as pairs of token reserves. For example, a reserve of token A paired with a reserve of token B allows for the trade of token A for token B, as long as the trade obeys the model rule:
must be preserved, where x is the reserve’s total quantity of token A, y is the reserve’s total quantity of token B.
“The idea is that you have a contract that holds x coins of token A and y coins of token B, and always maintains the invariant that x∗y=k for some constant k. Anyone can buy or sell coins by essentially shifting the market maker’s position on the x∗y=k curve; if they shift the point to the right, then the amount by which they move it right is the amount of token A they have to put in, and the amount by which they shift the point down corresponds to how much of token B they get out.” — Vitalik Buterin, Ethereum Founder.
The token exchange price is then determined by the ratio x:y in the pair of token reserves. Naturally, the market drives this ratio towards a price that matches that of the other token exchanges. If the ratio did not match the exchange rate on other exchanges, then there would be a price differential between the exchanges, which would create an opportunity for traders to make a profit. This is where arbitrage comes in. Arbitrage, while it allows for opportunistic traders to make a profit, is also an important mechanism to keep the overall market in sync.
Note that the exchange rate for tokens in an “x∗y=k” model changes with each trade, because each trade alters the ratio of tokens. This creates a continuous “slippage” that can be mathematically determined prior to the trade.
The above description of an “x∗y=k” model is overly simplistic. You might be wondering how the liquidity is initially supplied and then managed.
The “x*y=k market maker” operates “on-chain”. The exchanges that operate by this model are decentralized, and trades are automated by smart contracts (e.g. see Uniswap’s smart contracts). Those who supply the initial liquidy for the token reserves can then reap yields. A small fee (0.3% for Uniswap) is taken out of each trade and added to the reserves, generating the yield for the liquidity providers, as well as increasing the overall quantity of reserves. Increasing the size of the reserves increases the stability of the exchange rate between tokens, because a larger trade is then required to alter the ratio between tokens.
I think the “x∗y=k” model provides a fascinating market making mechanism and a demonstration of the powerful decentralized system designs that can be realized with blockchain technologies. In the interest of space and saving those less nerdy than I from boredom, I’ll refer you to Uniswap’s paper for a more details and a formal definition.
With so many different exchanges, there end up being price discrepancies between them. The variations in prices across exchanges can be capitalized on.
For example, if token A and token B are exchanging at a rate of A / B = 1 / 2.2 on exchange X and at a rate of 1 / 2 on exchange Y, then a trader can make 0.2 (2.2–2) of profit in token B by purchasing 2.2 units of token B for 1 unit of token A on exchange X at the 1 / 2.2 rate and then immediately selling 2 units on exchange Y at the 1 / 2 rate to get back their 1 unit of token A. They get to keep their unspent 0.2 units of token B.
Trader has: 1 token A, 0 token B
Trader exchanges 1 token A for 2.2 token B on exchange X:
1 token A → 2.2 token B
Trader has: 0 token A, 2.2 token B
Trader exchanges 2 token B for 1 token A on exchange Y:
2 token B → 1 token A
Trader has: 1 token A, 0.2 token B
This conceptually simple form of arbitrage can be summarized as “buy low, sell high”, and is known as 2-leg arbitrage. The first leg in our example is the transaction on exchange X and the second leg is the transaction on exchange Y.
Arbitrage is a set of transactions that involve no negative cash flow, and only positive cashflow. An arbitrage cycle, such as the example 2-leg cycle, is a series of trades that generates a “riskless” profit.
In practice, 2-leg arbitrage and other trading strategies that require moving assets between exchanges are risky and not well suited for cryptocurrency markets. Moving assets between exchanges means withdrawing funds from one exchange, making a transaction on the blockchain, and then depositing the funds in another exchange to complete the next transaction. Each of these steps incurs fees and are time intensive. In the time it takes for a transaction to complete on the blockchain, a profitable opportunity can disappear. Executing a series of transactions within a single centralized exchange is much faster, and arbitrage opportunities can still be found within a single exchange.
Similar to 2-leg arbitrage cycles, traders can find arbitrage cycles with more legs. For example, an arbitrage cycle with 3 legs, known as “triangular arbitrage”, occurs when exchanging three assets, say tokens A, B, C, in a cycle: token A for token B, then token B for token C, and then token C for token A,
A:B → B:C → C:A
results in a net gain.
These opportunities can arise within a single exchange due to market inefficiencies. However, these opportunities are quickly closed by those who exploit them. Finding and exploiting arbitrage cycles is a race, where the traders with the fastest trading algorithms win.
There is another arbitrage strategy that a professional trader discussed in our class. It is like a simplified version of what some might call “statistical arbitrage”. It involves maintaining positions in two (centralized) crypto exchanges at once. Opportunities are then found where a given asset has different prices across the two exchanges in order to take a short position where the asset is more expensive, and a long position where the asset is cheaper.
For example, consider a scenario with exchange X and exchange Y, where token A is trading at a lower price on exchange X and a higher price on exchange Y. A trader who maintains accounts in both exchange X and exchange Y then buys token A on exchange X for the lower price (taking a long position) and simultaneously sells token A on exchange Y for the higher price (taking a short position).
Every so often, the trader withdraws or deposit funds on the two exchanges in order to rebalance the values in the accounts or extract their profits.
2 centralized exchanges: exchange X, exchange Y
Trader has an account in exchange X, and an account in exchange Y
When the exchange rate A / B is lower on exchange X than exchange Y, then the trader:
buys token A for token B on exchange X & sells token A for token B on exchange Y
When the exchange rate A / B is higher on exchange X than exchange Y, then the trader:
sells token A for token B on exchange X & buys token A for token B on exchange Y
When the quantities of token A and B are significantly imbalanced between the accounts on exchanges X and Y, the trader rebalances these quantities by making withdrawals and deposits.
There are many more arbitrage strategies, such as those that capitalize on price differentials over time. However, the professional crypto traders that joined Celo’s workshop had found their financial successes through the arbitrage strategies presented above. These same strategies were useful in Celo’s crypto trading competition that I and the other workshop participants competed in.
Celo’s Tokens and Stability Protocol
Volatility is a well known problem for popular cryptocurrencies. A currency with highly volatile price fluctuations is not as useful in the exchange of goods and services as a currency that has a trusted and understood value. In order for the public to benefit from cryptocurrencies as actual currency rather than just financial assets to trade and profit from, cryptocurrencies need a value that the public can trust to remain stable.
“Stablecoins” or “stable tokens” are commonly presented as a solution to this problem. Stable tokens are pegged to a fiat currency (e.g. the US dollar) so that their value can match that currency with limited fluctuations. The implementations of stable tokens vary, and often involve backing tokens with collateral.
Celo has two crypto assets and uses them in a clever protocol in order to algorithmically address the price stability problem:
The Celo Dollar token (cUSD) is a stable token that is pegged to the US dollar (USD). It has an elastic supply.
The Celo Gold token (cGLD) has a fixed supply, but its value is allowed to vary.
Celo Gold is used to help control the circulation of the Celo Dollar and keep its value pegged to the value of USD. Celo’s protocol does this by automatically adjusting the supply of Celo Dollars by buying or selling Celo Dollars (cUSD) for Celo Gold (cGLD).
Let’s briefly revisit Economics 101 with the Celo Dollar as the commodity of interest:
When there is more demand than supply for the Celo Dollar, its price is pushed up above $1. On the other hand, when the supply exceeds the demand then the price is pushed below $1.
By expanding or contracting the quantity of Celo Dollars (cUSD) in the open market, Celo brings the supply and demand to the desired $1 equilibrium.
When the price of Celo Dollars is greater than $1, the protocol expands the supply of Celo Dollars until the market price for the Celo Dollar is $1. These expansions are handled by a smart contract that creates new Celo Dollars and sells them on the open market in exchange for Celo Gold and other crypto assets that it puts in Celo’s reserve.
When the market price of Celo Dollars is less than $1, the protocol contracts the supply of Celo Dollars until the market price reaches $1. To contract the Celo Dollar supply, the protocol purchases Celo Dollars from the open market with Celo Gold and other assets in the reserve, and then “burns” the Celo Dollars.
The Celo protocol uses decentralized auctions to perform these expansions and contractions in the open market. The auctions are capped, multi-unit, first-price sealed-bid (also known as “blind auctions”).
Sealed bids — Bids submitted by traders are hidden until the auction bidding stage is complete. Since traders cannot see each others submissions for in-progress auctions, they must instead use past auction bid prices to determine their optimal next bid. (Another blogpost could be written about how the wonders of cryptography allow for the design of sealed-bid auction protocols).
Multi-unit — Traders can bid on any fraction of the total pool of assets being auctioned off. Different portions of the pool can sell for different prices, and traders can even submit multiple bids at different price points. For example, if 2 cUSD is being auctioned off, 1.5 units of cUSD may go to a bidder who bids at a 1 cUSD / 3 cGLD exchange rate, while the remaining 0.5 units goes to a bidder who bid at a 1 cUSD / 2 cGLD exchange rate.
Capped — Each auction has a limit (“cap”) to the amount of Celo Dollars that will be bought or sold. Submitted bids are ordered by price, from highest to lowest, and the auction then fills those bids in order until the cap is reached.
For example, in an expansion with a cap of 100 cUSD (i.e. the auction is selling a total of 100 cUSD for cGLD to the highest bidders), the following bids might be placed:
(a) 50 cGLD for 50 cUSD (1 / 1 rate)
(b) 50 cGLD for 100 cUSD (1 / 2 rate)
(c) 90 cGLD for 80 cUSD (9 / 8 rate).
These bids are ordered by the highest cGLD / cUSD rates to the lowest, and filled until the 100 cUSD cap is reached:
(a) 90 cGLD for 80 cUSD (9 / 8 rate)
(c: partial) 20 cGLD for 20 cUSD (1 / 1 rate) — 100 cUSD cap reached
(c: remainder) 30 cGLD for 30 cUSD (1 / 1 rate)
(b) 50 cGLD for 100 cUSD (1 / 2 rate)
Understanding Celo’s auctions and how to “outbid” other traders without bidding at too high a price point was a key part of implementing a successful arbitrage strategy in Celo’s trading competition.
Competition and Arbitrage Algorithms
The crypto trading competition that Celo ran throughout the month-long class made use of our lessons about crypto markets and arbitrage strategies. It operated on a fork of the Ethereum network and only involved trading Celo Dollars (cUSD) and Celo Gold (cGLD).
Each competitor was given a wallet initially filled with:
The winner of the competition would be the one with the most value in their wallet at the end of the month. The prize was payment of the wallet’s value in US Dollars, plus a $1000 added bonus for the winner. (Celo also awarded bug bounties).
The competition involved 2 markets to trade in:
A Celo auction ran once an hour, on the hour. Traders could bid to either buy or sell cUSD for cGLD, depending on whether the auction was performing a market expansion or contraction. Because the auction was capped, not all bids could be filled, so traders bid in direct competition with one another. Bids that were too low were not filled. There was a small cost to bidding, as a small transaction fee (“gas”) was always extracted by the Ethereum network.
There was also an exchange that operated by the x∗y=k model. The exchange held reserves of Celo Dollars (cUSD) and Celo Gold (cGLD) and could be used at any time to trade between the two assets. The exchange rate between cUSD and cGLD was simply the ratio of the quantities of these two assets in the exchange reserves. This exchange rate established the understood value of cGLD relative to cUSD at any given time.
The total value of any heterogeneous quantity of cUSD and cGLD could be computed by using the exchange rate to value the cGLD in terms of cUSD, and then evaluating the resulting total cUSD value in dollars, since the value of cUSD is pegged to $1.
For example, if my wallet contained 100 cUSD, 200 cGLD, and the exchange rate for cUSD / cGLD = 1 / 2, then my wallet had a value of:
Total cUSD = (100 cUSD) + (200 cGLD * (1 cUSD / 2 cGLD))
= 100 cUSD + 100 cUSD = 200 cUSD
With these game mechanics in place, students began trading.
The occurrence of hourly auctions and the constant presence of the exchange created arbitrage opportunities that successful trading strategies could profit from.
Trades could be manually executed (via a CLI — command line interface), or trades could be executed by programmed algorithms (Celo provided an SDK to interface with the CLI: https://github.com/celo-org/celo-IAP).
Once an algorithm is programmed and tested, it can be left running on a server. It can then take advantage of each auction and arbitrage opportunity around the clock, which would not be feasible through manual trades. The programmer can then choose to occasionally check on the progress of the program and adjust the algorithm if necessary.
I programmed an algorithm that ran around the clock by using Celo’s SDK and hacking on some of their sample code. By the end of the competition it had net a profit of about $500 after starting off with about $50 of crypto.
The algorithm’s approach to profit was simple, like 2-leg arbitrage: “buy low, sell high”. If tokens can be bought in an auction and then sold on the exchange for a higher rate, then profit can be made. The implementation involved the following ideas and variables:
Minimum bid discount
Balance — Remember how at any given time, the cUSD / cGLD exchange rate is determined by the ratio of these two tokens in the exchange operating by thex∗y=k model. The value of cGLD in my wallet can then be calculated in terms of cUSD by simply multiplying its quantity by the exchange rate. However, this value is subject to change with the exchange rate, and the exchange rate moves with each trade, since each trade alters the ratio of tokens in the reserves of the x∗y=k model. This makes the total value of my wallet precarious. To minimize risk, I kept the value of cUSD and cGLD in my wallet “balanced”. I kept a target balance of 50 / 50 such that about 50% of the total value in the wallet was in cUSD, the other 50% cGLD.
After each auction closed, the algorithm checked the cUSD / cGLD exchange rate, and recalculated the value ratios of cUSD / cGLD in my wallet. If the ratio had deviated from the 50 / 50 target by a given threshold (10%), then I traded with the exchange so that the target balance was restored.
Bid discount — profit could be made from the auctions by placing bids at a “discount” to the exchange rate, and then trading the auctioned tokens at the exchange for the exchange rate (less slippage). For example, suppose the cUSD / cGLD exchange rate was 1 / 2, and the action was an expansion, auctioning off cUSD for cGLD. With a bid discount of 1.1, I would bid for cUSD in the auction at a 1.1 / 2 rate for cUSD / cGLD. If my bids were successful, I could then trade the cUSD I had won back on the exchange for the 1 / 2 rate, gaining a profit of 0.1 cUSD for 1 cUSD unit traded.
The higher the bid-discount, the higher the profit margin. However, too high a bid-discount jeopardized making any profit at all, because other traders would outbid. Getting outbid was a loss: There was the opportunity cost of not successfully participating in the hourly auction, as well as the transaction fees consumed by the network for transacting with the auction.
The bid-discount was a variable that adjusted algorithmically. The algorithm attempted to optimize the bid-discount in order to make it as high as possible, while still low enough to successfully win bids.
Bid adjustment — The bid-discount was incremented or decremented by a fixed amount bid-adjustment in order to maintain an optimal value.
Minimum bid discount — The bid-discount was never allowed to fall below a minimum value (e.g. ~1.01) even if this meant being outbid. Bidding in the auction was not profitable below this value.
Success streak — A numeric variable kept track of when bids were successful, and when they were not (outbid). At the end of each auction, if the bid had been successful, the success-streak was incremented by 1. Otherwise, it was reset to 0.
Now, for a simple algorithm that used these variables (in pseudocode). Note that
exchange rate could be in terms of cGLD or cUSD, depending on which is being auctioned off.
For each auction: Get the exchange rate To get the “discounted” exchange rate:
Multiply the exchange rate by the bid-discount Bid to buy as much as possible
Calculate the buy-amount as the maximum of the auction cap or how much of that currency is available in wallet Calculate sell-amount using the buy-amount and discounted exchange rate Submit a bid to buy the buy-amount for the sell-amount Wait for the auction to end…
At the end of the auction… If the bid was unsuccessful, then: Reset success-streak: success-streak = 0 Reduce the bid-discount, but keep it above the minimum
If bid-discount - bid-adjustment > minimum bid discount: Decrement the bid-discount by the bid-adjustment
bid-discount = bid-discount - bid-adjustment
The reduced bid-discount will be used in next auction
Otherwise the bid was successful, so: Increment success-streak: success-streak = success-streak + 1 When on a success streak, increment bid-discount
If success-streak > 5:
bid-discount = bid-discount + bid-adjustment
This increased bid-discount will be used in next auction Rebalance the values of cGLD and cUSD in the wallet if necessary
Repeat for each auction!
This algorithm was simple, but it was enough to be successful. More importantly, thinking about arbitrage strategies for Celo’s competition was an interesting way to learn about crypto markets. Thank you, Celo, for the workshop resources and lessons.
To answer your next question: No I am not planning to invest my winnings back into crypto markets and continue writing arbitrage algorithms. Crypto trading was a fun means through which to learn more about digital currencies and blockchains, and learning is what I will continue to invest my time in.