Unicycles, Juggling, Fire.

The Unicycle Diaries Part 1: Uniswap, The Graph, and Me

By pierce | Titor Technologies | 5 Mar 2020


You've probably played with Uniswap by now. If you haven't you're in for a treat! Uniswap is an Ethereum based decentralized exchange (DEX) with a built in Automated Market Maker (AMM). This means it's an exchange with no order book where anyone in the world can instantly convert from one Ethereum based asset to another. If this is your first time hearing about Uniswap, definitely go give it a look: https://uniswap.exchange  We'll still be here when you've had your fill :-)

Liquidity Lending

The future is awesome. One thing I love about this future we live in is the sudden ease of participating in liquidity lending systems. Rather than just betting on the horse race that is crypto volatility, you can deposit your hard earned monies in Uniswap liquidity pools, enabling more efficient markets, and earning a cut of every transaction that happens on the exchange. This is because Uniswap allows for instant transactions, and that money can't come from nowhere. Liquidity providers essentially offer up equal portions of ETH and the paired token, so it's always available to anyone who needs some. This balance is also what directly leads to the exchange price on Uniswap. It doesn't use any external oracles to set price, it's entirely based on the see-saw of available tokens in the contract itself.

Free Money

So, how good it is to be a liquidity provider? Let's to some math. We can pull some really nice numbers from https://uniswap.info.

The first thing I'm going to do is sort by 24 hour volume. USDC seems to be experiencing some pretty good volume lately.

March 4th 2020

Okay, what does this mean? First off, liquidity providers have locked $2,793,207 worth of value in the USDC liquidity pool, and in the past 24 hours, $643,538 has moved through the USDC exchange. 0.3% of these transactions go to the liquidity providers, so 0.3% of $643,538 is ~$1931 distributed among the liquidity providers. This means that for every $1000 a liquidity provider has in the pool, they earned $0.69.  (1931/2793207*1000=0.69132..) This might not be a lot, but let's multiply it by 365 and we see it comes out to ~252.33, which means, all else being stable, %25 yearly gains. This is FANTASTIC. Generally, anything this low risk that nets higher returns than 10% yearly is something worth taking a look at.

Free Money?

So what's the catch here? First off, the coins you have in the liquidity pool are always 50/50 straddling the ETH and USDC prices. This is a nice place to be, but if you're in a Uniswap pool with a more volatile token, you're exposed to a sudden crash in the price of that token, or the ETH price. You also will only experience half of the gains if the ETH or token price suddenly shoot up. This is a fairly conservative play, especially if you're one of those people with long term faith in USD, and ETH is relatively stable compared to most of the other tokens in the space. There's not a great way to calculate future prices of assets, so we can choose to be willfully ignorant, and just ignore price volatility of the underlying assets, while just remembering in the back of your head that you've strapped yourself to a couple volatile assets. Actually, the more volatile an asset it, the higher the liquidity is going to be. This brings us to our second note.

The biggest assumption in this calculation is that this level of price volume will continue forever. Uniswap is largely populated by arbitrage bots, buying and selling to and from exchanges as needed to bring the price towards the generally agreed upon market value. This means that as long as the price is moving, there's going to be volume. I sorted by volume, so was definitely cherry-picking good numbers for the day. Is that a tragic flaw? Maybe, but many other exchanges seem to have these opportunities as well, and today doesn't seem like an especially high volume day. I suppose there are high volume days and low volume days. You'll definitely be making most of your liquidity fees on high volume days, but low volume days just mean less returns, your returns can never go negative (relative to the underlying assets).

Programming is Fun

So how do we see where the best opportunities are at? Let's throw down some code, but first we need to figure out what APIs we need to pull from. Unfortunately, for this, we need historical data, which is not exactly kept on-chain in an easy to access way. How does uniswap.info do it? Let's see. First I right click and say "inspect" to get to my chrome dev tools, then I flip to the network tab and hit refresh.

uniswap.info network traffic

Ah, that's interesting. I see it's pulling data from The Graph (https://thegraph.com/) who I mostly know from their prolific stickering of the various Ethereum hackathons that I've attended. I didn't have experience with it, so I poked around on their site a bit, then headed to youtube, and found this video:

This was neat. I see now there's a special "Playground" feature (https://thegraph.com/explorer/subgraph/graphprotocol/uniswap) where I can directly query the graph API from the browser. I noticed really quick that something was funny, as The Graph is using GraphQL for querying data, rather than the typical REST style APIs that I'm used to. I also had no experience with GraphQL, so after some quick googling and some YouTube watching tl;dr: It's a fun new alternative to REST APIs, where instead of having a ton of routes for every possible type of data you want, it exposes a single route that you can send complex queries to in the form of fun JSON style blobs.

How do I GraphQL with python? after quite a bit of Stackoverflowing, this is what I came up with:

unidump code

See the code at https://github.com/pierce403/unicycle.finance/blob/master/unidump-simple.py

Cool. This is just copying the GraphQL we see in the example Playground (https://thegraph.com/explorer/subgraph/graphprotocol/uniswap), so let's play around with it a bit to see if we can get it to do anything more interesting. In the Playground we can poke through the documentation, and hit ctrl+space for autocomplete suggestions, and then hit the big purple play button to run the query. Lets look at a slightly more interesting query.

{
exchanges(orderBy: tradeVolumeEth, orderDirection:desc, first: 10){
id
tokenAddress
tokenSymbol
tokenName
tradeVolumeEth
tradeVolumeUSD
combinedBalanceInEth
}
}

This lets us take a look at recent data from exchanges. We can print this information out in our python script by throwing in something like this: 

for exchange in json.loads(response.content)['data']['exchanges']:
print(exchange['combinedBalanceInEth']+" "+exchange['tradeVolumeEth']+" - "+exchange['tokenName'] )

There's an interesting problem here though. Notice that the tradeVolumeEth value is much higher than what we see on uniswap.info. Turns out that this is because the volume presented by the graph is the volume of the exchange since the dawn of time, which is not actually an extremely useful bit of information to present. I was hoping to get all the data I needed in one shot, but it looks like I'm going to need to take some round trips.

I need to get the exchange address of USDC. This will be in the id field in the data getting returned, so I added that to my pretty printed output, and see that the USDC uniswap exchange address is at 0x97dec872013f6b5fb443861090ad931542878126. Let's try to get some historical records with a exchangeHistoricalDatas query.

{
exchangeHistoricalDatas(where:{exchangeAddress: "0x97dec872013f6b5fb443861090ad931542878126"}, orderBy:tradeVolumeEth, orderDirection:desc, first:10)
{
id
timestamp
tradeVolumeEth
}
}

Plugging this sort of thing in, and playing around with it a bit, we notice a few interesting things, like how the snapshots coming from the Graph API seem to be taken pretty often, but not really at regular intervals. I like to do quick timestamp conversions at https://www.unixtimestamp.com/index.php. This sort of thing is important to keep in mind, since it means there will be a bit of inaccuracy baked in to any time estimates.

Actually, another interesting data source is exchangeDayDatas:

{
exchangeDayDatas(where:{exchangeAddress: "0x97dec872013f6b5fb443861090ad931542878126"}, orderBy:date, orderDirection:desc, first:10)
{
id
date
ethVolume
ethBalance
}
}

I like this one, because it's doing daily snapshots, which is probably ideal for the type of profitability data I'm trying to get. Lets plug it into some python code and see what we can do.

351665157-4dc2eb01f5c39bd34fff353e6bfcd61487472d86a341257419085d4b211f1f71.png

Code here: https://github.com/pierce403/unicycle.finance/blob/master/unidump-usdc.py

Hey, this looks nice. On the left if timestamps of the first seconds of the past 10 days, and the second column is the extrapolated yearly return (that day's returns multiplied by 365, expressed as a percentage. You can see that only one day in the past week had less than 10% returns on USDC. Seems like there are definitely some opportunities here. Let's get a broader look across the available exchanges.

Putting the two scripts together, we come up with this:

final unidump

https://github.com/pierce403/unicycle.finance/blob/master/unidump.py

Analysis

Hey, this looks really nice.. compound.finance has a lending rate of 8%, so that's the number to beat. Each token name is followed by a list of 14 profitability points, two weeks of data, expressed as extrapolated yearly returns so they can be compared with Compound's 8%. Note that the first entry is what is now called SAI, though the Graph API still returns its name as "Dai Stablecoin v1.0". This comes in first because it has the most volume historically, but these days is pretty week compared to some of its competition, for example the new DAI. Looks to me like there are many awesome opportunities here. Notice that DAI had a few really awesome days last week 67.23% and 62.98%.

You should probably just ignore that first number, it's especially low due to the incomplete day information for the current day. I ran this script just a few hours into the latest day GMT, so the volume is presented as unusually low. I'm surprised by the impressive liquidity opportunities on Kyber and Pinakion. There seems to be some pretty solid volume, and the liquidity pools are relatively small, so those definitely look pretty great.

All the code here can be found at https://github.com/pierce403/unicycle.finance/   Enjoy!

 

Up Next:  Beautiful Unicycle UX, hosting your DAPPs on Github

Hit the Bell! Subscribe and Save! See you next time!

How do you rate this article?


4

0


Titor Technologies
Titor Technologies

Productive Futurology, explorations in beautiful tech.

Send a $0.01 microtip in crypto to the author, and earn yourself as you read!

20% to author / 80% to me.
We pay the tips from our rewards pool.