Crypto QuantLab
11 min read
Motivation
Around my junior year of highschool, I started getting big into "internet money". By this, I mean various different ways to get rich online. This started off with daytrading, then it went to NFTs, then finally it just landed on crypto. Ever since then, the technology and applications of Crypto/Web3 have been super interesting to me. Fast forward a few years and I'm a sophomore at JHU who's getting more and more into programming and finance-y applications of software.
After creating my first project, this blend of interesting between software and cryptocurrency would start my next project, a comprehensive data platform and suite of tools that would amplify my ability to make money in the market. Well, I sort of just never finished that version. There was never anything too interesting in it and eventually I wanted to take the project in a completely different route. Instead of just being a boilerplate dashboard with redundant data you could find anywhere else, the other path became clear: a quantitative research system for crypto currency.
With that, the goal was clear, use this as a reason to learn some cool things about quant research and how the practice actually works.
Design Decisions
By the virtue of the fact that this project was meant to be less technical from a programming sense, the design is not noteworthy. A simple HTTP server that routes the frontend to backend calculation functions is the entire scope of the project. With that being said, the lack of nuance in the code is made up with some neat mathematical tricks that are, or at least have been, used by quantitative researchers.
Mathematical Deep-Dive
There are four main categories of theory and math we focused on. Lets go through categories one by one and understand its theory and its usecase in the system.
Part I: Portfolio Theory
portfolio theory is a massive part with investing today. Managers conducting research on different types of action abide by contemporary portfolio theory. While some may consider this a little old-school, the results don't lie. In this project's usecase, we're just running one model: Mean-Variance Optimization. Curated by American economist Harry Markowitz, this model attempts to maximize return per unit of risk. If you know your stuff, you'll realize that this is just saying to maximize the sharpe ratio. We can find this given expected returns and covariance matrix , to calculate the portfolio weights/allocation that maximize the risk-to-reward ratio. The optimal portfolio is found on the curve of possible portfolio weights, known as the efficient frontier, where you find the tangency portfolio when considering these constraints:
Then, you will find the optimal portfolio. Of course, this is not a flawless money-making machine. Some drawbacks are:
- Inputs (, ) are estimated from historical data and are therefore not 100% accurate
- There is a long-only position constraint, eliminating short-selling entirely. That is not realistic
Part II: Cointegration & Pairs Trading
Some of the most lucrative strategies in history have leveraged a powerful statistical property known as cointegration. Before getting into what it is, here's the intuition: most asset prices are random walks, meaning they wander endlessly with no stable mean, no tendency to revert, just noise on top of noise. Cointegration is the rare case where two of these wandering series are tethered together. They can each drift forever, but they can never permanently drift apart.
Here's a concrete example. Imagine $BTC and $ETH tend to move together over the long run. Not necessarily perfectly, and not always, but there's an underlying relationship that keeps them from diverging indefinitely. Modern systems detect this relationship statistically, then watch for moments when it breaks down. When $ETH gets cheap relative to $BTC beyond what the historical relationship would predict, that's a signal: long ETH, short \BTC, and wait for the spread to converge back. The math guarantees it has toEventually, that is. That guarantee is what makes this interesting. It's not just a pattern someone eyeballed in a chart. It's a provable statistical property, and the trade is the exploitation of a temporary violation of it.
The formal framework that makes this rigorous is known as the Vector Error Correction Model, or VECM for short. Given a vector of log prices ,
Breaking this down, is just the vector of daily returns, not too interesting. What is interesting is , which attempts to encode all long-run relationships between the assets. Diving deeper,
Here, holds the cointegrating vectors. When we transpose beta, becomes the stationary spread(s). Essentially, this is what captures the invariant relationship between the two assets. On the other hand, represents the adjustment speeds, or how aggressively each asset corrects back towards the equilibrium spread. Finally, the rank of is the number of independent long-run relationships. If , there are cointegrating relationships to exploit.
The natural follow-up question is, "How can we determine the rank?". Let's intuit this first. Trivially, we know that rank is zero if is a zero matrix. Now, assume that we know , the next step is to break it down further with our second equation . The rank is determined now by the number of nonzero columns in , at least in theory. The real problem lies in the fact that if you naively estimated from data, the noise in the data would trump the actual signals and you would find a full-rank matrix every time.
To solve this problem, Søren Johansen created the aptly named Johansen test. Instead of directly estimating from data, the test finds the rank of indirectly through a cleaner procedure. Given the complexity of the original VECM model, the first step of the Johansen test is to strip out the short-run dynamics. This is done by regressing on the lagged differences and saving the residuals . Then, we simply repeat the process for with the same lags and saving the residuals as . At this point, both series filter for only the long-term information by removing everything that short-run autocorrelation can explain. and consist solely of the long-run co-movement signal, where represents filtered price changes and represents filtered price levels.
The next step is to solve a generalized eigenvalue problem. Given our residuals from step one, we construct the cross-product matrices , , and . Here is what each conceptually represents:
- : how price changes co-vary with each other
- : how price levels co-vary with each other
- : how price changes co-vary with price levels
Once these matrices are calculated, we solve:
Each eigenvalue measures the canonical correlation between and in a particular direction. Larger eigenvalues indicate that the linear combination of prices strongly predicts tomorrow's correction, highlighting a mean-reverting, cointegrating relationship. Eigenvalues close to zero indicate that direction has no predictive power and is a random walk.
Rather than drawing an arbitrary cutoff for significance on eigenvalues, Johansen formalizes the counting with:
This tests the null hypothesis where by asking whether the remaining eigenvalues are all statistically indistinguishable from zeroThat is, whether that linear combination of prices has no mean-reverting pull and behaves like a random walk. If they are, for each and the sum is small, and you fail to reject rank . Conversely, if any eigenvalue is significant, the sum grows large, rejecting the null and concluding that the rank is at least . This process repeats starting from , incrementing until you fail to reject.
This completely sidesteps the noise problem because it never estimates directly. Instead, it finds the directions in price space that maximally explain mean reversion, and those directions are the cointegrating vectors themselves, the spreads you ultimately trade.
Part III: Systematic Strategies
Modern trading systems rely heavily on computer programs that run curated algorithms, entering and exiting the market based on various conditions. These programs fall under the category of systematic investing. The art of systematic investing lies in finding certain configurations of parameters modeling volume, price change, volatility, and many other metrics that together maximize returns. In this project I've implemented a few of the more popular strategies in systematic investing. The strategies are quick and digestibleThe simplicity of these algorithms is actually a feature when you consider a fascinating tradeoff. Systematic investing requires programs to be blazingly fast and to beat out their competition. The nuance lies in the tradeoff between program logic and speed. The more complicated an algorithm or trading decision is, the slower it runs, but the algorithm must also have enough nuance to be profitable. I digress
The first strategy focuses solely on momentum. The core belief is that recent winners are more likely to keep winning and recent losers are more likely to keep losing. It turns out that this is one of the most empirically robust anomalies in the markets, showing up across asset classes, geographies, and time periods going back over a century.
From an implementation perspective, the specific flavor here is cross-sectional momentumCross-sectional momentum is market neutral and typically produces a stronger, less noisy signal than absolute momentum since broad market moves affect all assets equally and cancel out. The distinction is that we aren't looking at whether an asset goes up in absolute terms, but whether it is winning or losing relative to the other assets in the basket. The process is as follows:
- For each day , compute the 21-day cumulative return for each asset
- Rank all assets by that return as a percentile in
- Assign positions: if percentile , if percentile , otherwise
- Portfolio return:
The second strategy is mean reversion. Instead of betting on winners and losers continuing to diverge, this strategy assumes that outlier prices return back to their recent mean. If $BTC has been trading around $80K over the last 20 days but is now sitting at $60K, the strategy bets that BTC will revert back toward \80K and enters a long position. To put it simply, it trades the move back to the mean.
In a technical sense, all we need here is basic statistics. Leveraging z-scores relative to a 20-day rolling window:
- For each day , compute the z-score for each asset relative to its 20-day rolling mean
- Assign positions: if , if , otherwise
- Portfolio return:
The threshold of corresponds roughly to the 95th percentile of a normal distribution, meaning the strategy only trades genuinely unusual moves rather than everyday noise.
It also turns out that I didn't select these two strategies arbitrarily. Momentum thrives in trending markets where assets keep moving in one direction; as the price of Ethereum surges, the market supports and hypes the asset further. On the other hand, there are certainly markets that lack these traits and are instead much more choppy with immense price oscillations. These rougher conditions are the bread and butter for mean reversion, which captures random oscillatory movements and turns them into profit. So when one strategy is underperforming, the other tends to be better positioned, and the combined strategy ends up with a smoother return profile than either one alone.
Part IV: Backtesting
The system includes a backtesting engine that replays each strategy over historical price data and returns a performance report consisting of: sharpe ratio, win/loss ratio, max drawdown, and total return. Nothing novel here, just a clean implementation to close the loop on strategy evaluation.