Search code examples
rr-highcharter

Colors for volume indicators


enter image description hereI am trying to generate the volume indicators with color. Red when the close is less than open and Green when Close is higher than open. I am able to get the colors in candlestick but not in the volume section.

library(quantmod)
library(tidyverse)
library(highcharter)
aapl <- quantmod::getSymbols("AAPL",
                             src = "yahoo",
                             from = "2020-01-01",
                             auto.assign = FALSE
    )
# Plot prices and volume with relative height.
highchart(type = "stock") %>%
    hc_title(text = "AAPLE") %>%
    hc_add_series(aapl, yAxis = 0, showInLegend = FALSE) %>%
    hc_add_yAxis(nid = 1L, title = list(text = "Prices"), relative = 2) %>%
    hc_add_series(aapl[, "AAPL.Volume"], yAxis = 1, type = "column", showInLegend = FALSE) %>% hc_add_yAxis(nid = 2L, title = list(text = "Volume"), relative = 1)%>% hc_plotOptions(
        candlestick=list(color= 'pink',
                         lineColor= 'red',
                         upColor= 'lightgreen',
                         upLineColor= 'green',
                         downColor = 'red',
                         downLineColor='red'))

Solution

  • Unfortunately such functionality is not available in Highcharts API. Still we can define the colors for each volume point seperately depending on the candlestick close/open values. A basic JS demo for reference: https://jsfiddle.net/BlackLabel/tm5k7pgj/

    And the solution in R:

    library(highcharter)
    
    data <- data.frame(
      Date = as.Date('2023-01-01') + 0:4,
      Open = c(100, 105, 102, 108, 110),
      High = c(110, 107, 108, 112, 115),
      Low = c(95, 100, 99, 105, 107),
      Close = c(105, 102, 108, 100, 113),
      Volume = c(1000, 1500, 1200, 1300, 1600)
    )
    
    hc_data <- lapply(1:nrow(data), function(i) {
      list(
        as.numeric(as.POSIXct(data$Date[i])) * 1000,
        data$Open[i],
        data$High[i],
        data$Low[i],
        data$Close[i]
      )
    })
    
    hc_volume <- lapply(1:nrow(data), function(i) {
      list(
        x = as.numeric(as.POSIXct(data$Date[i])) * 1000,
        y = data$Volume[i],
        color = ifelse(data$Close[i] > data$Open[i], 'green', 'red')    
      )
    })
    
    hchart <- highchart(type = "stock") %>%
      hc_title(text = "Candlestick and Volume Chart") %>%
      hc_yAxis_multiples(
        list(title = list(text = "OHLC"), height = "60%", lineWidth = 2),
        list(title = list(text = "Volume"), top = "65%", height = "35%", offset = 0, lineWidth = 2)
      ) %>%
      hc_add_series(type = "candlestick", name = "AAPL", data = hc_data) %>%
      hc_add_series(type = "column", name = "Volume", data = hc_volume, yAxis = 1)%>%
      hc_plotOptions(candlestick = list(color = 'red', upColor = 'green', lineColor = 'red', upLineColor = 'green'))  
    
    
    print(hchart)
    

    In JS the core function looks like that:

    const volumeData = data.map((item, index) => {
     const volume = item[5];
     const open = item[1];
     const close = item[4];
     const color = close > open ? 'green' : 'red';
     return {
      x: item[0],
      y: volume,
      color: color
    }
    });