As we mentioned in our last post:
here we talk about the funding arbitrage, and some considerations, and my current tacky setup. The code is written to the main branch, and uses the quantpylib throttler library, for data polling and throttling of the REST endpoints.
https://github.com/hangukquant/quantpylib/tree/main/dev
If you are a free reader, actually, the same (but less awesome) dashboard is here:
https://app.hyperliquid.xyz/fundingComparison
and everything I talk about in this article still applies, so read on.
If you a paid reader, but have no access to our code repo, you can comment your Github ID in this post.
Now everything here should not be taken for word, since I am new to the space. I may say something outright wrong - and I would actually be sincerely grateful if you pointed it out in the comments.
Funding Arbitrage
Well, we all know what spot is, and what a future is (I hope). And then there is a perpetual future/swap, which honestly confused me. I mean those things have existed before crypto, but I have never paid attention to it, what the heck does it mean for a futures contract to be perpetual? I think the closest cousin to a perpetual future is perhaps a CFD, where it is intended to track the underlying.
So let’s just call this magic thing a perp. Why would it track the underlying? Okay actually, it doesn’t track the underlying to be precise, since there is no one true-price…but let’s just assume it tracks this figure, known as the mark price (mark-to-market), which turns out to be a combination of the perp price, oracle price (some index of multiple exchanges) and what not. The specific mechanism is exchange specific.
Well there is no reason to, except, there is an incentive factor known as the funding rate. Basically, whatever mark it is trying to track, when the perp lies above it, there is incentive to short via a positive funding rate, and when it is below, there is incentive to long the perp via negative funding rate. The specific funding computations and payout is also exchange-specific.
Positive funding rates mean longs pay shorts, in case the above paragraph was not clear. Then crypto has this thing called centralized exchanges (CEX) and decentralised exchanges (DEX) - whatever, I will not bore you with the details, you probably already know, or can figure it out.
Funding Rate arbitrage comes from mainly SPOT/PERP or PERP/PERP cross exchange arbitrage, where you long the coin in one exchange and short in the other, where they feature distinct funding rates, for some demand-supply dynamics that vary - for whatever reason.
Actually, let me defer to my friend
‘s article on the dependence of the funding arbitrage trade on regime factors, borrow concerns, shock risk, margin transfer and what not. I am more interested in demonstrating my crappy dashboard.To begin with, let’s assume a PERP/PERP arbitrage, so both will have associated funding rates. Clearly you want to LONG/SHORT the cross-exchange with LOW/HIGH funding rate, so that you are paid more on your short than you pay on the long, so that you can collect funding payments. You only want to hold this position until it converges, or flips. But since the instantaneous funding rate is very, very noisy, you want to have a more persistent figure.
Right of the bat, you want to take a look at historical data to look at the mean convergence time of this funding spread. From my first-order guess, I just assume that the price basis is also a function of the funding spread, although there are some fudge factors. Either way, when you enter into the trade, you want out when the funding spread has closed, because then you will not be receiving further swap payments. Additionally, your price basis will have converged, so there is a nice price arbitrage there too, although not our primary source of return.
Since trading is costly, you want this funding spread to be persistent, which means you probably should smooth out some figures to the instantaneous spread to get an adjusted funding spread in terms of say, an exponentially smoothed average. This means you get to hold on to the position for longer, which means you get paid more without having to incur transaction costs.
Quantarb’s talk about the entry and exit rules, using bollinger bands and what not. Here’s a quote from the article:
‘‘‘
…have decided that the spread is converging soon / past the point of attractiveness, so as to make it no longer worth holding, we may set a threshold, which is a combination of current price and convergence.
‘‘‘
A reasonable approach would be to take the Bollinger band of the price basis, which we can take as a proxy for both the price and funding arbitrage as exit rule. One thing you might want to do is adjust the prices involved in the band computation - since the different exchanges have different funding rates/intervals, the funding premium accrued is baked into the basis, and is only an apple-apple comparison if their funding time intersects. For instance, on HPL each coin pays funding hourly, while the Binance ones pay 4/8 hours - we want to adjust their prices and compute the bands against their market prices less premium accrued, otherwise there will be jumps > false signals. This is akin to a dividend payment for a common stock.
Dashboard + My Trade
Let’s talk about the dashboard, and my first iteration of this funding arb trade. First thing we wanna do is get data, and let’s first define some columns we might find important in coin-selection:
We have 1h/8h/D/Y funding intervals, exponentially smoothed data, funding rate interval, funding premium accrued, open interest , so on and so forth. We want to poll their data.
We have current half-ass support for Binance and Hyperliquid, which shows for each coin, the best exchange to go long/short in.
Since we do not have automated execution, we can at most do bilateral exchange arbitrage. We pick two exchanges (well we only have two now), and we can sort the ema_diff column, showing annualized FR spread (all the nan-values, we did not manage to yet implement the endpoint on binance). We construct new L/S pairs for each perp.
The exchange column shows whether it is L/S HYP/BIN or L/S BIN/HYP. We can treat this pair as a new contract, which means we want to go long the most negative FR pair, so we get paid funding. Our alpha source is the ema_diff:
The ema_diff is those for which determines the persistence of our funding spread, while the fr_diff is the instantaneous (with lags due to REST API limits) spread. However, remember, our setup is fairly garbage, and execution risk is big. We want both strong negative ema and instantaneous spread, since the latter is also a proxy for the price basis, which determines our ease of execution.
(I’ll explain why):
But first, we can see that ONDO is fairly negative in both columns (we don’t care about the other columns, we are not trying to be precise in this shit setup), so we can select the pair in the panel and plot some historical spreads:
As the screenshot suggests, the exchange column says we should go long binance short hyperliquid. Here is a screenshot of the order-book, as I am writing of the moment (LEFT, RIGHT) = (BINANCE, HYPERLIQUID):
The top of the order book is
0.7556 B A 0.7557 (Binance)
0.75652 B A 0.75673 (Hyp)
Assuming we get screwed the pooch and do a market order (small enough), we get filled at Ask-Binance (0.7557, 0.75652) Bid-Hyperliquid. We still managed to sell at a higher price than we bought at, and we have a zero-delta position with positive funding.
Okay now both the spreads in their respective order books are fairly tight, we let’s take a look at the transaction costs.
Assume that the maker-taker fees on hyperliquid are 0.0200%/0.0500%, while binance maker-taker fees are 0.0100%/0.0350%. It is actually exactly, the opposite, but hey, I said assume so.
First and foremost, this is manual arbitrage, so you don’t want to be left with a directional position. To do this, we are going to make a limit order on one-side, and then execute the opposite position as market order immediately upon limit-order-fill. To see where we want to issue our limit, if we make-take on binance-hyperliquid, we pay (0.01+0.05=0.06%), as opposed to if we make-take on hyperliquid-binance (0.02+0.035=0.055%).
Our breakeven profit for entry is 0.055% * 0.75696 = 0.000416328, which means if we get a better price by 0.0004-ish, we have entered into our positive-funding-zero-delta position for free or reward.
So that also settles where we want to make our order. To be a maker, our order has to sit on the order book in hyperliquid. But how do we size it?
We have to be a taker on binance, and we can just submit a market-order, but at the same time we don’t want to run through their entire order book. We can watch the volumes at the top of their order book for awhile…we see that the market can comfortably absorb about an order size = 1000, and our market order will just take the best offer without going too deep into the order book.
So we make a sell limit for 1000 ONDO on hyperliquid, and let it sit in the order books: the white dot represents our order ( I am executing the trade live as I write):
and I watch it like a hawk, while hovering my hand over the 1000 long market order on binance. The moment hyperliquid fills, I make my market order.
(Hyperliquid short):
(Binance long):
We actually got 0.00096 dollars per ONDO, for 96 cents in profit. The fees from both sides of the trade is 42 cents. We earned roughly 50 cents getting into the position, and will continue to get paid until the funding rate flips.
Of course, we now have to build up our position, repeating this same procedure and building our volumes depending on what the order book gives us. This is kind of painful, and obviously, preferably automated. Also, if you need to get things on in size, you would repeat the same price and order-book analysis, except perhaps with a VWAP price on the taker side instead as to whether you should enter into the trade.
We then start to reduce our books with the same exact trade, in opposite logic when the return is no longer there.
Now, let’s check on our trade:
Nice, I actually made some money while demonstrating…
Cheers.
To run the dashboard, cd to the dev/ folder on quantpylib, then first run the data feeder:
python3 feeder.py
and let it run indefinitely. This uses the credit semaphore and continuously polls the data in a rate-safe way. Then spin up another terminal and do
python3 -m streamlit run board.py
Cheers~
bordbe
github: lupoinvesting