Intro Thoughts

Status Quo

library(tidyverse)

compute_group_wax <- function(data, scales){
  
  data |>
    mutate(xmin = x,
           y = open, 
           yend = close) %>% 
    mutate(loss_gain =  
             ifelse(close > open, "gain", "loss") |> 
             factor(levels = c("loss", "gain")))
  
}

compute_group_wick <- function(data, scales){
  
  data |>
    mutate(xend = x, 
           y = high, 
           yend = low) %>% 
    mutate(loss_gain = 
             ifelse(close > open, "gain", "loss") |> 
             factor(levels = c("loss", "gain")))
  
}


stock_data <- read_csv("https://raw.githubusercontent.com/business-science/tidyquant/ae5a6ee60f58fd2fa0e4b811682601bcc5d96b0b/data-raw/FANG.csv") 
## Rows: 4032 Columns: 8
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (1): symbol
## dbl  (6): open, high, low, close, volume, adjusted
## date (1): date
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(stock_data)
## # A tibble: 6 × 8
##   symbol date        open  high   low close    volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
## 1 FB     2013-01-02  27.4  28.2  27.4  28    69846400     28  
## 2 FB     2013-01-03  27.9  28.5  27.6  27.8  63140600     27.8
## 3 FB     2013-01-04  28.0  28.9  27.8  28.8  72715400     28.8
## 4 FB     2013-01-07  28.7  29.8  28.6  29.4  83781800     29.4
## 5 FB     2013-01-08  29.5  29.6  28.9  29.1  45871300     29.1
## 6 FB     2013-01-09  29.7  30.6  29.5  30.6 104787700     30.6
library(statexpress)

stock_data %>% 
  slice(1:30) ->
to_plot

to_plot %>% 
  ggplot() + 
  aes(x = date,
      open = open,
      close = close,
      high = high,
      low = low) + 
  # geom_wax sketch
  qlayer(stat = qstat(compute_group_wax,
                      default_aes = aes(color = after_stat(loss_gain))),
         geom = qproto_update(GeomSegment, aes(linewidth = 3))) +
  # geom_wick sketch
  qlayer(stat = qstat(compute_group_wick,
                      default_aes = aes(color = after_stat(loss_gain))),
         geom = GeomSegment)

to_plot %>% 
  ggplot() + 
  aes(x = date,
      open = open,
      close = close,
      high = high,
      low = low) + 
  tidyquant::geom_candlestick()
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo

tidyquant::geom_candlestick
## function (mapping = NULL, data = NULL, stat = "identity", position = "identity", 
##     na.rm = TRUE, show.legend = NA, inherit.aes = TRUE, colour_up = "darkblue", 
##     colour_down = "red", fill_up = "darkblue", fill_down = "red", 
##     ...) 
## {
##     linerange <- ggplot2::layer(stat = StatLinerangeBC, geom = GeomLinerangeBC, 
##         data = data, mapping = mapping, position = position, 
##         show.legend = show.legend, inherit.aes = inherit.aes, 
##         params = list(na.rm = na.rm, fill_up = fill_up, fill_down = fill_down, 
##             colour_up = colour_up, colour_down = colour_down, 
##             ...))
##     rect <- ggplot2::layer(stat = StatRectCS, geom = GeomRectCS, 
##         data = data, mapping = mapping, position = position, 
##         show.legend = show.legend, inherit.aes = inherit.aes, 
##         params = list(na.rm = na.rm, fill_up = fill_up, fill_down = fill_down, 
##             colour_up = colour_up, colour_down = colour_down, 
##             ...))
##     list(linerange, rect)
## }
## <bytecode: 0x7fc6775606b0>
## <environment: namespace:tidyquant>
stock_data %>% 
  slice(1:200) %>% 
  ggplot() + 
  aes(x = date,
      open = open,
      close = close,
      high = high,
      low = low) + 
  tidyquant::geom_candlestick()

Experiment

Closing remarks, Other Relevant Work, Caveats