Is there a best day of week to buy or sell Bitcoin?

Which days of the week do Bitcoin make biggest gains and losses? Is there a best day of week to trade it? How about weekdays or weekends, is there a difference? In this article I explore these questions using statistics. This is an educational article, and is not investment or trading advice.

For the analyses I used historical daily Bitcoin prices between January 1st 2012 and May 5th 2021. I provide the R code I used to do the analyses so you can replicate it if you wanted to. But you will have to get the data yourself.

There are a few packages we will use so I suggest you install them and load them.

install.packages("tidyverse","data.table","plyr","kableExtra","effsize")
library(ggplot2)
library(data.table)
library(plyr)
library(tidyverse)
library(kableExtra)
library(effsize)

Is there a best day of week to trade?

First let’s get the data and calculate descriptive statistics including mean, standard deviation, minimum, and maximum values for price percent change.

# read the data in to a data frame
wd <- read_csv("weekdays.csv")
# create empty data frame to store descriptive statistics
days <- data.frame("Weekday" = character(),"Mean"=numeric(),"SD" = numeric(),"Min" = numeric(), "Max" = numeric(), stringsAsFactors = F)
daynames <- c('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday')
# calculate descriptives for each day
for (i in daynames){
  today <- wd %>%  filter (Weekday == i)
  meand <- round(mean(today$Percent), digits = 2)
  sdd <- round(sd(today$Percent), digits = 2)
  mind <- round(min(today$Percent), digits = 2)
  maxd <- round(max(today$Percent), digits = 2)
  days[i,] <- c(i,meand,sdd,mind,maxd)
}
# convert the columns to numeric
days[,c(2:5)] <- sapply(days[,c(2:5)], as.numeric)
#days <- days %>%  mutate(across(where(is.numeric), ~ round(., digits = 2)))
days %>% kbl(row.names=F) %>% kable_paper()

Let’s look at the descriptive statistics. The mean percent price change is the greatest on Mondays with 0.86% and the least on Sundays with -0.11%. We also see that on Thursdays the mean is lower than the other weekdays. But this is probably because of an outlier day on which Bitcoin dropped more than 64%. This is also reflected in the standard deviation of the percent price change on Thursdays, it is the greatest among all days.

Bitcoin day of week descriptive statistics

At first look Mondays seem promising. After all there has been news about it (https://cointelegraph.com/news/new-analysis-finds-that-mondays-are-the-best-days-to-buy-bitcoin). But is there a statistically significant difference among these days in terms of the price percent change. Let’s do a One-way ANOVA to compare the days of week.

res.aov <- aov(Percent ~ Weekday, data = wd)
summary(res.aov)

The output looks like this:

	      Df Sum Sq  Mean Sq  F value Pr(>F)  
Weekday        6    292   48.70   2.488  0.021 *
Residuals   3402  66588   19.57                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

It seems that ANOVA detected a significant difference at p < 0.05 level. Let’s see if we can compare the days and see if they are indeed different. We will do a TukeyHSD test.

TukeyHSD(res.aov)

The output is as follows:

                          diff         lwr        upr     p adj
Monday-Friday       0.50938032 -0.32659678  1.3453574 0.5497687
Saturday-Friday    -0.06990027 -0.90587736  0.7660768 0.9999815
Sunday-Friday      -0.46259999 -1.29857708  0.3733771 0.6611813
Thursday-Friday    -0.12392868 -0.96076451  0.7129072 0.9994739
Tuesday-Friday      0.31265290 -0.52418293  1.1494887 0.9276314
Wednesday-Friday    0.14733714 -0.68949869  0.9841730 0.9985870
Saturday-Monday    -0.57928058 -1.41482886  0.2562677 0.3861458
Sunday-Monday      -0.97198031 -1.80752859 -0.1364320 0.0108489*
Thursday-Monday    -0.63330899 -1.46971645  0.2030985 0.2775859
Tuesday-Monday     -0.19672741 -1.03313487  0.6396800 0.9929678
Wednesday-Monday   -0.36204318 -1.19845063  0.4743643 0.8626356
Sunday-Saturday    -0.39269972 -1.22824800  0.4428486 0.8092621
Thursday-Saturday  -0.05402841 -0.89043586  0.7823790 0.9999960
Tuesday-Saturday    0.38255317 -0.45385428  1.2189606 0.8284226
Wednesday-Saturday  0.21723741 -0.61917005  1.0536449 0.9880591
Thursday-Sunday     0.33867131 -0.49773614  1.1750788 0.8964554
Tuesday-Sunday      0.77525289 -0.06115456  1.6116603 0.0901605
Wednesday-Sunday    0.60993713 -0.22647032  1.4463446 0.3227799
Tuesday-Thursday    0.43658158 -0.40068417  1.2738473 0.7215823
Wednesday-Thursday  0.27126582 -0.56599993  1.1085316 0.9631500
Wednesday-Tuesday  -0.16531576 -1.00258151  0.6719500 0.9973098

It looks like there is only one pair of days that are significantly different than each other: Sunday and Monday. This makes sense from the table above. But what is the practical significance of this difference? We will do an effect size calculation using Cohen’s d from the effsize package.

sunday <- wd %>% filter( Weekday == 'Sunday')
monday <- wd %>% filter( Weekday == 'Monday')
cohen.d(sunday$Percent,monday$Percent)

The output:

Cohen's d
d estimate: -0.2368365 (small)
95 percent confidence interval:
     lower      upper 
-0.3629062 -0.1107669 

Finally let’s visualize the distributions of Mondays’ and Sundays’ price change frequencies.

today <- wd %>%  filter (Weekday == "Monday" | Weekday == "Sunday")
mu <- ddply(today, "Weekday", summarise, grp.mean=mean(Percent))
ggplot(today, aes(x=Percent, color=Weekday, fill=Weekday)) +
  geom_histogram(aes(y=..density..), position="identity", alpha=0.5, bins = 50)+
  geom_density(alpha=0.6)+
  geom_vline(data=mu, aes(xintercept=grp.mean, color=Weekday),
             linetype="dashed")+
  scale_color_manual(values=c("#000000", "#ff0000", "#56B4E9"))+
  scale_fill_manual(values=c("#cccccc", "#fff000", "#56B4E9"))+
  labs(title="Sunday vs Monday Price Change Percentage",x="Price Change %", y = "Density (Frequency)")
Sunday versus Monday Bitcoin price change distribution

Mondays appear to be a little more advantageous than Sundays. That was the only difference we could detect among the days of week. And practically it was a small effect.

Comparing weekends and weekdays

How about thinking in terms of workdays and weekends? Is there a difference? Let’s look into this question now. First group the data into weekdays and weekends.

weekends <- wd %>% mutate(is_weekend = ifelse(Weekday == "Saturday" | Weekday == "Sunday", "Weekends", "Weekdays"))
res.aov <- aov(Percent ~ is_weekend, data = weekends)
summary(res.aov)

The output:

Df Sum Sq Mean Sq F value  Pr(>F)   
is_weekend     1    132  132.14   6.745 0.00944 **
Residuals   3407  66748   19.59                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

It appears that there is a statistically significant difference at p < 0.01 level. Now let’s look at the difference:

TukeyHSD(res.aov)

The output:

              Df  Sum Sq Mean Sq F value  Pr(>F)   
is_weekend     1    132  132.14   6.745 0.00944 **
Residuals   3407  66748   19.59                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

It appears that there is a statistically significant difference at p < 0.01 level. Now let’s look at the difference:

TukeyHSD(res.aov)

The output is:

                        diff       lwr        upr     p adj
Weekends-Weekdays -0.4355487 -0.764365 -0.1067324 0.0094424

Now let’s see if this difference is practically significant too.

wknd<- weekends %>% filter(is_weekend == "Weekends")
wkd<- weekends %>% filter(is_weekend == "Weekdays")
cohen.d(wknd$Percent,wkd$Percent)

The output is:

Cohen's d

d estimate: -0.09840186 (negligible)
95 percent confidence interval:
     lower      upper 
-0.1727268 -0.0240769 

The difference is negligible in practical terms, though we detected a statistical significance. This is why we need to check effect sizes in our analyses. Here’s the code for the graph:

weekends <- weekends %>% filter(Percent > -30)
# create the plot for weekends and weekdays
mu <- ddply(weekends, "is_weekend", summarise, grp.mean=mean(Percent))
ggplot(weekends, aes(x=Percent, color=is_weekend, fill=is_weekend)) +
  geom_histogram(aes(y=..density..), position="identity", alpha=0.5, bins = 50)+
  geom_density(alpha=0.6)+
  geom_vline(data=mu, aes(xintercept=grp.mean, color=is_weekend),
             linetype="dashed")+
  scale_color_manual(values=c("#000000", "#ff0000", "#56B4E9"))+
  scale_fill_manual(values=c("#cccccc", "#fff000", "#56B4E9"))+
  labs(title="Weekends vs Weekdays Price Change Percentage",x="Price Change %", y = "Density (Frequency)")+
  theme_classic()

And here’s the resulting plot of weekends versus workdays.

Bitcoin price change percentage distributions for weekends versus weekdays

What does this mean? Weekends are very much like weekdays for trading Bitcoin. Reuters reported this (https://www.reuters.com/article/us-crypto-currencies-analysis-idUSKBN29G0DV). If you are a day trader you probably treat weekends like workdays. Let’s repeat again this is not investment or trading advice.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.