mirror of
https://github.com/Rucknium/misc-research.git
synced 2025-01-18 16:24:31 +00:00
Many updates; getting close to final version
This commit is contained in:
parent
222f62b905
commit
fcf5507736
3 changed files with 404 additions and 54 deletions
|
@ -2,10 +2,13 @@
|
|||
library(data.table)
|
||||
library(RSQLite)
|
||||
library(DBI)
|
||||
library(scales)
|
||||
# NOTE: Also need lubridate package installed, but not loading it due to
|
||||
# it masking functions
|
||||
|
||||
# WARNING: This code assumes that pre-fork bitcoin has been spent every day since the fork,
|
||||
# which is true up to March 31, 2022. If this code runs on later data, then will
|
||||
# have to pre-fill data.frames with dates
|
||||
|
||||
bch.data.dir <- ""
|
||||
btc.data.dir <- ""
|
||||
# Input data directory here, with trailing "/"
|
||||
|
@ -22,6 +25,9 @@ pre.fork.utxo.set <- setdiff(pre.fork.edgelist$destination_index, pre.fork.edgel
|
|||
|
||||
DBI::dbWriteTable(con.bch, "pre_fork_utxo_set",
|
||||
data.frame(destination_index = pre.fork.utxo.set, stringsAsFactors = FALSE))
|
||||
DBI::dbWriteTable(con.btc, "pre_fork_utxo_set",
|
||||
data.frame(destination_index = pre.fork.utxo.set, stringsAsFactors = FALSE))
|
||||
# Need to do this operation for both the BCH and BTC databases
|
||||
|
||||
pre.fork.utxo.set.value <- DBI::dbGetQuery(con.bch,
|
||||
'SELECT destination_index, value FROM edgelist_intermediate_2 WHERE destination_index IN (SELECT destination_index FROM pre_fork_utxo_set)')
|
||||
|
@ -32,7 +38,10 @@ pre.fork.utxo.set.value[, sum(value)] / pre.fork.bitcoin.supply
|
|||
pre.fork.bitcoin.supply - pre.fork.utxo.set.value[, sum(value)]
|
||||
# [1] 2637.559
|
||||
|
||||
pre.fork.utxo.set.value <- pre.fork.utxo.set.value[ ! destination_index %in% c(1740174960, 1740175469), ]
|
||||
duplicated.destination_index <-
|
||||
unlist(pre.fork.utxo.set.value[duplicated(destination_index), .(destination_index)])
|
||||
|
||||
pre.fork.utxo.set.value <- pre.fork.utxo.set.value[ ! destination_index %in% duplicated.destination_index, ]
|
||||
# Removes the transactions that are coinbases of blocks 91722, 91812, 91842, 91880
|
||||
# Since they are duplicated transaction hashes. See:
|
||||
# https://bitcoin.stackexchange.com/questions/40444/what-happens-when-two-txids-collide
|
||||
|
@ -42,63 +51,187 @@ excluded.duplicate.tx.hashes.output.count <- 4
|
|||
excluded.duplicate.tx.hashes.value <- 50 * 4
|
||||
|
||||
|
||||
spent.status <- DBI::dbGetQuery(con.bch,
|
||||
'SELECT origin_index, block_height FROM edgelist_intermediate_2 WHERE origin_index IN (SELECT destination_index FROM pre_fork_utxo_set)')
|
||||
colnames(spent.status) <- c("destination_index", "bch.spent.block_height")
|
||||
setDT(spent.status)
|
||||
bch.spent.status <- DBI::dbGetQuery(con.bch,
|
||||
'SELECT origin_index, block_height FROM edgelist_intermediate_1 WHERE origin_index IN (SELECT destination_index FROM pre_fork_utxo_set)')
|
||||
colnames(bch.spent.status) <- c("destination_index", "bch.spent.block_height")
|
||||
setDT(bch.spent.status)
|
||||
|
||||
|
||||
spent.status <- merge(pre.fork.utxo.set.value, spent.status, all.x = TRUE)
|
||||
# rm(pre.fork.utxo.set.value)
|
||||
btc.spent.status <- DBI::dbGetQuery(con.btc,
|
||||
'SELECT origin_index, block_height FROM edgelist_intermediate_1 WHERE origin_index IN (SELECT destination_index FROM pre_fork_utxo_set)')
|
||||
colnames(btc.spent.status) <- c("destination_index", "btc.spent.block_height")
|
||||
setDT(btc.spent.status)
|
||||
|
||||
|
||||
spent.status <- merge(pre.fork.utxo.set.value, bch.spent.status, all.x = TRUE)
|
||||
rm(pre.fork.utxo.set.value, bch.spent.status)
|
||||
spent.status <- merge(spent.status, btc.spent.status, all.x = TRUE)
|
||||
rm(btc.spent.status)
|
||||
|
||||
# aggregate(spent.status$value, by = list(! is.na(spent.status$bch.spent.block_height)), FUN = sum)
|
||||
# Group.1 x
|
||||
# 1 FALSE 5699742
|
||||
# 2 TRUE 10779508
|
||||
# table(spent.status[value > 0, ! is.na(bch.spent.block_height)])
|
||||
# FALSE TRUE
|
||||
# 29154762 21307064
|
||||
|
||||
|
||||
bch.block.times <- readRDS(paste0(bch.data.dir, "block_times.rds"))
|
||||
|
||||
bch.block.times[, block_time := as.POSIXct(block_time, origin = "1970-01-01", tz = "GMT")]
|
||||
colnames(bch.block.times) <- c("bch.spent.block_height", "block_time")
|
||||
colnames(bch.block.times) <- c("bch.spent.block_height", "bch.block_time")
|
||||
|
||||
spent.status <- merge(spent.status, bch.block.times, all = TRUE, by = "bch.spent.block_height")
|
||||
# Note that due to all = TRUE this will get all blocks,
|
||||
# even if there are no target spent outputs within the block
|
||||
|
||||
spent.status.by.block <- spent.status[,
|
||||
.(value = sum(value, na.rm= TRUE), n.outputs = length(destination_index[ (! is.na(value)) & value > 0])),
|
||||
by = .(bch.spent.block_height, block_time)]
|
||||
|
||||
spent.status.by.block[, block_time.date := lubridate::date(block_time)]
|
||||
btc.block.times <- readRDS(paste0(btc.data.dir, "block_times.rds"))
|
||||
|
||||
spent.status.by.date <- spent.status.by.block[,
|
||||
.(value = sum(value, na.rm= TRUE), n.outputs = sum(n.outputs, na.rm= TRUE)),
|
||||
by = .(block_time.date)]
|
||||
btc.block.times[, block_time := as.POSIXct(block_time, origin = "1970-01-01", tz = "GMT")]
|
||||
colnames(btc.block.times) <- c("btc.spent.block_height", "btc.block_time")
|
||||
|
||||
unspent <- spent.status.by.date[is.na(block_time.date), value]
|
||||
cumsum.na.rm <- function(x) {x[is.na(x)] <- 0; cumsum(x)}
|
||||
spent.status.by.date[, value.cumsum := cumsum.na.rm(value) - unspent]
|
||||
|
||||
spent.status.by.date[, perc.value.cumsum := 100 * value.cumsum / sum(value, na.rm = TRUE)]
|
||||
spent.status.by.date[, unspent.perc.value.cumsum := 100 - perc.value.cumsum]
|
||||
spent.status <- merge(spent.status, btc.block.times, all = TRUE, by = "btc.spent.block_height")
|
||||
|
||||
|
||||
write.csv(spent.status, file = paste0(bch.data.dir, "spent_status-test.csv"), row.names = FALSE)
|
||||
|
||||
btc.spent.status <- DBI::dbGetQuery(con.btc,
|
||||
'SELECT origin_index, block_height FROM edgelist_intermediate_2 WHERE origin_index IN (SELECT destination_index FROM pre_fork_utxo_set)')
|
||||
colnames(btc.spent.status) <- c("destination_index, btc.spent.block_height")
|
||||
setDT(btc.spent.status)
|
||||
|
||||
spent.status <- merge(spent.status, btc.spent.status, all.x = TRUE)
|
||||
spent.status[, bch.block_time.date := lubridate::date(bch.block_time)]
|
||||
spent.status[, btc.block_time.date := lubridate::date(btc.block_time)]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Column format below is:
|
||||
# {BTC spent status}{BCH spent status}.to.{BTC spent status}{BCH spent status}
|
||||
# u = unspent; s = spent
|
||||
|
||||
spent.status[, uu.to.su := as.Date(ifelse(
|
||||
ifelse(is.na(btc.block_time.date), Inf, btc.block_time.date) < ifelse(is.na(bch.block_time.date), Inf, bch.block_time.date),
|
||||
btc.block_time.date, rep(NA, .N)), origin = "1970-01-01")]
|
||||
|
||||
spent.status[, uu.to.us := as.Date(ifelse(
|
||||
ifelse(is.na(bch.block_time.date), Inf, bch.block_time.date) < ifelse(is.na(btc.block_time.date), Inf, btc.block_time.date),
|
||||
bch.block_time.date, rep(NA, .N)), origin = "1970-01-01")]
|
||||
|
||||
spent.status[, uu.to.ss := as.Date(ifelse(
|
||||
ifelse(is.na(btc.block_time.date), Inf, btc.block_time.date) == ifelse(is.na(bch.block_time.date), Inf, bch.block_time.date),
|
||||
btc.block_time.date, rep(NA, .N)), origin = "1970-01-01")]
|
||||
|
||||
spent.status[, su.to.ss := as.Date(ifelse(
|
||||
(! is.na(uu.to.su)) &
|
||||
ifelse(is.na(bch.block_time.date), Inf, bch.block_time.date) > ifelse(is.na(btc.block_time.date), Inf, btc.block_time.date),
|
||||
bch.block_time.date, rep(NA, .N)), origin = "1970-01-01")]
|
||||
|
||||
spent.status[, us.to.ss := as.Date(ifelse(
|
||||
(! is.na(uu.to.us)) &
|
||||
ifelse(is.na(btc.block_time.date), Inf, btc.block_time.date) > ifelse(is.na(bch.block_time.date), Inf, bch.block_time.date),
|
||||
btc.block_time.date, rep(NA, .N)), origin = "1970-01-01")]
|
||||
|
||||
|
||||
uu.to.su <- spent.status[ (! is.na(uu.to.su)),
|
||||
.(value.uu.to.su = sum(value, na.rm = TRUE), outputs.uu.to.su = .N), by = uu.to.su]
|
||||
names(uu.to.su)[1] <- "block_time.date"
|
||||
|
||||
uu.to.us <- spent.status[ (! is.na(uu.to.us)),
|
||||
.(value.uu.to.us = sum(value, na.rm = TRUE), outputs.uu.to.us = .N), by = uu.to.us]
|
||||
names(uu.to.us)[1] <- "block_time.date"
|
||||
|
||||
uu.to.ss <- spent.status[ (! is.na(uu.to.ss)),
|
||||
.(value.uu.to.ss = sum(value, na.rm = TRUE), outputs.uu.to.ss = .N), by = uu.to.ss]
|
||||
names(uu.to.ss)[1] <- "block_time.date"
|
||||
|
||||
su.to.ss <- spent.status[ (! is.na(su.to.ss)),
|
||||
.(value.su.to.ss = sum(value, na.rm = TRUE), outputs.su.to.ss = .N), by = su.to.ss]
|
||||
names(su.to.ss)[1] <- "block_time.date"
|
||||
|
||||
us.to.ss <- spent.status[ (! is.na(us.to.ss)),
|
||||
.(value.us.to.ss = sum(value, na.rm = TRUE), outputs.us.to.ss = .N), by = us.to.ss]
|
||||
names(us.to.ss)[1] <- "block_time.date"
|
||||
|
||||
|
||||
trans.matrix.prep <-
|
||||
data.table(block_time.date = sort(unique(lubridate::date(c(spent.status$bch.block_time, spent.status$btc.block_time)))))
|
||||
|
||||
trans.matrix.prep <- merge(trans.matrix.prep, uu.to.su, all = TRUE)
|
||||
trans.matrix.prep <- merge(trans.matrix.prep, uu.to.us, all = TRUE)
|
||||
trans.matrix.prep <- merge(trans.matrix.prep, uu.to.ss, all = TRUE)
|
||||
trans.matrix.prep <- merge(trans.matrix.prep, su.to.ss, all = TRUE)
|
||||
trans.matrix.prep <- merge(trans.matrix.prep, us.to.ss, all = TRUE)
|
||||
|
||||
|
||||
trans.matrix.prep[is.na(trans.matrix.prep)] <- 0
|
||||
|
||||
|
||||
|
||||
spent.status.by.day <-
|
||||
data.table(block_time.date = sort(unique(lubridate::date(c(spent.status$bch.block_time, spent.status$btc.block_time)))),
|
||||
value.btc.unspent.bch.unspent = NA_real_,
|
||||
outputs.btc.unspent.bch.unspent = NA_integer_,
|
||||
value.btc.spent.bch.unspent = NA_real_,
|
||||
outputs.btc.spent.bch.unspent = NA_integer_,
|
||||
value.btc.unspent.bch.spent = NA_real_,
|
||||
outputs.btc.unspent.bch.spent = NA_integer_,
|
||||
value.btc.spent.bch.spent = NA_real_,
|
||||
outputs.btc.spent.bch.spent = NA_integer_)
|
||||
|
||||
for (day.i in spent.status.by.day$block_time.date) {
|
||||
|
||||
spent.status[, btc.spent := (btc.block_time.date <= day.i) & (! is.na(btc.block_time.date))]
|
||||
spent.status[, bch.spent := (bch.block_time.date <= day.i) & (! is.na(bch.block_time.date))]
|
||||
|
||||
spent.status.by.day$value.btc.unspent.bch.unspent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ (! btc.spent) & (! bch.spent), sum(value, na.rm = TRUE)]
|
||||
|
||||
spent.status.by.day$outputs.btc.unspent.bch.unspent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ (! btc.spent) & (! bch.spent), .N]
|
||||
|
||||
|
||||
spent.status.by.day$value.btc.spent.bch.unspent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ ( btc.spent) & (! bch.spent), sum(value, na.rm = TRUE)]
|
||||
|
||||
spent.status.by.day$outputs.btc.spent.bch.unspent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ ( btc.spent) & (! bch.spent), .N]
|
||||
|
||||
|
||||
spent.status.by.day$value.btc.unspent.bch.spent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ (! btc.spent) & ( bch.spent), sum(value, na.rm = TRUE)]
|
||||
|
||||
spent.status.by.day$outputs.btc.unspent.bch.spent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ (! btc.spent) & ( bch.spent), .N]
|
||||
|
||||
|
||||
spent.status.by.day$value.btc.spent.bch.spent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ ( btc.spent) & ( bch.spent), sum(value, na.rm = TRUE)]
|
||||
|
||||
spent.status.by.day$outputs.btc.spent.bch.spent[spent.status.by.day$block_time.date == day.i] <-
|
||||
spent.status[ ( btc.spent) & ( bch.spent), .N]
|
||||
|
||||
cat(base::date(), which(spent.status.by.day$block_time.date == day.i),
|
||||
"of", nrow(spent.status.by.day),"\n")
|
||||
|
||||
}
|
||||
# Fairly inefficient implementation, but gets the job done
|
||||
|
||||
|
||||
|
||||
## Data validity check below
|
||||
|
||||
value.row.sum.check <- rowSums(spent.status.by.day[, .(
|
||||
value.btc.unspent.bch.unspent, value.btc.spent.bch.unspent,
|
||||
value.btc.unspent.bch.spent, value.btc.spent.bch.spent)
|
||||
])
|
||||
|
||||
stopifnot(max(value.row.sum.check) - min(value.row.sum.check) < 0.000001)
|
||||
# Some small error allowed for floating point arithmetic inaccuracy
|
||||
|
||||
outputs.row.sum.check <- rowSums(spent.status.by.day[, .(
|
||||
outputs.btc.unspent.bch.unspent, outputs.btc.spent.bch.unspent,
|
||||
outputs.btc.unspent.bch.spent, outputs.btc.spent.bch.spent)
|
||||
])
|
||||
|
||||
stopifnot(max(outputs.row.sum.check) - min(outputs.row.sum.check) == 0)
|
||||
|
||||
|
||||
saveRDS(spent.status.by.day, file = paste0(bch.data.dir, "spent_status_by_day.rds"))
|
||||
saveRDS(trans.matrix.prep, file = paste0(bch.data.dir, "trans_matrix_prep.rds"))
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,14 +1,107 @@
|
|||
|
||||
library(data.table)
|
||||
library(ggplot2)
|
||||
library(scales)
|
||||
library(Cairo)
|
||||
# NOTE: Also need lubridate package installed, but not loading it due to
|
||||
# it masking functions
|
||||
|
||||
|
||||
spent.status.by.date <- spent.status.by.date[ ! is.na(block_time.date), ]
|
||||
|
||||
spent.status.by.date.reshaped <- melt(spent.status.by.date, id.vars = c("block_time.date"),
|
||||
measure.vars = c("perc.value.cumsum", "unspent.perc.value.cumsum"))
|
||||
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"))]
|
||||
|
||||
|
||||
|
||||
|
||||
trans.matrix.prep.value.reshaped <- melt(trans.matrix.prep[,
|
||||
.(block_time.date, value.uu.to.su, value.uu.to.us, value.uu.to.ss,
|
||||
value.su.to.ss, value.us.to.ss)], id.vars = c("block_time.date"),
|
||||
measure.vars = c("value.uu.to.su", "value.uu.to.us", "value.uu.to.ss",
|
||||
"value.su.to.ss", "value.us.to.ss"))
|
||||
|
||||
|
||||
trans.matrix.prep.value.reshaped[, block_time.date := as.POSIXct(block_time.date)]
|
||||
trans.matrix.prep.value.reshaped[, variable :=
|
||||
factor(variable, levels = c("value.uu.to.su", "value.uu.to.us", "value.uu.to.ss",
|
||||
"value.su.to.ss", "value.us.to.ss"))]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
trans.matrix.prep.outputs.reshaped <- melt(trans.matrix.prep[,
|
||||
.(block_time.date, outputs.uu.to.su, outputs.uu.to.us, outputs.uu.to.ss,
|
||||
outputs.su.to.ss, outputs.us.to.ss)], id.vars = c("block_time.date"),
|
||||
measure.vars = c("outputs.uu.to.su", "outputs.uu.to.us", "outputs.uu.to.ss",
|
||||
"outputs.su.to.ss", "outputs.us.to.ss"))
|
||||
|
||||
|
||||
trans.matrix.prep.outputs.reshaped[, block_time.date := as.POSIXct(block_time.date)]
|
||||
trans.matrix.prep.outputs.reshaped[, variable :=
|
||||
factor(variable, levels = c("outputs.uu.to.su", "outputs.uu.to.us", "outputs.uu.to.ss",
|
||||
"outputs.su.to.ss", "outputs.us.to.ss"))]
|
||||
|
||||
|
||||
|
||||
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")
|
||||
|
||||
|
||||
|
||||
c_trans <- function(a, b, breaks = b$breaks, format = b$format) {
|
||||
|
@ -26,36 +119,160 @@ c_trans <- function(a, b, breaks = b$breaks, format = b$format) {
|
|||
|
||||
rev_date <- c_trans("reverse", "time")
|
||||
|
||||
spent.status.by.date.reshaped[, block_time.date := as.POSIXct(block_time.date)]
|
||||
spent.status.by.date.reshaped[, variable :=
|
||||
factor(variable, levels = c("perc.value.cumsum", "unspent.perc.value.cumsum"))]
|
||||
|
||||
# #FF9900 BTC color
|
||||
# https://gist.github.com/paladini/ef383fce1b782d919898
|
||||
# #0AC18E BCH color
|
||||
# https://bitcoincashstandards.org/
|
||||
|
||||
png(paste0(bch.data.dir, "preliminary-pre-fork-BCH-spent-status.png"), width = 800, height = 2000)
|
||||
png(paste0(bch.data.dir, "preliminary-pre-fork-BTC-BCH-spent-status-by-value.png"), width = 800, height = 2000)
|
||||
|
||||
print(
|
||||
ggplot(spent.status.by.date.reshaped, aes(x = block_time.date, y=value, fill=variable)) +
|
||||
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") +
|
||||
geom_area(alpha = 0.6 , size = 0, colour = "black") + coord_flip() +
|
||||
scale_x_continuous(trans = rev_date) +
|
||||
scale_fill_manual(values = c("#0AC18E", "purple"), breaks = rev(c("perc.value.cumsum", "unspent.perc.value.cumsum"))) +
|
||||
ylab("\t\t\t\t\t\tPercent github.com/Rucknium") +
|
||||
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") +
|
||||
theme(legend.position = "top", axis.title.y = element_blank(),
|
||||
plot.title = element_text(size = 27),
|
||||
axis.text = element_text(size = 20), axis.title.x = element_text(size = 20),
|
||||
legend.title = element_blank(), legend.text = element_text(size = 15)) +
|
||||
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 = 25), colour = "white", size = 7.5) +
|
||||
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) +
|
||||
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 = 25), colour = "white", size = 7.5) +
|
||||
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) +
|
||||
geom_vline(xintercept = as.POSIXct("2018-11-15"), linetype = 3) +
|
||||
geom_text(aes(x = as.POSIXct("2018-11-15"), label = "BSV Hard Fork", y = 12), colour = "white", size = 7.5) +
|
||||
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) +
|
||||
geom_vline(xintercept = as.POSIXct("2020-11-15"), linetype = 3) +
|
||||
geom_text(aes(x = as.POSIXct("2020-11-15"), label = "BCHABC Hard Fork", y = 15), colour = "white", size = 7.5)
|
||||
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)
|
||||
)
|
||||
# https://en.wikipedia.org/wiki/List_of_bitcoin_forks
|
||||
# expand = c(0, 0) due to:
|
||||
# https://stackoverflow.com/questions/48611719/remove-inner-padding-in-ggplot
|
||||
dev.off()
|
||||
|
||||
|
||||
|
||||
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,
|
||||
variable = factor("value.us.to.ss", levels = levels(trans.matrix.prep.value.reshaped$variable)))
|
||||
# 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(
|
||||
ggplot(trans.matrix.prep.value.reshaped, aes(x = block_time.date, y = value, fill = variable)) +
|
||||
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 =
|
||||
c(value.uu.to.su = "FF to TF", value.uu.to.us = "FF to FT", value.uu.to.ss = "FF to TT",
|
||||
value.su.to.ss = "TF to TT", value.us.to.ss = "FT to TT" ))) +
|
||||
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,
|
||||
variable = factor("outputs.us.to.ss", levels = levels(trans.matrix.prep.outputs.reshaped$variable)))
|
||||
|
||||
png(paste0(bch.data.dir, "preliminary-pre-fork-BTC-BCH-trans-matrix-by-outputs.png"), width = 800, height = 2000)
|
||||
|
||||
print(
|
||||
ggplot(trans.matrix.prep.outputs.reshaped, aes(x = block_time.date, y = value, fill = variable)) +
|
||||
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 =
|
||||
c(outputs.uu.to.su = "FF to TF", outputs.uu.to.us = "FF to FT", outputs.uu.to.ss = "FF to TT",
|
||||
outputs.su.to.ss = "TF to TT", outputs.us.to.ss = "FT to TT" ))) +
|
||||
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()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ bitcoin.conf.file <- ""
|
|||
data.dir <- ""
|
||||
# Input data directory here, with trailing "/"
|
||||
|
||||
bch.config <- rbch::conrpc(bitcoin.conf.file)
|
||||
bitcoin.config <- rbch::conrpc(bitcoin.conf.file)
|
||||
|
||||
initial.fork.height <- 478558 - 1
|
||||
|
||||
|
@ -23,8 +23,8 @@ for (iter.block.height in initial.fork.height:current.block.height) {
|
|||
cat(iter.block.height, base::date(), "\n")
|
||||
}
|
||||
|
||||
block.hash <- rbch::getblockhash(bch.config, iter.block.height)
|
||||
block.data <- rbch::getblock(bch.config, blockhash = block.hash@result, verbosity = "l1")
|
||||
block.hash <- rbch::getblockhash(bitcoin.config, iter.block.height)
|
||||
block.data <- rbch::getblock(bitcoin.config, blockhash = block.hash@result, verbosity = "l1")
|
||||
block.times[[iter.block.height - initial.fork.height + 1]] <-
|
||||
data.frame(block_height = iter.block.height, block_time = block.data@result$time)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue