Trading using r/Cryptocurrency mentions data

As Quiver Quantitative expands its cryptocurrency metrics, we can begin to build and backtest trading strategies derived from this data. Using information from Reddit’s Cryptocurrency forum we can design a relatively simple algorithmic trading approach. The code that follows will provide a rough outline of this strategy as well as provide some framework with which one could use to build more complex systems. The goal here will not necessarily be to generate alpha, but rather to showcase a simple use case for the r/CryptoCurrency discussion data.

The Strategy

1. We begin by using the Quiver API to access data from the Cryptocurrency subreddit.

2. Identify the five most mentioned cryptocurrencies or tokens per week.

3. Size your portfolio using the cryptocurrencies/tokens mentions in proportion to each other. Buy at the start of the trading week and sell end of week.

4. Repeat.

Preparation

Like I mentioned before, we should begin by accessing our data. In this particular case I used the quiverquant package in Python. In order to work efficiently, we should properly group our data in a format conducive to our strategy. The code you see here provides us approximately 18 months’ worth of ‘Mentions’ data.

import pandas as pd
import quiverquant
#Replace "token" with your own personal token
quiver = quiverquant.quiver("token")
enddate = pd.to_datetime("now")
startdate = pd.to_datetime("now")-pd.Timedelta(days=30)
started = False
while startdate >= pd.to_datetime("2020-01-01"):
df = quiver.cryptoCommentsHistorical(date_from=startdate.strftime('%Y%m%d'), date_to=enddate.strftime('%Y%m%d'))
enddate = startdate
startdate = startdate-pd.Timedelta(days=30)
if not started:
combined = df
started = True
else:
combined = pd.concat([combined, df])

Now we can generate a Pandas Dataframe and with a few simple lines of code this data can be grouped into total mentions per week by ticker.

#convert Datetime to Y-M-D, (no time)
import datetime as dt
combined['Date'] = combined['Datetime'].dt.date
# Generates number of comments mentioning a specific cryptocurrency each day
daily = combined.groupby(["Ticker","Date"]).count().reset_index()
daily = daily[["Ticker", "Date", "Yolos"]]
daily["Date"] = pd.to_datetime(daily["Date"])
# Groups mentions per day for total mentions of each crypto currency by week
weekly = daily.groupby([pd.Grouper(key='Date', freq='W-MON'),
'Ticker'])['Yolos'].sum().reset_index().sort_values('Date')
weekly['Mentions'] = weekly['Yolos']
weekly = weekly[['Date', 'Ticker','Mentions']]
weekly = weekly.sort_values('Mentions, ascending = False)

With these variables defined we can move on to backtesting our strategy.

Backtesting

I’m not going to go into too much depth on this block of code, because I expect that most of you will be more interested in building your own strategies rather than copying the one that I show here.

#Backtesting...
import yfinance as yf
dfLarge = weekly[weekly["Mentions"]>1]
dfLarge = dfLarge.sort_values("Date", ascending=True)
dates = dfLarge["Date"].unique()
#Initial capital of mock portfolio
capital = 100000
started = False
startedDFW = False
for date in dates[:-1]:
dfW = dfLarge[dfLarge['Date']==date]
dfW = dfW.sort_values('Mentions', ascending=False).head(5)
dfW['prop'] = dfW['Mentions']/dfW["Mentions"].sum()
dfW['buy'] = capital*dfW['prop']
buyDate = date+pd.Timedelta(days=6)
dfW['buyDate'] = [buyDate]*len(dfW['buy'])
if not startedDFW:
dfWs = dfW
startedDFW = True
else:
dfWs = pd.concat([dfWs, dfW])
sellDate = date+pd.Timedelta(days=15)
startedWeek = False
print(date)
for index, row in dfW.iterrows():
ticker = row["Ticker"]
ticker = ticker+"-USD"
print(ticker)
try:
ytStock = yf.download(ticker, start=str(buyDate.date()), end=str(sellDate.date()), interval="1d").reset_index()
shares = row["buy"]/ytStock["Adj Close"].values[0]
ytStock = ytStock.iloc[1:]
ytStock = ytStock.head(7)
except:
print("Error")
ytStock = yf.download("BTC-USD", start=str(buyDate.date()), end=str(sellDate.date()), interval="1d").reset_index()
shares = row["buy"]/ytStock["Adj Close"].values[0]
ytStock = ytStock.iloc[1:]
ytStock = ytStock.head(7)
sDates = list(ytStock["Date"].values)
ytStock = ytStock[ytStock["Date"].isin(sDates[:5]+sDates[7:])]
ytStock = ytStock.head(5)
ytStock["OpenAmount"] = ytStock["Open"]*shares
ytStock["CloseAmount"] = ytStock["Adj Close"]*shares
ytStock["Ticker"] = [ticker]*len(ytStock["OpenAmount"])
ytStock = ytStock.fillna(method='ffill')
ytStock = ytStock.fillna(method='bfill')
ytStock = ytStock.dropna()
if not startedWeek:
dfCombined = ytStock
startedWeek = True
else:
dfCombined = pd.concat([dfCombined, ytStock])

if not started:
dfAll = ytStock
started = True
else:
dfAll = pd.concat([dfAll, ytStock])

capital = 0
for ticker in dfCombined["Ticker"].unique():
dfT = dfCombined[dfCombined["Ticker"]==ticker]
capital+=dfT["CloseAmount"].values[-1]
print("Week end capital: ", capital)

Visuals

We also want to get a sense of how this strategy performs against alternative portfolios. In the past we have used the market as a benchmark, but in this case it seemed like the best measure might be to simply compare the performance of the mock portfolio against the performance of a few large cap cryptocurrencies.

You can see in the graph below the performance of the r/Cryptocurrency fund and also some other cryptocurrencies. Along with this I will also get historical data on the cryptocurrencies I am comparing our portfolio to.

import plotly.graph_objects as go
dfDay = dfAll.groupby("Date").sum().reset_index()
dfDay["Fund"] = ["r/Crypto"]*len(dfDay["Close"])
#Remove dates
dfDay = dfDay[~dfDay["Date"].isin([ "2020-04-20","2020-10-19","2020-10-20"])]
#Visual
import plotly.express as px
import plotly
fig = go.Figure(data=go.Scatter(x=dfDay["Date"], y=dfDay["CloseAmount"], line=dict(width=1.5),marker=dict(color="rgb(229, 81, 39)"), name="r/Crypto"))
coins = ["BTC", "XRP", 'LTC']
colors = ["red", 'blue', 'green']
for i in range(0, len(coins)):
coin = coins[i]
color = colors[i]
dfCoin = yf.download(coin+"-USD", start="2020-01-27", end="2021-06-8", interval="1d").reset_index()
dfCoin["Fund"] = [coin] * len(dfCoin["Open"])
shares = 100000/dfCoin["Open"].values[0]
dfCoin["OpenAmount"] = dfCoin["Open"]*shares
dfCoin["CloseAmount"] = dfCoin["Close"]*shares
fig.add_trace(go.Scatter(x=dfCoin["Date"], y=dfCoin["CloseAmount"], line = dict(width=1.5),marker=dict(color=color, opacity=.1), name=coin))
rCryptoReturn = (capital-100000)/100000*100
fig.update_layout(title="<b>+"+str(round(rCryptoReturn, 2))+"% Return</b><br>January 2020 - Feb 2021", titlefont=dict(color='rgb(229, 81, 39)', size=20), plot_bgcolor='rgb(32,36,44)', paper_bgcolor='rgb(32,36,44)')
fig.update_xaxes(title_text="",color='white', showgrid=False, tickfont=dict(size=10))
fig.update_yaxes(title_text="$", color='white', showgrid=False, titlefont=dict(size=20),gridcolor="rgb(228,49,34)")
fig.update_layout(
legend=dict(
title=dict(text="",font=dict(color='white')),
x=.85, y=1.15,
font=dict(
color='white',
size=15
)
)
)
fig.show()

We can also generate a bar graph depicting the weekly composition of the portfolio.

import plotly.express as px
import plotly
fig = px.bar(dfWs, x="buyDate", y="buy", color='Ticker',text='Ticker',color_discrete_sequence=px.colors.qualitative.Light24)
fig.update_layout(title="Portfolio by Week", titlefont=dict(color='rgb(228,49,34)'), plot_bgcolor='rgb(32,36,44)', paper_bgcolor='rgb(32,36,44)')
fig.update_xaxes(title_text="",color='white', showgrid=False, fixedrange=False)
fig.update_yaxes(title_text="$",color='white', showgrid=False, fixedrange=False,gridwidth=1,gridcolor="rgb(109,177,174)")
fig.update_layout(
legend=dict(
title=dict(text="Ticker",font=dict(color="white")),

font=dict(
color='white'
),

)
)
fig.show()

Conclusion

While certainly a simple approach, I hope that the code shown here today provides a framework for developing more complex strategies using data on r/CryptoCurrency discussion.

That being said neither this post nor this strategy should be used as financial advice, or as any indication of future results.