Análisis de un caso básico
Si hay un indicador que les guste a los agoreros del precio de bitcoin es sin duda el índice Fear and Greed (miedo y codicia) que se publica diariamente en la web de Crypto Fear & Greed Index.
Es una métrica que intenta adivinar el sentimiento del mercado, si este es positivo (>50) presupone que habrá una mayor demanda de BTC por lo que el precio subirá y si es negativo (<50) se traducirá en ventas del activo con la consiguiente bajada del precio. Este indicador de Alternative para bitcoin lleva publicándose desde el 5/2/2018.
Vamos a realizar un estudio para conocer si es rentable la compra y venta de BTC siguiendo este indicador, lo que se conoce como un backtesting, escogemos un caso básico donde se compran bitcoin cuando el índice es mayor que 50, que es el valor donde empieza la codicia, y se venden cuando baja por debajo de ese límite. Utilizaremos el lenguaje de programación Python junto con las librerías que tiene preparadas para este tipo de análisis.
Esta métrica la construyen diariamente a partir de 5 fuentes de datos:
- Volatilidad (25 %). Se compara la volatilidad del día anterior con los promedios de los últimos 30 y 90 días. La idea que hay detrás sería que una alta volatilidad es una señal de un mercado temeroso.
- Volumen / impulso del mercado (25 %). En este indicador se compara el volumen de ayer con los valores promedio de los últimos 30 y 90 días. Entendiendo que altos volúmenes de compra indican que el mercado está codicioso y alcista.
- Redes Sociales (15%). Análisis de los mensajes en Twitter relacionados con Bitcoin. Tasas de interacciones altas significan más interés lo que se traduce en un mercado codicioso.
- Dominancia (10%). El dominio de una moneda se asemeja a la cuota de capitalización de mercado de todo el criptomercado. Si aumenta ese dominio de bitcoin frente a las otras altcoins es una señal alcista y si disminuye es un indicador bajista.
- Tendencias (10%). Este indicador se extrae de los datos de Google Trends para varias consultas de búsqueda relacionadas con Bitcoin, se analizan estos números y si el número de búsquedas sube se supone que el interés por Bitcoin aumenta y que por consiguiente aumenta la euforia y disminuye el miedo.
Primero se va a analizar el comportamiento del indicador Fear and Greed (F&G) sin tener en cuenta la evolución de precios de bitcoin.
Para ello importamos las librerías de python que se utilizarán.
import pandas as pd
import numpy as np
import requests
import matplotlib.pyplot as plt
import seaborn as sns
import yfinance as yf
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from scipy.stats import norm
from pylab import rcParams
import warnings
warnings.filterwarnings('ignore')
rcParams['figure.figsize'] = 10, 5
Se descarga el histórico de datos del índice Fear and Greed
# Data download of https://alternative.me/crypto/fear-and-greed-index/
# The index fear_greed that shows today is the value calculated with yesterday's data
r = requests.get('https://api.alternative.me/fng/?limit=0')
Se muestra una gráfica con la evolución temporal del indicador
# Show fear and greed index since the beginning of the year 2018
# The values range between 0 and 100, with low values indicating fear and high values indicating euphoria.
df = pd.DataFrame(r.json()['data'])
df.value = df.value.astype(int)
df.timestamp = pd.to_datetime(df.timestamp, unit='s')
df.set_index(df.timestamp, inplace=True)
df.rename(columns = {'value':'fear_greed'}, inplace=True)
df.drop(['timestamp', 'time_until_update'], axis=1, inplace=True)
df.fear_greed.plot(figsize=(20,10))

Los valores del índice F&G se mueven entre el 0 al 100, donde los datos bajos indican miedo en el mercado y los altos euforia.
A priori viendo la gráfica no se pueden extraer conclusiones claras así que optaré por “interrogar” a los datos.
Inicialmente miro la distribución de los valores y se aprecia que la mayor parte de los datos están alrededor del valor 26 lo cual indica que en este periodo ha predominado el miedo y que los valores altos asociados con la euforia son menos frecuentes.
# Show in a graph the distribution of the values of the fear and euphoria index
# Where it can be seen that in this period the most recurrent values are around 20 and 40, which are indicators of fear
sns.distplot(df['fear_greed'], color='g', bins=30)

La media es 42, la mediana 39 lo que nos indica que en este periodo, 2018 a 2022, en términos generales ha habido más miedo que euforia y en el gráfico de caja se ve que además la mayor parte de los valores están entre el 24 y el 59 y que el resto de valores son menos frecuentes.
# The mean and median values are around 40, which indicates that fear prevails over euphoria
print("Mean: " + str(df.fear_greed.mean()))
print("Median: " + str(df.fear_greed.median()))
sns.boxplot(x='fear_greed', data=data)

Si analizamos la autocorrelación de los datos de la muestra veremos que esta existe y es mayor cuanto los datos son mas cercanos. Lo cual parece lógico ya que el miedo y la euforia siguen tendencias no cambian arbitrariamente de un día para otro y siempre tendrán más influencia en el valor de hoy, el dato de ayer, que el de antes de ayer, que el de hace dos días… y a medida que pasan los días este influencia va decreciendo.
# There is a high autocorrelation in the fear and greed index that decreases little by little as the days go by
# It is normal since fear and greed work for periods it is not usual to go from extreme fear one day to high greed the next day
# Today's index is more likely to be more like yesterday's than 2 weeks ago as trend changes take time to occur
plot_acf(df["fear_greed"], lags=30)
plt.show()

Con respecto a la autocorrelación parcial no vemos esta dependencia tan escalonada, influyen los datos de ayer y de antes de ayer pero el resto ya entra dentro de la irrelavancia.
# The partial autocorrelation is strong with respect to yesterday, a little more with the day before yesterday, but after those two days
# Does not exist since they are statistically insignificant since they are within the confidence interval (shaded part)
plot_pacf(df["fear_greed"], lags=30)
plt.show()

Esta correlación que se da en el valor de F&G con los días anteriores no se mantiene si nos centramos en el incremento o decrecimiento del valor de un día para otro donde si tenemos una mayor aletoriedad.
# But if we focus on the variations of the index from one day to the next, we do find a great randomness
df.fear_greed.diff().plot(figsize=(15,6))

# If the distribution of values of the difference is shown, we see that it is an almost normal distribution centered on a value close to 0
sns.distplot(df.fear_greed.diff(), color='c', bins=30, fit=norm)

Ahora toca analizar el precio de bitcoin en relación con el índice F&G y por ello empiezo descargándome los datos del precio de cierre de bitcoin de la web de Yahoo finance.
# Data Bitcoin price download of yahoo finance
df1 = yf.download('BTC-USD', interval = '1d')[['Close']]
df1.rename(columns = {'Close':'close'}, inplace=True)
df1.index.name = 'timestamp'
df1['timestamp'] = df1.index
df1.reset_index(drop=True, inplace=True)
df1.timestamp = pd.to_datetime(df1.timestamp, unit='s').dt.tz_localize(None)
df1.set_index(df1.timestamp, inplace=True)
df1.drop(['timestamp'], axis=1, inplace=True)
Unimos en un mismo dataframe los datos del índice más los del precio de BTC.
# The fear and greed index data is merged with the bitcoin price data in dollars
data = df.merge(df1, on='timestamp')
data = data.sort_index()
data.tail()

Muestro en una gráfica el histórico de precios de bitcoin desde 5/2/2018 hasta finales del 2022 que son los datos que tenemos del índice F&G.
Haciendo un análisis muy somero se aprecian varios periodos diferenciados:
- Del 2018 a finales del 2020 donde hay una relativa estabilidad en el precio
- De finales del 2020 hasta el primer cuarto del 2021 donde hay un periodo alcista, posteriormente tenemos un periodo bajista, para luego conseguir en noviembre del 2021 el mayor precio de BTC de la historia
- Y desde ahí hasta finales del 2022 vivimos un periodo bajista
# The graph of the price of bitcoin during that same period
# Briefly analyzed we see a relative stability between 2018 and the end of 2020
# Subsequently a very pronounced rise until the end of the first quarter of 2021
# Then a descent followed by a big rise ending at the end of 2022
# And since then a bearish period
data.close.plot()

De cara a comparar los precios y saber como de bueno es este indicador para predecirlos tenemos que tener en cuenta que el dato del índice de Fear and Greed de hoy se publica a las 00:00 UTC a partir de la información del día anterior y el precio de cierre de bitcoin de un día es su valor de mercado a las 00:00 UTC. Esto supone que a las 00:00 UTC del día tenemos el índice F&G con la fecha de hoy y el precio de cierre de BTC también con la fecha de hoy y con esa información queremos ejecutar una estrategia de compra o de venta y que tendremos que compararla con el precio de cierre de mañana a las 00:00 UTC de bitcoin.
# The fear and greed index is published at 00:00 UTC taking into account the data of the previous day
# The closing data of the bitcoin price is the value at 00:00 UTC
# Therefore, in order to make money, the value to be compared with is the closing price of the next day
# A column is included with the data from tomorrow's close and the difference between the two values
# Another columns with returns in value today and tomorrow and change ntc price
data['close_tomorrow'] = data['close'].shift(-1)
data['returns'] = data['close_tomorrow'] / data['close'] - 1
data['change_btc'] = (data['returns'] + 1).cumprod()
data = data.dropna()
Antes de realizar la estrategia vemos que la correlación entre el índice F&G y el precio de BTC del día siguiente es de 0.24 un valor por encima de 0 indica que si que existe una relación, por lo menos en el periodo estudiado, entre los dos valores.
# We perform a correlation between the F&G index and the closing price of BTC the next day
# A total correlation would be 1 and 0 indicates that there is no correlation, so 0.24 indicates that there is a slight correlation
data['fear_greed'].corr(data['close_tomorrow'])
0.2400391649234413
Definimos la estrategia básica donde se procede a comprar cuando el indicador F&G sea mayor que 50 y se vende cuando es menor que ese valor.
# A basic BTC purchase strategy is analyzed when the fear and greed index is greater than 50
# and when it is less than that value, nothing is done
data['signal'] = np.where(data.fear_greed > 50, 1, 0)
data['strategy'] = (data['returns'] +1) ** data['signal']
data['cumulative'] = data[['strategy']].dropna().cumprod()
data.tail()

Mostramos el backtesting en un gráfico donde se observa el desempeño de la estrategia escogida junto a la evolución del precio de bitcoin para la mismo periodo.
# Graph of the performance of the strategy compared to the evolution of the price
plt.figure(figsize=(20,10))
plt.plot(data['cumulative'], label ='Cumulative')
plt.plot(data['change_btc'], label ='BTC')
plt.legend()

El resultado de esta estrategia es claramente positivo con un beneficio de alrededor de un 600%. En la parte final de la gráfica se aprecia que el beneficio se mantiene en horizontal debido a que el índice Fear and Greed lleva con valores por debajo de 50 desde 5 de abril del 2022.
# It is clearly observed that it is a good strategy for the period studied.
print('Initial value: \t' + str(data['cumulative'].iloc[1]))
print('End value: \t' + str(data['cumulative'].iloc[-2]))
print('End value BTC: \t' + str(data['change_btc'].iloc[-2]))
Initial value: 1.0
End value: 6.430155875523231
End value BTC: 2.264909298446648
A priori parece una muy buena estrategia pero ya sabemos que el diablo está en los detalles:
- Es únicamente válida al 100% para el periodo, 5/02/2018 a 27/10/2022, pero desconocemos el rendimiento que tendría si tuviésemos un histórico mayor de datos del índice Fear and Greed.
- El porcentaje de ganancia final es dependiente del punto inicial y del punto final escogido con otras referencias el beneficio puede oscilar considerablemente pero es cierto que en la gráfica se observa que la mayor parte del tiempo tiene un mejor desempeño que el precio del BTC.
- El cálculo de la ganancia sigue el análisis típico de estrategias de trading donde se calculan porcentajes lo que equivale a que cada vez que se da una señal de compra se utiliza todo el capital lo cual no es muy realista.
- Y lo más importante no se han tenido en cuenta las comisiones que van a ser muy importantes en esta estrategia porque se está utilizando todo el capital disponible en las órdenes de compra y venta.
Creo una función para calcular el beneficio real de esta estrategia suponiendo que sólo se utiliza un capital inicial, que cuando hay un sentimiento de euforia por encima de 50 se utiliza todo el capital para comprar BTC y que cuando el índice baja de 50 se venden todos los bitcoin e incluyendo las comisiones.
# I carry out the most realistic practical exercise starting with an initial investment and adding a commission on purchases and sales
# Everything is sold when the buy signal runs out since in this strategy all the capital is used for buying and selling and the money is needed to buy again
def portfolio_calculation (_data, _initial_portfolio, _feeds):
n_buy_sell = 0
sell = 0
portfolio = _initial_portfolio
for date,row in data.iterrows():
if row['signal'] == 1:
n_buy_sell += 1
buy = (portfolio / row['close'])*(1-_feeds)
_data.at[date, 'buy'] = buy
portfolio = buy * row['close_tomorrow']
_data.at[date, 'portfolio'] = portfolio
sell = portfolio
elif sell != 0:
n_buy_sell += 1
sell_BTC = (sell/ row['close'])*(1-_feeds)
_data.at[date, 'portfolio'] = portfolio
_data.at[date, 'sell'] = sell_BTC
portfolio = sell
sell = 0
print("Nº buy and sell: \t" + str(n_buy_sell))
print("Feeds: \t\t\t" + str(_feeds) + "%")
print("Initial portfolio: \t$" + str(_initial_portfolio))
print("End Portfolio: \t\t$" + str(round(portfolio,2)))
print("Profit: \t\t$" + str(round(portfolio-_initial_portfolio, 2)))
Se realiza el ejercicio práctico con un capital inicial de 10000 dólares y suponemos que el broker cobra una comisión de un 0.3% por cada compra o venta.
# Initial investment of $10,000 and a commission of 0.3%
feeds = 0.003
initial_portfolio = 10000
portfolio_calculation(data, initial_portfolio, feeds)
El número de veces que se han lanzado órdenes de compra o venta es de 619 cuando han pasado unos 1700 días.
El capital que se tendría a día de hoy (27 de octubre 2022) es de 11846 dólares, se han invertido inicialmente 10000 $ así que el beneficio total es de 1846 $, muy lejos del 600% que nos indicaba el backtesting de la estrategia.
Esto es debido a las comisiones que aunque no parecen muy altas al haber realizado tantas compras y ventas y siempre con el total del capital hace que los beneficios bajen considerablemente.
Nº buy and sell: 619
Feeds: 0.003%
Initial portfolio: $10000
End Portfolio: $11846.65
Profit: $1846.65
Paramos aquí el ejercicio dejando al lector que pruebe por si mismo otras estrategias sobre este índice F&G.
Notebook en Python con el script para poder copiarlo y ejecutarlo Bitcoin Price Prediction with the Fear and Greed
Versión en Inglés: Is it profitable to trade bitcoin from the Fear and Greed index?
Categories: Bitcoin, BTC, Code, Notebook, Price, Python, Script, Trader, Trading
Leave a Reply