dc_intervals <- function(dat, threshold=0.02/100, price="price", time="time", vol="amount") {
# candidates for confirmed directional change
dcc_up_cand <- c(FALSE, c(dat[2:nrow(dat), price]dat[1:(nrow(dat)-1), price]*(1+threshold)))
# initialize new columns
dat[,"interval"] <- NA # 4 types of intervals: down, down_os, up, up_os (os=overshoot, NA means unknown)
dat[,"point"] <- NA # 3 types of points: dcc_up, dcc_down, ep (NA means ignore)
# threshold too large?
if(all(!dcc_up_cand)) stop("threshold=",threshold, " too large, no price moves above this threshold")
if(all(!dcc_down_cand)) stop("threshold=",threshold, " too large, no price moves above this threshold")
# figure out if the first change is up or down
first_up <- which.max(dcc_up_cand)
first_down <- which.max(dcc_down_cand)
if(first_up0) { # if not changing direction immediately
ep_idx <- which.min(dat[(i+1):(j-1), price])+i
dat[ep_idx, "point"] <- "ep"
dat[i:ep_idx-1, "interval"] <- "uoi"
dat[ep_idx:j,"interval"] <- "dei"
}
i <- j+1
mode <- "dcc_down"
} else { # mode=="dcc_down"
j <- which.max(dcc_up_cand[i+1:length(dcc_up_cand)])+i
if(!dcc_up_cand[j]) break # end of dataset
dat[i,"point"] <- "dcc_down"
dat[i,"interval"] <- "doi"
if((j-1)-(i+1)>0) { # if not changing direction immediately
ep_idx <- which.max(dat[(i+1):(j-1), price])+i
dat[ep_idx, "point"] <- "ep"
dat[i:ep_idx-1, "interval"] <- "doi"
dat[ep_idx:j,"interval"] <- "uei"
}
i <- j+1
mode <- "dcc_up"
}
}
dat <- dat[!is.na(dat[,"point"]),] # drop all points that are not dcc points
return(dat)
}
ohlc_summary <- function(dat, browse=TRUE, verbose=TRUE) {
dat$hour <- strftime(dat$time, format="%Y-%m-%d %H")
one_hour <- function(dset) {
i1 <- which.min(dset$time)
i2 <- which.max(dset$time)
ans <- data.frame(
time=strptime(dset[1,"hour"], format="%Y-%m-%d %H"),
open=dset[i1, "price"],
hi=max(dset$price),
lo=min(dset$price),
close=dset[i2,"price"],
amount=sum(dset$amount)
)
return(ans)
}
ret <- do.call(rbind, lapply(split(dat, dat$hour), FUN=one_hour))
if(verbose) message("ohlc summary built.")
if(browse) browser()
return(ret)
}
# begin, end ... "YYYY-MM-DD"
plot_dc <- function(dc_dat=NULL, ohlc=NULL, ticks=NULL, begin=NULL, end=NULL, lwd=3, price="price", time="time", vol="amount", ...) {
if(is.null(ohlc) & !is.null(ticks)) ohlc <- ohlc_summary(ticks)
if(is.null(dc_dat) & !is.null(ticks)) dc_dat <- dc_intervals(dat=ticks, time=time, price=price, vol=vol)
if(is.null(dc_dat)) stop("missing dc data.")
if(is.null(end)) end <- max(dc_dat[,time])
if(is.character(end)) end <- as.POSIXct(strptime(end, "%Y-%m-%d"))
if(is.null(begin)) begin <- min(dc_dat[,time])
if(is.character(begin)) begin <- as.POSIXct(strptime(begin, "%Y-%m-%d"))
plot(
dat=1, col="white", dc_dat=dc_dat, xlab="",
xlim=c(min(ohlc$time), max(ohlc$time)), ylim=c(min(ticks$price), max(ticks$price)),
main=sprintf("%.2f%% Direction Changes for BTC", threshold*100),
cex.main=1
)
if(!is.null(ohlc)) {
for (i in seq(1, nrow(ohlc))) {
segments(
x0=ohlc[i,"time"], y0=ohlc[i,"lo"],
x1=ohlc[i,"time"], y0=ohlc[i, "hi"],
col="darkgrey", lwd=0.5
)
}
}
dcc_idx <- which(dc_dat$point=="dcc_up"|dc_dat$point=="dcc_down")
for (i in setdiff(dcc_idx,1)) {
segments(
x0=dc_dat[i-1,time], y0=dc_dat[i-1,price],
x1=dc_dat[i,time], y1=dc_dat[i,price],
col="red", lwd=lwd
)
}
for (i in setdiff(dcc_idx,nrow(dc_dat))) {
segments(
x0=dc_dat[i,time], y0=dc_dat[i,price],
x1=dc_dat[i+1,time], y1=dc_dat[i+1,price],
col="darkgreen", lwd=lwd
)
}
axis(1,at=dc_dat[dcc_idx, time],labels=FALSE)
}