UniV3 Strategy - Part 6, WMATIC-USDC
A little over a month ago when the market was in a free fall, I wanted to scoop up some matic at 40c ~ 60c, but I waited several days and its price kept at above 80c. So I decided to use the Univ3 WMATIC-USDC pool on polygon instead of spot buying. I set my range at about 40c ~ 93c with 100% USDC and 0 WMATIC initially and planned to remove my liquidity when price falls to 40c or my average cost basis reaches around 60c or 70c. Then I kinda of forgot about it. Today when I was fitting an ARIMA model to hourly matic price data for this article, I remembered my position and checked it on revert. Here’s the result: after 34.9 days of LPing, the current fee APR sits at 25.96% and the total APR is at 16.09%1. I also get additional 4% MATIC rewards from revert for staking my LP with them for 14 days. The LP only swapped 21% of my initial USDC into WMATIC, accumulating less matic than I wanted. But the 25%+ fee APR surprised me, after all, my price range was pretty wide. Not gonna complain. When the market goes from worse to worse, it’s good to have stables earn 25%+ yield while accumulating the asset you want for the next bull. So I’ll let it be and report back in another month.
That’s a detour into today’s main topic, where I’ll show you how ARIMA model works by training one on matic hourly prices and making forecasts for the next 1, 2, 3 hours. Once again, the motivation came from a scenario where in anticipation of a surge in trading volumes, you want to max out the fees through super-concentrated liquidity provision in the WMATIC-USDC pool. If you haven’t read my previous article on ARMA model, I recommend you to read it first before continuing.
In theory, if a time series is not stationary, we are not allowed to fit an ARMA model on it. Stationarity means the series has no trend (constant mean) or cyclic variation (constant autocorrelation) and its seasonal pattern also doesn’t change. That’s a mouthful. Unless you are interviewed by a math/stats PhD from a big-brand-name University, you don’t really need to understand what stationarity is. You just need to know that
real data are rarely stationary,
how to formally test if a time series is stationary, and
differencing often helps.
When a series is non-stationary, differencing it once, twice, three times, …, and d times can sometimes make it stationary. This process is called integration. If differencing it d times makes it stationary, we say the degree of differencing is d. For example, the hourly matic price series between 2022-12-01 00:00:00 and 2022-12-15 23:00:00 displayed below is clearly not stationary because of the drop. And we can formally test it using something called the adfuller test. It returns a p-value of 0.8712, indicating the price series is indeed non-stationary.
But when we subtract the previous price from the current price, the resulting series looks like almost stationary. The adfuller test gives a tiny p-value of almost 0, confirming that the 1st order differenced series is likely stationary, and hence can be modeled with ARMA model.
If we make the PACF and ACF plots, we’ll see either AR(0) or MA(0) will work for the differenced series. See my article for how to read the PACF and ACF plots.
ARIMA Model
In practice, we don’t need to do this multi-step process, we can fit the ARIMA model to the price series directly, and it does the differencing under the hood. And there’s a tool for auto-detect the degree of differencing, namely, the `ndiffs()` function in a python package called `pmdarima`. In this example, let’s use an ARIMA(0,1,0) and carry out the iterative training and forwarding testing scheme as we did previously. The following screen reports the first few records of forecasts vs. actual observations.
The following figures plot the forecasts and actuals over time. We see our model’s forecasts become worse as we try to predict more distance into the future. This is expected! The average prediction error for next-hour and next-3hour are 0.547% and 0.85% respectively.
Code & Data
Python notebook. Make sure you study my code to understand the details of how I carried out each step. Pay attention to when/how I used training and test parts of the series to avoid data snooping/leaking.
Referrals
This section contains affiliate links to crypto products. If you click on the link and use the product, I may receive a small commission at no cost to you. I only link to products I use myself.
Get 5% discount when trading on GMX.
Juno Finance offers free onramp to Arbitrum, Optimism and Solana, a high interest bearing checking account (currently at 5%), and a great loyalty program that gives ledger, gift cards, and 5% cash back for spending. You will get $10 and 500 JCOIN if you use my referral link to open an account and fund it with $50 worth crypto or more. Available to US persons and requires KYC.
If you enjoyed this article and would like to buy me a coffee, you can send ETH, WBTC, AVAX, BNB, USDC, USDT to 0x783c5546C863f65481BD05Fd0e3FD5f26724604E, or you can tip me sat. Thank you and have a great day!
I don’t really care about the total APR here because the goal was to accumulate matic. So IL is not my concern. In fact, I wanted to have a big IL and hence a negative total APR since that would imply I bought matic at lower prices.