2022-04-29 20:44:29 +00:00
|
|
|
|
2022-04-09 14:38:00 +00:00
|
|
|
library(data.table)
|
|
|
|
library(ggplot2)
|
|
|
|
library(scales)
|
2022-04-29 20:44:29 +00:00
|
|
|
library(Cairo)
|
2022-04-09 14:38:00 +00:00
|
|
|
# NOTE: Also need lubridate package installed, but not loading it due to
|
|
|
|
# it masking functions
|
|
|
|
|
2022-05-12 02:10:07 +00:00
|
|
|
bch.data.dir <- ""
|
|
|
|
|
|
|
|
spent.status.by.day <- readRDS(paste0(bch.data.dir, "spent_status_by_day.rds"))
|
|
|
|
state.trans.by.day <- readRDS(paste0(bch.data.dir, "state_trans_by_day.rds"))
|
|
|
|
|
|
|
|
|
2022-04-09 14:38:00 +00:00
|
|
|
|
|
|
|
|
2022-04-29 20:44:29 +00:00
|
|
|
sum.value.pre.fork <- sum(spent.status.by.day[1,
|
|
|
|
.(value.btc.unspent.bch.unspent, value.btc.spent.bch.unspent,
|
|
|
|
value.btc.unspent.bch.spent, value.btc.spent.bch.spent)])
|
|
|
|
|
|
|
|
sum.outputs.pre.fork <- sum(spent.status.by.day[1,
|
|
|
|
.(outputs.btc.unspent.bch.unspent, outputs.btc.spent.bch.unspent,
|
|
|
|
outputs.btc.unspent.bch.spent, outputs.btc.spent.bch.spent)])
|
|
|
|
|
|
|
|
|
|
|
|
current.status <- spent.status.by.day[block_time.date == "2022-03-31", ]
|
|
|
|
|
|
|
|
current.status[,
|
|
|
|
.(value.btc.unspent.bch.unspent, value.btc.spent.bch.unspent,
|
|
|
|
value.btc.unspent.bch.spent, value.btc.spent.bch.spent)]
|
|
|
|
|
|
|
|
100 * current.status[,
|
|
|
|
.(value.btc.unspent.bch.unspent, value.btc.spent.bch.unspent,
|
|
|
|
value.btc.unspent.bch.spent, value.btc.spent.bch.spent)] / sum.value.pre.fork
|
|
|
|
|
|
|
|
|
|
|
|
current.status[,
|
|
|
|
.(outputs.btc.unspent.bch.unspent, outputs.btc.spent.bch.unspent,
|
|
|
|
outputs.btc.unspent.bch.spent, outputs.btc.spent.bch.spent)]
|
|
|
|
|
|
|
|
100 * current.status[,
|
|
|
|
.(outputs.btc.unspent.bch.unspent, outputs.btc.spent.bch.unspent,
|
|
|
|
outputs.btc.unspent.bch.spent, outputs.btc.spent.bch.spent)] / sum.outputs.pre.fork
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spent.status.by.day.value.reshaped <- melt(spent.status.by.day[,
|
|
|
|
.(block_time.date, value.btc.unspent.bch.unspent, value.btc.spent.bch.unspent,
|
|
|
|
value.btc.unspent.bch.spent, value.btc.spent.bch.spent)], id.vars = c("block_time.date"),
|
|
|
|
measure.vars = c("value.btc.unspent.bch.unspent", "value.btc.spent.bch.unspent",
|
|
|
|
"value.btc.unspent.bch.spent", "value.btc.spent.bch.spent"))
|
|
|
|
|
|
|
|
|
|
|
|
spent.status.by.day.value.reshaped[, block_time.date := as.POSIXct(block_time.date)]
|
|
|
|
spent.status.by.day.value.reshaped[, variable :=
|
|
|
|
factor(variable, levels = c("value.btc.unspent.bch.unspent", "value.btc.unspent.bch.spent",
|
|
|
|
"value.btc.spent.bch.unspent", "value.btc.spent.bch.spent"))]
|
|
|
|
|
|
|
|
|
|
|
|
spent.status.by.day.outputs.reshaped <- melt(spent.status.by.day[,
|
|
|
|
.(block_time.date, outputs.btc.unspent.bch.unspent, outputs.btc.spent.bch.unspent,
|
|
|
|
outputs.btc.unspent.bch.spent, outputs.btc.spent.bch.spent)], id.vars = c("block_time.date"),
|
|
|
|
measure.vars = c("outputs.btc.unspent.bch.unspent", "outputs.btc.spent.bch.unspent",
|
|
|
|
"outputs.btc.unspent.bch.spent", "outputs.btc.spent.bch.spent"))
|
|
|
|
|
|
|
|
|
|
|
|
spent.status.by.day.outputs.reshaped[, block_time.date := as.POSIXct(block_time.date)]
|
|
|
|
spent.status.by.day.outputs.reshaped[, variable :=
|
|
|
|
factor(variable, levels = c("outputs.btc.unspent.bch.unspent", "outputs.btc.spent.bch.unspent",
|
|
|
|
"outputs.btc.unspent.bch.spent", "outputs.btc.spent.bch.spent"))]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-05-12 02:10:07 +00:00
|
|
|
state.trans.by.day.value.reshaped <- melt(state.trans.by.day[,
|
|
|
|
.(block_time.date, value.ff.to.tf, value.ff.to.ft, value.ff.to.tt,
|
|
|
|
value.tf.to.tt, value.ft.to.tt)], id.vars = c("block_time.date"),
|
|
|
|
measure.vars = c("value.ff.to.tf", "value.ff.to.ft", "value.ff.to.tt",
|
|
|
|
"value.tf.to.tt", "value.ft.to.tt"))
|
2022-04-29 20:44:29 +00:00
|
|
|
|
|
|
|
|
2022-05-12 02:10:07 +00:00
|
|
|
state.trans.by.day.value.reshaped[, block_time.date := as.POSIXct(block_time.date)]
|
|
|
|
state.trans.by.day.value.reshaped[, variable :=
|
|
|
|
factor(variable, levels = c("value.ff.to.tf", "value.ff.to.ft", "value.ff.to.tt",
|
|
|
|
"value.tf.to.tt", "value.ft.to.tt"))]
|
2022-04-29 20:44:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-05-12 02:10:07 +00:00
|
|
|
state.trans.by.day.outputs.reshaped <- melt(state.trans.by.day[,
|
|
|
|
.(block_time.date, outputs.ff.to.tf, outputs.ff.to.ft, outputs.ff.to.tt,
|
|
|
|
outputs.tf.to.tt, outputs.ft.to.tt)], id.vars = c("block_time.date"),
|
|
|
|
measure.vars = c("outputs.ff.to.tf", "outputs.ff.to.ft", "outputs.ff.to.tt",
|
|
|
|
"outputs.tf.to.tt", "outputs.ft.to.tt"))
|
2022-04-29 20:44:29 +00:00
|
|
|
|
|
|
|
|
2022-05-12 02:10:07 +00:00
|
|
|
state.trans.by.day.outputs.reshaped[, block_time.date := as.POSIXct(block_time.date)]
|
|
|
|
state.trans.by.day.outputs.reshaped[, variable :=
|
|
|
|
factor(variable, levels = c("outputs.ff.to.tf", "outputs.ff.to.ft", "outputs.ff.to.tt",
|
|
|
|
"outputs.tf.to.tt", "outputs.ft.to.tt"))]
|
2022-04-29 20:44:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
date.breaks <- seq.POSIXt(min(spent.status.by.day.value.reshaped$block_time.date),
|
|
|
|
max(spent.status.by.day.value.reshaped$block_time.date), by = "month")
|
|
|
|
|
2022-04-09 14:38:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
c_trans <- function(a, b, breaks = b$breaks, format = b$format) {
|
|
|
|
a <- scales::as.trans(a)
|
|
|
|
b <- scales::as.trans(b)
|
|
|
|
|
|
|
|
name <- paste(a$name, b$name, sep = "-")
|
|
|
|
|
|
|
|
trans <- function(x) a$trans(b$trans(x))
|
|
|
|
inv <- function(x) b$inverse(a$inverse(x))
|
|
|
|
|
|
|
|
trans_new(name, trans, inverse = inv, breaks = breaks, format=format)
|
|
|
|
}
|
|
|
|
# Thanks to https://stackoverflow.com/questions/59542697/reverse-datetime-posixct-data-axis-in-ggplot-version-3
|
|
|
|
|
|
|
|
rev_date <- c_trans("reverse", "time")
|
|
|
|
|
|
|
|
# #FF9900 BTC color
|
|
|
|
# https://gist.github.com/paladini/ef383fce1b782d919898
|
|
|
|
# #0AC18E BCH color
|
|
|
|
# https://bitcoincashstandards.org/
|
|
|
|
|
2022-04-29 20:44:29 +00:00
|
|
|
png(paste0(bch.data.dir, "preliminary-pre-fork-BTC-BCH-spent-status-by-value.png"), width = 800, height = 2000)
|
2022-04-09 14:38:00 +00:00
|
|
|
|
|
|
|
print(
|
2022-04-29 20:44:29 +00:00
|
|
|
ggplot(spent.status.by.day.value.reshaped, aes(x = block_time.date, y = value, fill = variable)) +
|
|
|
|
ggtitle("Spent status of Pre-fork BTC and BCH by Bitcoin Value") +
|
2022-04-09 14:38:00 +00:00
|
|
|
geom_area(alpha = 0.6 , size = 0, colour = "black") + coord_flip() +
|
2022-04-29 20:44:29 +00:00
|
|
|
scale_x_continuous(trans = rev_date, breaks = date.breaks, labels = date_format("%b-%Y"), expand = c(0, 0)) +
|
|
|
|
scale_y_continuous(breaks = sum.value.pre.fork * seq(0, 1, by = 0.1),
|
|
|
|
labels = scales::percent_format(scale = 100 * 1/sum.value.pre.fork, accuracy = 1), expand = c(0, 0)) +
|
|
|
|
scale_fill_manual(
|
|
|
|
labels = c("BTC & BCH spent", "BTC spent & BCH unspent", "BTC unspent & BCH spent", "BTC & BCH unspent"),
|
|
|
|
values = c("purple", "#FF9900", "#0AC18E", "darkgrey"),
|
|
|
|
breaks = c("value.btc.spent.bch.spent", "value.btc.spent.bch.unspent",
|
|
|
|
"value.btc.unspent.bch.spent", "value.btc.unspent.bch.unspent")) +
|
|
|
|
ylab("Percentage of Pre-fork Bitcoin Value") +
|
2022-04-09 14:38:00 +00:00
|
|
|
theme(legend.position = "top", axis.title.y = element_blank(),
|
2022-04-29 20:44:29 +00:00
|
|
|
plot.title = element_text(size = 27),
|
2022-04-09 14:38:00 +00:00
|
|
|
axis.text = element_text(size = 20), axis.title.x = element_text(size = 20),
|
2022-04-29 20:44:29 +00:00
|
|
|
legend.title = element_blank(), legend.text = element_text(size = 14)) +
|
2022-04-09 14:38:00 +00:00
|
|
|
geom_vline(xintercept = as.POSIXct("2017-11-12"), linetype = 3) +
|
2022-04-29 20:44:29 +00:00
|
|
|
geom_text(aes(x = as.POSIXct("2017-11-12"), label = "Max BCH/BTC Exchange Rate",
|
|
|
|
y = 0.75 * sum.value.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
2022-04-09 14:38:00 +00:00
|
|
|
geom_vline(xintercept = as.POSIXct("2017-12-20"), linetype = 3) +
|
2022-04-29 20:44:29 +00:00
|
|
|
geom_text(aes(x = as.POSIXct("2017-12-20"), label = "Max BCH/USD Exchange Rate",
|
|
|
|
y = 0.75 * sum.value.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
2022-04-09 14:38:00 +00:00
|
|
|
geom_vline(xintercept = as.POSIXct("2018-11-15"), linetype = 3) +
|
2022-04-29 20:44:29 +00:00
|
|
|
geom_text(aes(x = as.POSIXct("2018-11-15"), label = "BSV Hard Fork",
|
|
|
|
y = 0.25 * sum.value.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
2022-04-09 14:38:00 +00:00
|
|
|
geom_vline(xintercept = as.POSIXct("2020-11-15"), linetype = 3) +
|
2022-04-29 20:44:29 +00:00
|
|
|
geom_text(aes(x = as.POSIXct("2020-11-15"), label = "BCHABC Hard Fork",
|
|
|
|
y = 0.25 * sum.value.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
|
|
|
geom_text(aes(x = as.POSIXct("2022-03-15"), label = "github.com/Rucknium",
|
|
|
|
y = 0.87 * sum.value.pre.fork), colour = "black", size = 6, check_overlap = TRUE)
|
2022-04-09 14:38:00 +00:00
|
|
|
)
|
|
|
|
# https://en.wikipedia.org/wiki/List_of_bitcoin_forks
|
2022-04-29 20:44:29 +00:00
|
|
|
# expand = c(0, 0) due to:
|
|
|
|
# https://stackoverflow.com/questions/48611719/remove-inner-padding-in-ggplot
|
2022-04-09 14:38:00 +00:00
|
|
|
dev.off()
|
|
|
|
|
|
|
|
|
2022-04-29 20:44:29 +00:00
|
|
|
|
|
|
|
png(paste0(bch.data.dir, "preliminary-pre-fork-BTC-BCH-spent-status-by-outputs.png"), width = 800, height = 2000)
|
|
|
|
|
|
|
|
print(
|
|
|
|
ggplot(spent.status.by.day.outputs.reshaped, aes(x = block_time.date, y = value, fill = variable)) +
|
|
|
|
ggtitle("Spent status of Pre-fork BTC and BCH by Number of Outputs") +
|
|
|
|
geom_area(alpha = 0.6 , size = 0, colour = "black") + coord_flip() +
|
|
|
|
scale_x_continuous(trans = rev_date, breaks = date.breaks, labels = date_format("%b-%Y"), expand = c(0, 0)) +
|
|
|
|
scale_y_continuous(breaks = sum.outputs.pre.fork * seq(0, 1, by = 0.1),
|
|
|
|
labels = scales::percent_format(scale = 100 * 1/sum.outputs.pre.fork, accuracy = 1), expand = c(0, 0)) +
|
|
|
|
scale_fill_manual(
|
|
|
|
labels = c("BTC & BCH spent", "BTC spent & BCH unspent", "BTC unspent & BCH spent", "BTC & BCH unspent"),
|
|
|
|
values = c("purple", "#FF9900", "#0AC18E", "darkgrey"),
|
|
|
|
breaks = c("outputs.btc.spent.bch.spent", "outputs.btc.spent.bch.unspent",
|
|
|
|
"outputs.btc.unspent.bch.spent", "outputs.btc.unspent.bch.unspent")) +
|
|
|
|
ylab("Percentage of Pre-fork Outputs") +
|
|
|
|
theme(legend.position = "top", axis.title.y = element_blank(),
|
|
|
|
plot.title = element_text(size = 26),
|
|
|
|
axis.text = element_text(size = 20), axis.title.x = element_text(size = 20),
|
|
|
|
legend.title = element_blank(), legend.text = element_text(size = 14)) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2017-11-12"), linetype = 3) +
|
|
|
|
geom_text(aes(x = as.POSIXct("2017-11-12"), label = "Max BCH/BTC Exchange Rate",
|
|
|
|
y = 0.75 * sum.outputs.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2017-12-20"), linetype = 3) +
|
|
|
|
geom_text(aes(x = as.POSIXct("2017-12-20"), label = "Max BCH/USD Exchange Rate",
|
|
|
|
y = 0.75 * sum.outputs.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2018-11-15"), linetype = 3) +
|
|
|
|
geom_text(aes(x = as.POSIXct("2018-11-15"), label = "BSV Hard Fork",
|
|
|
|
y = 0.10 * sum.outputs.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2020-11-15"), linetype = 3) +
|
|
|
|
geom_text(aes(x = as.POSIXct("2020-11-15"), label = "BCHABC Hard Fork",
|
|
|
|
y = 0.15 * sum.outputs.pre.fork), colour = "black", size = 6, check_overlap = TRUE) +
|
|
|
|
geom_text(aes(x = as.POSIXct("2022-03-15"), label = "github.com/Rucknium",
|
|
|
|
y = 0.87 * sum.outputs.pre.fork), colour = "black", size = 6, check_overlap = TRUE)
|
|
|
|
)
|
|
|
|
dev.off()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ann_text.value <- data.frame(
|
|
|
|
block_time.date = as.POSIXct("2022-03-15"),
|
|
|
|
value = 300000,
|
2022-05-12 02:10:07 +00:00
|
|
|
variable = factor("value.ft.to.tt", levels = levels(state.trans.by.day.value.reshaped$variable)))
|
2022-04-29 20:44:29 +00:00
|
|
|
# Due to
|
|
|
|
# https://stackoverflow.com/questions/11889625/annotating-text-on-individual-facet-in-ggplot2
|
|
|
|
|
|
|
|
|
|
|
|
png(paste0(bch.data.dir, "preliminary-pre-fork-BTC-BCH-trans-matrix-by-value.png"), width = 800, height = 2000)
|
|
|
|
|
|
|
|
print(
|
2022-05-12 02:10:07 +00:00
|
|
|
ggplot(state.trans.by.day.value.reshaped, aes(x = block_time.date, y = value, fill = variable)) +
|
2022-04-29 20:44:29 +00:00
|
|
|
ggtitle("State Transition of Pre-fork BTC and BCH by Bitcoin Value\nKEY: {BTC Spent}{BCH Spent} to {BTC Spent}{BCH Spent}") +
|
|
|
|
geom_line(aes(color = variable)) + coord_flip() +
|
|
|
|
scale_x_continuous(trans = rev_date, labels = date_format("%b-%Y"), expand = c(0, 0),
|
|
|
|
breaks = date.breaks) +
|
|
|
|
scale_y_continuous(labels = scales::comma) +
|
|
|
|
facet_grid(. ~ variable, labeller = labeller(variable =
|
2022-05-12 02:10:07 +00:00
|
|
|
c(value.ff.to.tf = "FF to TF", value.ff.to.ft = "FF to FT", value.ff.to.tt = "FF to TT",
|
|
|
|
value.tf.to.tt = "TF to TT", value.ft.to.tt = "FT to TT" ))) +
|
2022-04-29 20:44:29 +00:00
|
|
|
ylab("Quantity of Bitcoin Value Transitioned per Day") +
|
|
|
|
theme(legend.position = "none", axis.title.y = element_blank(),
|
|
|
|
strip.text.x = element_text(size = 20), plot.title = element_text(size = 24),
|
|
|
|
axis.text = element_text(size = 15), axis.title.x = element_text(size = 15),
|
|
|
|
axis.text.x = element_text(angle = 270)) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2017-11-12"), linetype = 3) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2017-12-20"), linetype = 3) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2018-11-15"), linetype = 3) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2020-11-15"), linetype = 3) +
|
|
|
|
geom_text(data = ann_text.value, label = "github.com/Rucknium",
|
|
|
|
colour = "black", size = 4.5, check_overlap = TRUE)
|
|
|
|
)
|
|
|
|
dev.off()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ann_text.output <- data.frame(
|
|
|
|
block_time.date = as.POSIXct("2022-03-15"),
|
|
|
|
value = 280000,
|
2022-05-12 02:10:07 +00:00
|
|
|
variable = factor("outputs.ft.to.tt", levels = levels(state.trans.by.day.outputs.reshaped$variable)))
|
2022-04-29 20:44:29 +00:00
|
|
|
|
|
|
|
png(paste0(bch.data.dir, "preliminary-pre-fork-BTC-BCH-trans-matrix-by-outputs.png"), width = 800, height = 2000)
|
|
|
|
|
|
|
|
print(
|
2022-05-12 02:10:07 +00:00
|
|
|
ggplot(state.trans.by.day.outputs.reshaped, aes(x = block_time.date, y = value, fill = variable)) +
|
2022-04-29 20:44:29 +00:00
|
|
|
ggtitle("State Transition of Pre-fork BTC and BCH by Number of Outputs\nKEY: {BTC Spent}{BCH Spent} to {BTC Spent}{BCH Spent}") +
|
|
|
|
geom_line(aes(color = variable)) + coord_flip() +
|
|
|
|
scale_x_continuous(trans = rev_date, labels = date_format("%b-%Y"), expand = c(0, 0),
|
|
|
|
breaks = date.breaks) +
|
|
|
|
scale_y_continuous(labels = scales::comma) +
|
|
|
|
facet_grid(. ~ variable, labeller = labeller(variable =
|
2022-05-12 02:10:07 +00:00
|
|
|
c(outputs.ff.to.tf = "FF to TF", outputs.ff.to.ft = "FF to FT", outputs.ff.to.tt = "FF to TT",
|
|
|
|
outputs.tf.to.tt = "TF to TT", outputs.ft.to.tt = "FT to TT" ))) +
|
2022-04-29 20:44:29 +00:00
|
|
|
ylab("Number of Transitioned Outputs per Day") +
|
|
|
|
theme(legend.position = "none", axis.title.y = element_blank(),
|
|
|
|
strip.text.x = element_text(size = 20), plot.title = element_text(size = 24),
|
|
|
|
axis.text = element_text(size = 15), axis.title.x = element_text(size = 15),
|
|
|
|
axis.text.x = element_text(angle = 270)) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2017-11-12"), linetype = 3) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2017-12-20"), linetype = 3) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2018-11-15"), linetype = 3) +
|
|
|
|
geom_vline(xintercept = as.POSIXct("2020-11-15"), linetype = 3) +
|
|
|
|
geom_text(data = ann_text.output, label = "github.com/Rucknium",
|
|
|
|
colour = "black", size = 4.5, check_overlap = TRUE)
|
|
|
|
)
|
|
|
|
dev.off()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|