Building a crypto momentum trading strategy - Part 2
This is the second part of the article on building a crypto momentum trading strategy. The first part can be found at:
https://medium.com/coinmonks/building-a-crypto-momentum-trading-strategy-4527bbe1bbac
or
https://www.bulbapp.io/p/b8788f61-804b-45dc-9683-ae3769688df5/building-a-crypto-momentum-trading-strategy
The strategy from scratch
First, import all libraries that we’ll use.
import requests
import json
import pandas as pd
import datetime as dt
from heapq import nlargest
from functools import reduce
import numpy as np
from scipy import stats
Once all necessary libraries are imported, we can begin to read data from Binance. Binance is the largest crypto exchange in the world. So, it makes sense to test the momentum strategy on its data. Let’s create a list containing tens of cryptocurrencies trading on Binance. Create an array variable called lst:
You can of course add to and delete from any item from this list. Now, define a create_df() function to read Binance data for the tokens we specified and create a data frame containing their price data.
def create_df():
pair = “USDT”
root_url = ‘https://api.binance.com/api/v3/klines'
interval = ‘1d’
close_prices = pd.DataFrame()
for i in lst:
url = root_url + ‘?symbol=’ + i + pair + ‘&interval=’ + interval
data = json.loads(requests.get(url).text)
if ‘msg’ in data:
pass
else:
df = pd.DataFrame(data)
df.columns = [‘open_time’,
‘o’, ‘h’, ‘l’, ‘c’, ‘v’,
‘close_time’, ‘qav’, ‘num_trades’,
‘taker_base_vol’, ‘taker_quote_vol’, ‘ignore’]
df.index = [dt.datetime.fromtimestamp(x/1000.0) for x in df.close_time]
close_price = df[‘c’]
close_prices[i] = close_price
close_prices = close_prices.apply(pd.to_numeric)
return close_prices
I won’t go through the code step by step. You can do it yourself; in fact, I encourage you to do this to understand it well. It’s mostly self-explanatory. Call the function and assign the output to close_prices. If you take a look at close_prices, it should contain historical prices for securities we specified in the list above. Something like below.
Parameters
The dates and thus prices will likely vary, but you get the idea. Now, let’s define our parameters for the strategy. The first thing we have to decide is how many days’ data we’ll look at which is what lookback does. When researchers backtest momentum strategy in equity markets, they usually look back to 3–12 last months’ performance dropping the last month. But since crypto is more dynamic than the stock market, it is much likely that any momentum effect will be eroded away during 90 days. That’s why for this model, I decided to go with 35 days. We’ll drop the data of the most recent 14 days, and this is what the line last_days = 14 does.
We’ll rebalance the portfolio once every 7 days which means that we’ll hold our coins for 7 days, and after 7 days we will run the test again to decide whether to hold or sell any of the 5 coins we are holding at the moment. The last parameter, threshold, refers to the performance of BTC as a percent return. The reason why we do this is as follows. Momentum in crypto markets almost always starts with the strong BTC performance. Only when BTC seems strong, altcoin season begins. Therefore, if BTC shows a lackluster performance, i.e., BTC return is below the specified threshold, we don’t do anything. If BTC has better return than our predefined threshold, we start trading altcoins.
Exponential regression
Now that we obtained the historical data from Binance and defined the model parameters, you may ask “OK, how do we select the five best coins of the week?” It is a good question and an answer to it can make a big difference between a great and a bad model. For this strategy I’ll use the momentum metric developed by Andreas Clenow by his book “Trading Evolved”. By the way, it is a wonderful introductory book on building trading strategies in Python.
I should first explain why we don’t just look at percent returns to measure momentum. Let’s take a highly volatile coin. The news about it was just released and the coin is skyrocketing. This doesn’t mean the cryptocurrency in question is actually strong; it just reacted to the news after which it can give back most of its return to the market. Now you see the problem, I hope. If we choose percent return as a metric, our portfolio will be dominated by highly volatile digital assets. But this is not what momentum is about. We have to think of not only performance but also the path of this performance.
Clenow’s idea is to gauge momentum with exponential regression and then multiply it by R2, the coefficient of determination. Regression is a statistical approach to quantify the relationship between a dependent variable and one or more independent variables. Linear regression, which is the most widely used form of regression analysis, seeks to find a straight line that best fits to the data which in our case is prices of cryptocurrency traded at Binance. The slope of the line indicates the trend and, in our model, it will be in USDT if we choose to employ linear regression. What the slope tells us is if the current trend continues, how much, i.e., how many USDT we can earn or lose.
But here is the problem. Take two coins with a high and a low price, e.g., $MKR which is trading at a 4-figure price and $SHIBA which is trading at such a tiny price that the number of zeros in its price seems infinite. Let’s say, we run our model and both cryptocurrencies show the regression slope of $0.1 (or 0.1 USDT, it doesn’t matter for our discussion). Though the slope is the same for the tokens, it means different things for $MKR and $SHIBA. Since 0.1 is the miniscule percentage of $MKR price, this model implies that Maker is rising very slowly. Conversely, the slope of $SHIBA is large relatively to its price which would mean that $SHIBA is trading at a greater momentum right now. So, using a model which produces the slope in absolute USD or USDT numbers is not useful and can result in wrong investment decisions.
The slope of exponential regression, on the other hand, gives information in percentages, i.e., how many percent up or down the line is sloping. This is much more useful than linear regression for our purposes because it allows to compare tokens without regard to their prices. We’ll annualize it because the slope of exponential regression tends to be a very small number. Say, for example, the slope is 0.000634. We annualize the number:
(1+0.00634)365–1 = 0.2603
This means that we’re dealing with the digital asset with the positive trend of approximately 26% per year. The reason why we 365 is that since our data is daily, result of the model will also be daily. Therefore, to annualize it we raise to the power of 365 because crypto markets are open 24/7, 365 days per year.
Now about the coefficient of determination part. This metric, more succinctly called R2, measures how well the regression line fits the data. In other words, it shows how well the variation in our independent variable(s) explains the variation in the dependent variable. The higher R2 is, the better. We add the coefficient of determination to punish more volatile tokens. Digital assets rising gradually will have a smoother trend and thus a higher R2.
The code below does everything we discussed above.
def slope(ts):
ts = ts.dropna()
x = np.arange(len(ts))
log_ts = np.log(ts)
slope, intercept, r_value, p_value, std_err = stats.linregress(x, log_ts)
annualized_slope = (np.power(np.exp(slope), 365) -1) *100
return annualized_slope * (r_value ** 2)
First, it creates natural log series calculated from our price data. This is because the most convenient way to run exponential regression is to calculate linear regression on the log of the original time series. The fifth line calculates the needed metrics, viz. slope and r_value (the coefficient of determination). SciPy is a powerful Python library used for scientific computing. In this model we won’t calculate linear or exponential regression manually but instead will use SciPy. The built-in function stats.linregress does exactly what we need. The last line returns annualized slope which has been calculated in the previous line.
I created a PDF file explaining this model and attached the full Python code.
To get both PDF and Python code, please go to the following link:
https://fmiren.gumroad.com/l/zwnkt?
_gl=1*goxinf*_ga*MTgyNzMyOTE1NC4xNzAzNjU2ODAw*_ga_6LJN6D94N6*MTcwMzkzMjA3Ny4xNC4xLjE3MDM5MzIwNzkuMC4wLjA.
https://www.amazon.com/dp/B0CRQHMJYL
2024 will be THE great year for crypto. And I’m sure momentum strategies will shine as they always do in bull markets.
Make 2024 your year!