Stock candlestick drawing issues with geom_boxplot (R)

廉价感情. 提交于 2019-12-06 03:08:33

问题


I am using geom_boxplot to draw candlesticks using stock market data. The problem is that the individual boxplot's upper and lower edges as well as the upper whisker end point show up way higher on the y-axis than their corresponding values. The relative height (difference between upper and lower edges) and the end point of the lower whisker of each boxplot are fine though. Here's my code :

candlestickPlot <- function(x){

library("ggplot2")

# x is a data.frame with columns 'date','open','high','low','close'
x$candleLower <- pmin(x$open, x$close)
x$candleUpper <- pmax(x$open, x$close)
x$candleMiddle <- NA
x$fill <- "red"
x$fill[x$open < x$close] = "green"

# Draw the candlesticks
g <- ggplot(x, aes(x=date, lower=candleLower, middle=candleMiddle, upper=candleUpper, ymin=low, ymax=high)) 
g <- g + geom_boxplot(stat='identity', aes(group=date, fill=fill))
g 
}

Here's x :

    date     close volume  open  high   low
5 2013-12-30 25.82 3525026 27.30 27.76  25.7
4 2013-12-31 27.41 5487204 25.25 27.70 25.25
3 2014-01-02 30.70 7835374 29.25 31.24 29.21
2 2014-01-03 30.12 4577278 31.49 31.80 30.08
1 2014-01-06 30.65 4042724 30.89 31.88 30.37

Am I doing something wrong here?


回答1:


There are more efficient ways to create OHLC candlesticks with ggplot2 than the way you have described using geom_boxplot. Your code seems very similar to the example in the link: http://www.perdomocore.com/2012/using-ggplot-to-make-candlestick-charts-alpha/

It seems many people are putting ggplot candlestick examples on the net that are based on the example in that link using geom_boxplot. But the problem with plotting with geom_boxplot is that the plotting itself gets slow at producing plots as the number of bars plotted increases.

Here is one computationally faster solution for plotting financial data using candlesticks/OHLC bars:

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])
FOSL$flat_bar <- FOSL[, "High"] == FOSL[, "Low"]

# Candle chart:
pl <- ggplot(FOSL, aes(x=Date))+
  geom_linerange(aes(ymin=Low, ymax=High)) +
  theme_bw() +
  labs(title="FOSL") +
  geom_rect(aes(xmin = Date - width/2 * 0.9, xmax = Date + width/2 * 0.9, ymin = pmin(Open, Close), ymax = pmax(Open, Close), fill = chg)) + guides(fill = FALSE, colour = FALSE) + scale_fill_manual(values = c("dn" = "darkred", "up" = "darkgreen"))

# Handle special case of drawing a flat bar where OHLC = Open:
if (any(FOSL$flat_bar)) pl <- pl + geom_segment(data = FOSL[FOSL$flat_bar,], aes(x = Date - width / 2 * 0.9, y = Close, yend = Close, xend = Date + width / 2 * 0.9))

print(pl)




回答2:


Thank you FXQuantTrader for introducing a beautiful and fast alternative approach to the candlestick bars in R! Awesome, concise, easy to read! Here comes a bit improved version of FXQuantTrader's solution, which include:
  - wraps it into a function
  - supports lower resolution (down to 1 sec bars)
  - changes candle's whiskers colour from black to proper one
  - adds small horizontal line for bars with Close == Open
  - adds 3rd colour (blue) to bars with Close == Open
  - adds 'alpha' argument which allows you to make the whole candlesticks chart more transparent, so when you draw on top some Bollinger Bands and/or Moving Averages the bars will be less distracting (more like a background)
- a bit more comments for newbies to figure out what is going on :)

Here she comes:

library(ggplot2)
library(quantmod)
draw_candles <- function(df, title_param, alpha_param = 1){
  df$change <- ifelse(df$Close > df$Open, "up", ifelse(df$Close < df$Open, "down", "flat"))

  # originally the width of the bars was calculated by FXQuantTrader with use of 'periodicity()', which 
  # seems to work ok only with: ‘minute’,‘hourly’, ‘daily’,‘weekly’, ‘monthly’,
  # ‘quarterly’, and ‘yearly’, but can not do 1 sec bars while we want arbitrary bar size support!-)
  # df$width <- as.numeric(periodicity(df)[1])
  # So let us instead find delta (seconds) between 1st and 2nd row and just 
  # use it for all other rows. We check 1st 3 rows to avoid larger "weekend gaps"
  width_candidates <- c(as.numeric(difftime(df$Date[2], df$Date[1]), units = "secs"), 
                        as.numeric(difftime(df$Date[3], df$Date[2]), units = "secs"), 
                        as.numeric(difftime(df$Date[4], df$Date[3]), units = "secs"))

  df$width_s = min(width_candidates)  # one (same) candle width (in seconds) for all the bars

  # define the vector of candle colours either by name or by rgb()
  #candle_colors = c("down" = "red", "up" = "green", "flat" = "blue")
  candle_colors = c("down" = rgb(192,0,0,alpha=255,maxColorValue=255), "up" = rgb(0,192,0,alpha=255,maxColorValue=255), "flat" = rgb(0,0,192,alpha=255,maxColorValue=255))

  # Candle chart:
  g <- ggplot(df, aes(x=Date))+
    geom_linerange(aes(ymin=Low, ymax=High, colour = change), alpha = alpha_param) +  # candle whiskerss (vertical thin lines:)
    theme_bw() +
    labs(title=title_param) +
    geom_rect(aes(xmin = Date - width_s/2 * 0.9, xmax = Date + width_s/2 * 0.9, ymin = pmin(Open, Close), ymax = pmax(Open, Close), fill = change), alpha = alpha_param) +                            # cabdke body
    guides(fill = FALSE, colour = FALSE) +
    scale_color_manual(values = candle_colors) +  # color for line
    scale_fill_manual(values = candle_colors)     # color for candle fill  

    # Handle special cases: flat bar and Open == close:
    if (any(df$change == "flat")) g <- g + geom_segment(data = df[df$change == "flat",], aes(x = Date - width_s / 2 * 0.9, y = Close, yend = Close, xend = Date + width_s / 2 * 0.9, colour = change), alpha = alpha_param)

  #print(g)
  g
}



回答3:


Could not completely understand your problem but this seems to work nicely:

http://www.perdomocore.com/2012/using-ggplot-to-make-candlestick-charts-alpha/




回答4:


I created a package generating candlestick chart with the possibility of further extension.

https://github.com/dominikduda/candlePlotter

From help:

Plots OHLC chart

(...)

Arguments:

time_series: A data frame with c('Time', 'Open', 'High', 'Low', 'Close') columns where Time column must be of POSIXct type.

chart_title: An optional string with main chart title

under_candles_layers: A vector of ggplot layers to print under candles

Working example how to use:

 # Plotting a chart and saving it from a string:

 raw_data <- "
 Time Open High Low Close
 2018-08-30 7050.267 7068.232 6740.648 6985.976
 2018-08-31 6982.225 7075.417 6915.935 7046.783
 2018-09-01 7040.911 7257.571 7030.790 7193.122
 2018-09-02 7203.630 7314.289 7136.561 7277.199
 2018-09-03 7286.205 7334.481 7201.419 7255.241
 2018-09-04 7269.067 7394.179 7251.269 7364.443
 2018-09-05 7365.232 7391.967 6704.715 6704.715
 2018-09-06 6715.508 6715.508 6365.000 6503.564
 2018-09-07 6514.690 6544.672 6378.351 6446.210
 2018-09-08 6426.220 6485.850 6147.691 6203.588
 2018-09-09 6202.271 6417.675 6178.907 6260.216
 2018-09-10 6270.848 6351.214 6263.048 6317.647
 2018-09-11 6320.536 6391.365 6241.453 6289.961
 2018-09-12 6296.140 6349.481 6238.578 6339.010
 2018-09-13 6345.973 6525.523 6337.746 6498.652
 2018-09-14 6488.631 6583.669 6428.993 6492.367
 2018-09-15 6488.870 6561.979 6480.306 6524.671"
 data_for_chart <- read.table(text = raw_data, header = TRUE)
 data_for_chart <- transform(data_for_chart, Time = as.POSIXct(Time))
 plot <- prettyCandlePlot(data_for_chart, 'BTCUSD')

 ggsave(
   'btc_usd_daily.png',
   plot = plot,
   width = 30,
   height = 18,
   units = 'cm'
 )


来源:https://stackoverflow.com/questions/21045866/stock-candlestick-drawing-issues-with-geom-boxplot-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!