library(ggplot2)
library(quantmod)
FOSL <- getSymbols("FOSL", from="2015-01-01", auto.assign=FALSE)
names(FOSL) <- gsub("^.+\\.","",names(FOSL)) # remove "FOSL." from column names
rng <- "2015-08"
FOSL <- FOSL[rng]
FOSL <- data.frame(Date=as.POSIXct(index(FOSL)), FOSL[,1:4])
FOSL$chg <- ifelse(Cl(FOSL) > Op(FOSL), "up", "dn")
FOSL$width <- as.numeric(periodicity(FOSL)[1])
# Bar chart:
ggplot(data=FOSL, aes(x=Date, colour = chg)) +
theme_bw() +
geom_linerange(aes(ymin=Low, ymax=High)) +
geom_segment(aes(y = Open, yend = Open, xend = Date - width / 2 )) +
geom_segment(aes(y = Close, yend = Close, xend = Date + width / 2)) +
scale_colour_manual(values = c("dn" = "darkred", "up" = "darkgreen")) + guides(colour = FALSE)

The space on the weekends can't be removed easily for ggplot graphs with x axis scales like scale_x_datetime
. This is because ggplot interprets POSIXct and date data as numbers from an origin on the x-axis
. e.g. as.numeric(as.POSIXct("2015-09-25")) would be the value on the x axis in the ggplot. For "hacks" around this, you can check this SO answer, where dates are treated as factors:
R + ggplot2: how to hide missing dates from x-axis?
**Edit 2016-05, removing weekend gaps from ggplot time series plots **
Here is a working example for drawing ggplot OHLC bars that removes weekends (this function is easy to modify for drawing candles instead of bars example here).
library(ggplot2)
library(quantmod)
library(lubridate)
# prepare data:
md <- getSymbols("FOSL", from="2015-01-01", auto.assign=FALSE)
names(md) <- gsub("^.+\\.","",names(md)) # remove "md." from column names
rng <- "2015-08"
md <- md[rng]
# Use ceiling date to ensure "Date" is rounded to 00:00:00 in POSIXct numeric scale from 1970, not Date scale.
md <- data.frame(Date = ceiling_date(as.POSIXct(index(md)), "day"), md[,1:4])
md$time_idx <- 1:NROW(md)
# Check special case of drawing of flat bars:
md[10, 2:5] <- md[10, 5]
gg_build_candlechart_without_weekends <- function(md, # in data.frame format, with a Date column
x_scale = 0.8, # Controls thickness of bars
width = 1
)
{
stopifnot("Date" %in% colnames(md))
md$chg <- ifelse(Cl(md) > Op(md), "up", "dn")
md$time_idx <- 1:NROW(md)
md$width <- width
pl <- ggplot(md, aes(x = time_idx, colour = chg)) +
geom_linerange(aes(ymin=Low, ymax=High)) +
geom_segment(aes(y = Open, yend = Open, xend = time_idx - width / 2 * x_scale)) +
geom_segment(aes(y = Close, yend = Close, xend = time_idx + width / 2 * x_scale)) +
scale_colour_manual(values = c("dn" = "darkred", "up" = "darkgreen")) + guides(colour = FALSE) + labs(x = "Time", y = "Price")
Nr <- NROW(md)
maj_breaks <- round(Nr * c(0.05, 0.25, 0.5, 0.75, .95))
periodicity <- quantile(diff(as.numeric(md$Date)), 0.5)
if (periodicity < 86400) {
label_timestamp <- "%b %d %H:%M:%S"
} else {
label_timestamp <- "%y' %b %d"
}
pl <- pl + scale_x_continuous(limits = c(0, Nr + 1), expand = c(0, 0), breaks = maj_breaks, labels = format(md$Date[maj_breaks], label_timestamp), minor_breaks = Nr * seq(0.1, 0.9, by = 0.2))
# draw flat bars as special case:
md_flatbars <- md[md$High == md$Low, ]
if (NROW(md_flatbars) > 0) {
pl <- pl + geom_segment(data = md_flatbars, aes(x = time_idx - width / 2 * x_scale, y = Close, yend = Close, xend = time_idx + width / 2 * x_scale))
}
pl
}
gg_build_candlechart_without_weekends(md, x_scale = 0.8, width = 1)
