Bitcoin price prediction with chaos theory

Leonardo
9 min readJul 15, 2021

Is it possible to predict an asset price with differential equations?

Introduction

Solution to the Lorenz attractor, symbol of chaos theory

It is known that financial assets price can exhibit turbulent, chaotic price movements and are, for the most part, random. Due to this nature, such systems are difficult to model using deterministic equations.

However, there are deterministic models that predict and can model chaotic behavior. There are numerous examples of such equations, one example being the three-dimensional Navier-Stokes equations which model with excellent accuracy turbulent flows in water and air.

One of the most “simple” equations that exhibit chaotic behavior on its solutions are called “jerk” equations, which are ordinary differential equations of third order. They are called “jerk” equations because they include the third derivative of a variable, which in the case of mechanics is called “jerk”. “Jerk” is defined as the variation of acceleration of an object.

In this article, a “jerk” equation will be utilized to model and predict the daily close price of an asset, on this particular case the close price of the Bitcoin cryptocurrency. First, the mathematical formulation will be presented and the numerical methods utilized for obtaining the equation parameters. Next, the results obtained, including kinematics data from Bitcoin price and statistics of the predictive model as well as its use as a risk-management tool. This article is ended with discussion of the method and its potential, with the Python code utilized attached.

Obs. 1: If you are not familiar with undergraduate math (calculus, differential equations, numerical methods and linear algebra) you can skip the methodology section and go straight to the results section.

Obs. 2: This is NOT a scientific article nor it has the intention of being one, as that would require peer-review. Nevertheless, I will try to be as scientific rigorous as possible.

Methodology

Mathematical model (Jerk equation)

The velocity of an asset price is the rate of change in time of that price, i.e, the derivative of the asset price (x) with respect to time t:

The acceleration of a price is the rate of change of velocity, or the second derivative of the price with respect to time:

Jerk is defined as the rate of change of acceleration in time, or the third derivative of the price with respect to time:

Differential equations of the form

are called jerk equations. It has been shown that a jerk equation, which is equivalent to a system of three first order, ordinary, non-linear differential equations, is in a certain sense the minimal setting for solutions showing chaotic behavior. This type of equation is often utilized to model electronic circuits which exhibit chaotic behavior.

Thus, the approach to model Bitcoin chaotic price movement will be model its behavior with an equation of the form:

Or, denoting x’’’ as the third derivative, x’’ as the second derivative and x’ as the first derivative, this equation can be more easily represented as:

On this equation, A, B, C, D and E are constants (real numbers) to be determined accordingly with the methods described in the next sections.

When E = 0, this differential equation has the following characteristic equation:

By obtaining its roots, which can be complex numbers, the analytical solution can be obtained:

Where C1, C2 and C3 are constants which can be determined from the initial conditions x0 (initial price), v0 (initial velocity), a0 (initial acceleration and j0 (initial jerk):

This set of equations consists in the following linear system:

Its solution yields the constants C1, C2 and C3, thus obtaining a particular solution of the differential equation.

Discretization (finite difference method)

In order to determine constants A, B, C, D and E, first it is necessary to compute the velocity (first derivative), acceleration (second derivative) and jerk (third derivative). The method utilized to obtain the derivatives was the finite difference method, using forward finite differences of first order.

Finite difference approximation of the first derivative
Finite difference approximation of the second derivative
Finite difference approximation of the third derivative

The indexes denote the close price in a given time interval.

Since the time frame utilized was the daily chart and the predictions will be made for a day interval, in the following calculations the parameter Δt will be equal to 1.

Solution to the linear system

In order to obtain the coefficients A, B, C, D and E, a least-squares solutions of the following linear system was obtained, where each row represents one day of data up to n days:

This is a linear system of the type:

On this system, ε is a parameter which must be close to zero in order to approximate the original equation. Ideally, this parameter would be equal to zero, but this would yield trivial solutions with all coefficients equal to zero. In order to avoid that, it was utilized ε with values of order 1E-6 and below in order to achieve convergence of the values of constants A, B, C, D and E.

Predictor equation

The jerk equation was discretized using the mentioned finite-difference equations for the third, second and first derivative, obtaining the following equation:

The close price value in the next day can then be approximated using the following equation, with the constants obtained by solving the linear system mentioned earlier:

Results

Kinematics

The figure below shows the Bitcoin close price, velocity, acceleration and jerk for a one-year period, from July of 2020 to July of 2021. An interesting feature that can be observed is the increase of magnitude of velocity, acceleration and jerk around January of 2021, which follows the surge in price up to its peak in April of 2021 and the bear market of May 2021.

Bitcoin close price (x), velocity (x’), acceleration (x’’) and jerk (x’’’) from July of 2020 to July of 2021

The three charts that follow show the histogram and adjusted probability distribution of, respectively, velocity, acceleration and jerk from the period of 2018 to 2021. As expected, the three variables show mean around zero.

Histogram for Bitcoin velocity (2018–2021)
Histogram for Bitcoin acceleration (2018–2021)
Histogram for Bitcoin jerk (2018–2021)

The figures below show the phase space of, respectively, velocity (x’) versus acceleration (x’’) and acceleration versus jerk (x’’’), which, as expected, exhibit an attractor towards point (0, 0), which shows the tendency of price movement towards equilibrium.

Phase space for acceleration (x’’) and velocity (x’)
Phase space for jerk (x’’’) and acceleration (x’’)

The figure below displays the three-dimensional phase space of price velocity, acceleration and jerk in the period of 2018–2021, where again it is observed a formation of an attractor towards point (0, 0, 0).

Three-dimensional phase space for jerk (x’’’), acceleration (x’’) and velocity (x’)

Statistics of the predictor equation

With the velocity, acceleration and jerk obtained, as discussed in the previous section, the constants of the jerk equation were determined using least squares and are shown in the table below.

The chart that follows shows the box-plot of the relative error (%) of the daily predictor in relation to the actual close price, where a high occurrence of outliers is observed.

Box-plot of relative error (%) of daily close price prediction

The average relative error obtained was 5.33% and the standard-deviation was 4.58%. Other statistical data are shown in the table below.

Statistical data from the box-plot of daily close price prediction (%)

The chart plotted below displays the Bitcoin close price in one year range as well as the values predicted by the model, where a good agreement can be qualitatively observed.

One year Bitcoin close price plotted with daily predictor (07/14/2020 to 07/14/2021)

Using the predictor as a risk-management tool

Similar to the Bollinger Bands® technical indicator idea, a risk management tool can be obtained by plotting the predicted value along with two standard deviations up and down to obtain a price range with around 95% of confidence interval.

The figure below displays the close price as well with the predicted value with two standard deviations up and down in the period from April of 2021 to July of 2021. It is observed that, for the most part, the price remained inside the interval.

Bitcoin close price and two-standard deviation band of predicted value from April 2021 to July 2021

Final remarks

A jerk equation, which is a ordinary linear differential equation of third order, was utilized to forecast the close price of an asset, on this particular case of Bitcoin. The derivatives were obtained using finite difference method and the coefficients of the equation were then obtained by solving a linear system.

This equation shown promising results in predicting Bitcoin daily price, with average relative error of around 5% and standard deviation of 4%, although with a large number of outliers. It was shown that this model can be used as an effective risk-management tool through an example using 95% of confidence interval.

Python code

import config # config file with Binance API keys
from binance.client import Client
from binance.enums import *
import pandas as pd
import numpy as np
import pylab as plt
from matplotlib import pyplot
from numpy import linalg
from sklearn import linear_model
import seaborn as sns
client = Client(config.API_KEY, config.API_SECRET)# valid intervals - 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1Mdef derivative(x):
dx = np.zeros(len(x))
for i in range(1,len(x)-2):
dx[i-1] = x[i]-x[i-1]
return dx
def print_file(pair, interval, name):# request historical candle (or klines) data
bars = client.get_historical_klines(pair, interval, "14 Jun, 2018", "14 Jul, 2021")

# delete unwanted data - just keep date, open, high, low, close
for line in bars:
del line[6:]

# save as CSV file
df = pd.DataFrame(bars, columns=['date', 'open', 'high', 'low', 'close', 'volume'])
df.set_index('date', inplace=True)
df.to_csv(name)
print_file('BTCUSDT', '1d', "BTC_kinematics.csv")df = pd.read_csv("BTC_kinematics.csv", parse_dates=True)
closes = df.close
volumes = df.volume
volumes = np.array(volumes)
closes = np.array(closes)
closes_v = derivative(closes)
closes_a = derivative(closes_v)
closes_j = derivative(closes_a)
dates = pd.to_datetime(df['date'], unit='ms')
timestamps = df['date']
timestamps = np.array(timestamps)
fig, axs = plt.subplots(4)
axs[0].plot(dates, closes, color = 'b')
axs[0].set_title('Bitcoin close price [$]')
axs[1].plot(dates, closes_v, color = 'r')
axs[1].set_title('Bitcoin velocity [$/d]')
axs[2].plot(dates, closes_a,color = 'g')
axs[2].set_title('Bitcoin acceleration [$/d²]')
axs[3].plot(dates, closes_j,color = 'm')
axs[3].set_title('Bitcoin jerk [$/d³]')
for ax in fig.get_axes():
ax.label_outer()
plt.legend()
plt.show()
plt.plot(closes, closes_v,'o')
plt.xlabel("Price (x)")
plt.ylabel("Price velocity (x')")
plt.show()
plt.plot(closes, closes_a,'o')
plt.xlabel("Price (x)")
plt.ylabel("Price acceleration (x'')")
plt.show()
plt.plot(closes, closes_j,'o')
plt.xlabel("Price (x)")
plt.ylabel("Price jerk (x''')")
plt.show()
plt.plot(closes_v, closes_a,'o')
plt.xlabel("Price velocity (x')")
plt.ylabel("Price acceleration (x'')")
plt.show()
plt.plot(closes_a, closes_j,'o')
plt.xlabel("Price acceleration (x'')")
plt.ylabel("Price jerk (x''')")
plt.show()
ax = plt.axes(projection='3d')
ax.scatter(closes, closes_v, closes_a, c=closes_a, cmap='viridis', linewidth=0.5)
ax.set_xlabel("Price (x)")
ax.set_ylabel("Price velocity (x')")
ax.set_zlabel("Price acceleration (x'')")
plt.show()
ax = plt.axes(projection='3d')
ax.scatter3D(closes, closes_v, closes_a, c=closes_a, cmap='Greens')
ax.set_xlabel("Price (x)")
ax.set_ylabel("Price velocity (x')")
ax.set_zlabel("Price acceleration (x'')")
plt.show()
ax = plt.axes(projection='3d')
ax.scatter(closes_v, closes_a, closes_j, c=closes_j, cmap='viridis', linewidth=0.5)
ax.set_xlabel("Price velocity (x')")
ax.set_ylabel("Price acceleration (x'')")
ax.set_zlabel("Price jerk (x''')")
plt.show()
ax = plt.axes(projection='3d')
ax.scatter3D(closes_v, closes_a, closes_j, c=closes_j, cmap='Greens')
ax.set_xlabel("Price velocity (x')")
ax.set_ylabel("Price acceleration (x'')")
ax.set_zlabel("Price jerk (x''')")
plt.show()
sns.distplot(closes_v)
plt.xlabel('Bitcoin velocity [$/d]')
plt.ylabel("Frequency")
plt.show()
sns.distplot(closes_a)
plt.xlabel('Bitcoin acceleration [$/d²]')
plt.ylabel("Frequency")
plt.show()
sns.distplot(closes_j)
plt.xlabel('Bitcoin jerk [$/d³]')
plt.ylabel("Frequency")
plt.show()
eps = 1e-9
A = np.matrix([closes_j, closes_a, closes_v, closes, np.ones(len(closes))])
A = A.reshape(len(closes),5)
B = np.ones(len(closes))*eps
X = np.linalg.lstsq(A, B)
print(X)

--

--

Leonardo

Software developer, former civil engineer. Musician. Free thinker. Writer.