Bitcoin Analysis

Alexander J. McNeil and Martin Bladt

2024-02-16

The Bitcoin Log-Return Data

We first load the data and calculate log-returns.

data(bitcoin)
X <- (diff(log(bitcoin))[-1]) * 100 # log-returns (as percentages)
length(X)
#> [1] 1043
plot(X, type = "h")

Copula Processes

ARMA Copulas

We start with the fulcrum profile-likelihood plot which indicates that a value \(\delta = 0.45\) is about right.

U <- strank(X)

copmod_Gauss <- armacopula(pars = list(ar = 0.95, ma = -0.85))
pts <- seq(from=0.01, to=0.99, length=51) + 0.005
profilefulcrum(U, copmod_Gauss, locations = pts)
abline(v = 0.45)

Our baseline model is a model with ARMA(1,1) copula and v-transform with fulcrum at \(\delta=0.45\).

mod_Gauss <- vtscopula(copmod_Gauss, Vlinear(0.45))
fit_Gauss <- fit(mod_Gauss, U, tsoptions = tsoptions)
fit_Gauss
#> object class: vtscopula
#> ____________ 
#> Base copula: 
#> object class: armacopula
#> name: ARMA(1,1)
#> parameters: 
#>        ar1        ma1 
#>  0.9631285 -0.8424401 
#> ____________ 
#> V-transform: 
#> name: Vlinear
#> parameters: 
#> delta 
#>  0.45 
#> _____________________
#> Summary of estimates:
#>         ar.ar1      ma.ma1
#> par 0.96312845 -0.84244010
#> se  0.01146705  0.02698389
#> convergence status: 0, log-likelihood: 91.87754

D-Vine Copula (second kind)

In this next section we try a d-vine copula model of the second kind with a finite value for maxlag and a linear v-transform. We continue to use the Frank copula. The resulting model is superior to the ARMA copula model and has the same number of parameters. Note that an infinite value for maxlag makes next to no difference in the fit.

copmod_Frank <- dvinecopula2(family = "frank",
                             pars = list(ar = 0.95, ma = -0.85),
                             maxlag = 30)
mod_Frank <- vtscopula(copmod_Frank, Vlinear(0.45))
fit_Frank <- fit(mod_Frank, U, tsoptions = tsoptions)

AIC(fit_Gauss, fit_Frank)
#>           df       AIC
#> fit_Gauss  2 -179.7551
#> fit_Frank  2 -186.4793

We provide plots for the model with Frank copula to show aspects of the fit.

plot(fit_Frank, plottype = "residual")
plot(fit_Frank, plottype = "kendall")

Marginal Models

We fit 6 marginal distributions (3 symmetric and 3 skewed) of which the double Weibull gives the lowest AIC value.

marg_st <- fit(margin("st"), X)
marg_sst <- fit(margin("sst"), X)
marg_lp <- fit(margin("laplace", 
                      pars = c(mu = 0.2, scale = 2.7)), X)
marg_slp <- fit(margin("slaplace", 
                pars = c(mu = 0.2, scale = 2.7, gamma = 0.9)), X)
marg_dw <- fit(margin("doubleweibull", 
                      pars = c(mu = 0.2, shape = 0.8, scale = 2.7)), X)
marg_sdw <- fit(margin("sdoubleweibull", 
                pars = c(mu = 0.2, shape = 0.8, scale = 2.7, gamma = 0.9)), X)
AIC(marg_st, marg_sst, marg_slp, marg_lp, marg_dw, marg_sdw)
#>          df      AIC
#> marg_st   3 5816.288
#> marg_sst  4 5818.249
#> marg_slp  3 5801.355
#> marg_lp   2 5799.447
#> marg_dw   3 5749.362
#> marg_sdw  4 5751.137

Full Models

D-Vine Copula

We fit a full model combining the double Weibull margin with the VT-d-vine model of the second kind.

fullmod <- tscm(fit_Frank, margin = marg_dw)
fullmod <- fit(fullmod, as.numeric(X), 
               method = "full", tsoptions = tsoptions)
fullmod
#> object class: tscmfit
#> _______ 
#> MARGIN: 
#> name: doubleweibull
#> parameters: 
#>        mu     shape     scale 
#> 0.1916831 0.8440733 2.6951432 
#> _______
#> COPULA: 
#> object class: vtscopula
#> ____________ 
#> Base copula: 
#> object class: dvinecopula2
#> name: type2-d-vine
#> copula family: frank
#> KPACF: kpacf_arma with max lag 30
#> parameters: 
#> [1]  0.9597057 -0.8344573
#> ____________ 
#> V-transform: 
#> name: Vlinear
#> parameters: 
#> delta 
#>  0.45 
#> _________________________
#> summary of all estimates:
#>             ar          ma    margin.mu margin.shape margin.scale
#> par 0.95970573 -0.83445730 0.1916831037   0.84407334    2.6951432
#> se  0.01419982  0.02912741 0.0006240765   0.03191155    0.2711454
#> convergence status: 10 , log-likelihood: -2776.988
AIC(marg_dw, fullmod)
#>         df      AIC
#> marg_dw  3 5749.362
#> fullmod  5 5563.977

We show all the possible plots for the full model.

plot(fullmod, plottype = "residual")
plot(fullmod, plottype = "kendall")
plot(fullmod, plottype = "margin")
plot(fullmod, plottype = "vtransform")
plot(fullmod, plottype = "volprofile")
plot(fullmod, plottype = "volproxy")

plot(fullmod, plottype = "glag")