1

I have some price data (in the end of this question) and I am trying to plot the geom_candlestick chart using the following:

library(scales)
library(ggplot2)
library(tidyquant)

rects <- data.frame(xstart = as.POSIXct(c("2019-01-24 21:40:00", "2019-01-24 23:15:00"), tz="CST"),
                    xend = as.POSIXct(c("2019-01-24 22:10:00", "2019-01-24 21:45:00"), tz="CST"),
                    col = c('in_period', 'out_period'))

ggplot(df, aes(x = date)) +
  geom_candlestick(aes(open = open, high = high, low = low, close = close), alpha=0.7) +
  geom_rect(data = rects, aes(xmin = as.Date(xstart), xmax = as.Date(xend), ymin = -Inf, ymax = Inf, fill = col),
            alpha = 0.1, inherit.aes = FALSE) +
  scale_x_datetime(labels = date_format("%H:%M:%S"))

The expected effect of plot will be similar to the figure below (which means based on time is in or out period, we set different background colours), but I get an error I didn't understand where it comes from since I have convert it to as.POSIXct or as.Date.

Someone could help to deal with this issue? Thanks.

Error: Invalid input: time_trans works with objects of class POSIXct only

enter image description here

Data:

df <- structure(list(date = structure(c(1548342900, 1548342600, 1548342300, 
1548342000, 1548341700, 1548341400, 1548341100, 1548340800, 1548340500, 
1548340200, 1548339900, 1548339600, 1548339300, 1548339000, 1548338700, 
1548338400, 1548338100, 1548337800, 1548337500, 1548337200), class = c("POSIXct", 
"POSIXt"), tzone = ""), low = c(101.95, 102.1, 102.28, 102.29, 
102.31, 102.33, 102.33, 102.34, 102.34, 102.5, 102.59, 102.51, 
102.51, 102.5, 102.6, 102.59, 102.68, 102.67, 102.71, 102.8), 
    high = c(102.11, 102.29, 102.36, 102.34, 102.4, 102.35, 102.43, 
    102.42, 102.51, 102.61, 102.68, 102.59, 102.57, 102.67, 102.7, 
    102.7, 102.69, 102.83, 102.91, 102.95), open = c(102.11, 
    102.29, 102.29, 102.32, 102.34, 102.34, 102.34, 102.34, 102.51, 
    102.61, 102.59, 102.51, 102.57, 102.67, 102.7, 102.67, 102.68, 
    102.83, 102.86, 102.82), close = c(101.96, 102.1, 102.29, 
    102.32, 102.32, 102.34, 102.34, 102.34, 102.34, 102.5, 102.68, 
    102.59, 102.51, 102.5, 102.66, 102.7, 102.69, 102.73, 102.83, 
    102.9), volume = c(68.47, 55.24, 12.54, 128.77, 86.44, 45.84, 
    47.4, 31.97, 61.93, 31.02, 4.85, 33.49, 3.01, 180.48, 43.45, 
    61.53, 17.27, 34.86, 47.1, 14.61)), row.names = c(NA, -20L
), class = c("tbl_df", "tbl", "data.frame"))

EDIT:

Running output from @Marco_CH's code:

Warning messages:
1: In strptime(xx, f, tz = tz) : unknown timezone 'CST'
2: In as.POSIXct.POSIXlt(x) : unknown timezone 'CST'
3: In strptime(x, f, tz = tz) : unknown timezone 'CST'
4: In as.POSIXct.POSIXlt(as.POSIXlt(x, tz, ...), tz, ...) :
  unknown timezone 'CST'
5: In strptime(xx, f, tz = tz) : unknown timezone 'CST'
6: In as.POSIXct.POSIXlt(x) : unknown timezone 'CST'
7: In strptime(x, f, tz = tz) : unknown timezone 'CST'
8: In as.POSIXct.POSIXlt(as.POSIXlt(x, tz, ...), tz, ...) :
  unknown timezone 'CST'
ah bon
  • 9,293
  • 12
  • 65
  • 148

2 Answers2

3

Try this: See here https://www.r-bloggers.com/2011/11/doing-away-with-%E2%80%9Cunknown-timezone%E2%80%9D-warnings/

library(scales)
library(ggplot2)
library(tidyquant)


Sys.getenv("TZ")
Sys.setenv(TZ="Europe/Berlin")
Sys.getenv("TZ")
#as.POSIXct(t, tz=getOption("tz"))


rects <- data.frame(xstart = as.POSIXct(c("2019-01-24 21:40:00", "2019-01-24 23:15:00")),
                    xend = as.POSIXct(c("2019-01-24 22:10:00", "2019-01-24 21:45:00")),
                    col = c('in_period', 'out_period'))


rects1 <- rects %>% 
  mutate(across(starts_with("x"), ~as.POSIXct(., tz=getOption("tz"))))

ggplot(df, aes(x = date)) +
  geom_candlestick(aes(open = open, high = high, low = low, close = close), alpha=0.7) +
  geom_rect(data = rects1, aes(xmin = xstart, xmax = xend, ymin = -Inf, ymax = Inf, fill = col),
            alpha = 0.1, inherit.aes = FALSE) +
  scale_x_datetime(labels = date_format("%H:%M:%S"))

enter image description here

TarJae
  • 72,363
  • 6
  • 19
  • 66
  • Thanks, do you know how to hide red and darkblue from legend? Or maybe I should ask another question. – ah bon Dec 29 '21 at 10:02
2

Update:

Now without warnings (check if TZ is correct, "CST" doesn't work) and with only needed items in legend.

df <- structure(list(date = structure(c(1548342900, 1548342600, 1548342300, 
                                        1548342000, 1548341700, 1548341400, 1548341100, 1548340800, 1548340500, 
                                        1548340200, 1548339900, 1548339600, 1548339300, 1548339000, 1548338700, 
                                        1548338400, 1548338100, 1548337800, 1548337500, 1548337200), class = c("POSIXct", 
                                                                                                               "POSIXt"), tz = "CST6CDT"), low = c(101.95, 102.1, 102.28, 102.29, 
                                                                                                                                               102.31, 102.33, 102.33, 102.34, 102.34, 102.5, 102.59, 102.51, 
                                                                                                                                               102.51, 102.5, 102.6, 102.59, 102.68, 102.67, 102.71, 102.8), 
                     high = c(102.11, 102.29, 102.36, 102.34, 102.4, 102.35, 102.43, 
                              102.42, 102.51, 102.61, 102.68, 102.59, 102.57, 102.67, 102.7, 
                              102.7, 102.69, 102.83, 102.91, 102.95), open = c(102.11, 
                                                                               102.29, 102.29, 102.32, 102.34, 102.34, 102.34, 102.34, 102.51, 
                                                                               102.61, 102.59, 102.51, 102.57, 102.67, 102.7, 102.67, 102.68, 
                                                                               102.83, 102.86, 102.82), close = c(101.96, 102.1, 102.29, 
                                                                                                                  102.32, 102.32, 102.34, 102.34, 102.34, 102.34, 102.5, 102.68, 
                                                                                                                  102.59, 102.51, 102.5, 102.66, 102.7, 102.69, 102.73, 102.83, 
                                                                                                                  102.9), volume = c(68.47, 55.24, 12.54, 128.77, 86.44, 45.84, 
                                                                                                                                     47.4, 31.97, 61.93, 31.02, 4.85, 33.49, 3.01, 180.48, 43.45, 
                                                                                                                                     61.53, 17.27, 34.86, 47.1, 14.61)), row.names = c(NA, -20L
                                                                                                                                     ), class = c("tbl_df", "tbl", "data.frame"))
library(scales)
library(ggplot2)
library(tidyquant)
library(lubridate)

rects <- data.frame(xstart = as.POSIXct(c("2019-01-24 21:40:00", "2019-01-24 23:15:00"), tz = "CST6CDT"),
                    xend = as.POSIXct(c("2019-01-24 22:10:00", "2019-01-24 21:45:00"), tz="CST6CDT"),
                    col = c('in_period', 'out_period'))

ggplot(df, aes(x = date)) +
  geom_candlestick(aes(open = open, high = high, low = low, close = close), alpha=0.7) +
  geom_rect(data = rects, aes(xmin = floor_date(xstart, "day"), xmax = xend, ymin = -Inf, ymax = Inf, fill=col),
            alpha = 0.1, inherit.aes = FALSE) +
  scale_x_datetime(labels = date_format("%H:%M:%S")) + 
  scale_fill_discrete(name = "Period", label = c('in_period', 'out_period'), limits = c('in_period', 'out_period'))

Output:

enter image description here

PS: If you don't need the part with floor_date, just change floor_date(xstart, "day") to xstart.

Marco_CH
  • 3,243
  • 8
  • 25
  • Thanks, do you know how to hide red and darkblue from legend? – ah bon Dec 29 '21 at 10:01
  • I get warnings while running your new code, I pasted in the end part of question. – ah bon Dec 29 '21 at 10:07
  • 1
    I just updated my post. Now without warnings and only the required items in legend. – Marco_CH Dec 29 '21 at 10:21
  • As I add `scale_fill_discrete()`, the color of geom_candlestick also changed, any ideas to prevent this? – ah bon Dec 29 '21 at 10:33
  • 1
    In my case it didn't change. It was still blue and red as before. maybe it's good to start a separate thread for this, as this has nothing to do with the posixct issue :-) – Marco_CH Dec 29 '21 at 10:43
  • 1
    Regarding this issue, I raise a new question here: https://stackoverflow.com/questions/70522654/how-to-avoid-scale-fill-discrete-changed-the-bars-colors-of-geom-candlestick, please check. – ah bon Dec 29 '21 at 17:07