Skip to contents

`stat_macd` is a `ggplot2` layer that allows you to plot a `ggplot2` layer of moving average convergence divergence (macd) by providing the column names `ggplot2::aes` of the previously calculated metrics.

You are free to use whatever algorithm you desire; the result will be a line plot overlayed on a histogram.

To use this layer provide `ggplot2::aes` values for `x` (datetime x-axis) and `macd` (y-axis) and `macd_signal` (y-axis) and `macd_diff` (y-axis).

See examples for more details.

Usage

stat_macd(
  mapping = NULL,
  data = NULL,
  geom = "line",
  position = "identity",
  na.rm = TRUE,
  show.legend = NA,
  inherit.aes = TRUE,
  alpha_lines = 0.75,
  alpha_histogram = 0.5,
  colour_lines = list(macd = "blue", macd_signal = "red"),
  colour_histogram = list(positive = NA_character_, negative = NA_character_),
  fill_histogram = list(positive = "green", negative = "red"),
  ...
)

Arguments

mapping

A `ggplot2::aes` object (required - default `NULL`).

data

A `data.table` object (required - default `NULL`).

alpha_lines

A `numeric` vector of length one; the alpha of the lines (optional - default `0.75`).

alpha_histogram

A `numeric` vector of length one; the alpha of the histogram (optional - default `0.5`).

colour_lines

A named or unnamed `list` of two elements "macd" and "macd_signal" (optional - default `list(macd = "blue", macd_signal = "red")`).

colour_histogram

A named or unnamed `list` of two elements "positive" and "negative" (optional - default `list(positive = NA_character_, negative = NA_character_)`).

fill_histogram

A named or unnamed `list` of two elements "positive" and "negative" (optional - default `list(positive = "green", negative = "red")`).

linewidth

A `numeric` vector of length one; the linewidth of the line (optional - default `1.75`).

Value

A `ggplot2::layer` object.

Details

This is a `ggplot2` extension; it is used with the `+` operator for adding a layer to a `ggplot2` object.

Aesthetics

stat_movingaverages understands the following aesthetics (required aesthetics are in bold):

  • x -- datetime (x-axis)

  • macd -- y-axis

  • macd_signal -- y-axis

  • macd_diff -- y-axis

Author

Dereck Mezquita

Examples


# get some financial data
# kucoin is private package - you can use any data source
ticker <- "BTC/USDT"

dt <- kucoin::get_market_data(
    symbols = ticker,
    from = "2022-11-28 15:29:43 EST", # lubridate::now() - lubridate::days(7),
    to = "2022-12-05 15:29:31 EST",# lubridate::now(),
    frequency = "1 hour"
)

dt
#>        symbol            datetime    open    high     low   close   volume
#>        <char>              <POSc>   <num>   <num>   <num>   <num>    <num>
#>   1: BTC/USDT 2022-11-28 15:00:00 16215.3 16233.6 16126.0 16144.1 327.8979
#>   2: BTC/USDT 2022-11-28 16:00:00 16144.1 16382.6 16000.0 16305.9 837.5801
#>   3: BTC/USDT 2022-11-28 17:00:00 16305.9 16382.0 16195.4 16205.4 507.8351
#>   4: BTC/USDT 2022-11-28 18:00:00 16206.1 16230.7 16146.5 16162.6 252.3387
#>   5: BTC/USDT 2022-11-28 19:00:00 16161.7 16253.3 16150.1 16220.9 225.4121
#>  ---                                                                      
#> 165: BTC/USDT 2022-12-05 11:00:00 17295.2 17314.3 17283.8 17312.0 176.8633
#> 166: BTC/USDT 2022-12-05 12:00:00 17312.0 17318.6 17230.5 17254.5 199.6922
#> 167: BTC/USDT 2022-12-05 13:00:00 17254.5 17282.5 17208.1 17229.7 105.2655
#> 168: BTC/USDT 2022-12-05 14:00:00 17229.8 17241.4 17175.1 17205.2 140.4375
#> 169: BTC/USDT 2022-12-05 15:00:00 17205.1 17205.1 17021.6 17083.0 504.9158
#>      turnover
#>         <num>
#>   1:  5301836
#>   2: 13557348
#>   3:  8270203
#>   4:  4082464
#>   5:  3653147
#>  ---         
#> 165:  3058929
#> 166:  3447960
#> 167:  1815447
#> 168:  2416907
#> 169:  8630174

# we need a function that calculates the indicator for us
# typically I like to write my own functions in C++; in this case we will use TTR's
# the stat expects a named list to be returned - we redefine ttr
macd <- function(x, s = 12, l = 26, k = 9) {as.list(as.data.frame(TTR::MACD(x, s, l, k)))}

# macd(dt$close)
dt[, c("macd", "macd_signal") := macd(close, s = 12, l = 26, k = 9)]
#>        symbol            datetime    open    high     low   close   volume
#>        <char>              <POSc>   <num>   <num>   <num>   <num>    <num>
#>   1: BTC/USDT 2022-11-28 15:00:00 16215.3 16233.6 16126.0 16144.1 327.8979
#>   2: BTC/USDT 2022-11-28 16:00:00 16144.1 16382.6 16000.0 16305.9 837.5801
#>   3: BTC/USDT 2022-11-28 17:00:00 16305.9 16382.0 16195.4 16205.4 507.8351
#>   4: BTC/USDT 2022-11-28 18:00:00 16206.1 16230.7 16146.5 16162.6 252.3387
#>   5: BTC/USDT 2022-11-28 19:00:00 16161.7 16253.3 16150.1 16220.9 225.4121
#>  ---                                                                      
#> 165: BTC/USDT 2022-12-05 11:00:00 17295.2 17314.3 17283.8 17312.0 176.8633
#> 166: BTC/USDT 2022-12-05 12:00:00 17312.0 17318.6 17230.5 17254.5 199.6922
#> 167: BTC/USDT 2022-12-05 13:00:00 17254.5 17282.5 17208.1 17229.7 105.2655
#> 168: BTC/USDT 2022-12-05 14:00:00 17229.8 17241.4 17175.1 17205.2 140.4375
#> 169: BTC/USDT 2022-12-05 15:00:00 17205.1 17205.1 17021.6 17083.0 504.9158
#>      turnover      macd macd_signal
#>         <num>     <num>       <num>
#>   1:  5301836        NA          NA
#>   2: 13557348        NA          NA
#>   3:  8270203        NA          NA
#>   4:  4082464        NA          NA
#>   5:  3653147        NA          NA
#>  ---                               
#> 165:  3058929 0.4731906   0.4505607
#> 166:  3447960 0.4303121   0.4465110
#> 167:  1815447 0.3803542   0.4332796
#> 168:  2416907 0.3255538   0.4117344
#> 169:  8630174 0.2223466   0.3738569
dt[, macd_diff := macd - macd_signal]
#>        symbol            datetime    open    high     low   close   volume
#>        <char>              <POSc>   <num>   <num>   <num>   <num>    <num>
#>   1: BTC/USDT 2022-11-28 15:00:00 16215.3 16233.6 16126.0 16144.1 327.8979
#>   2: BTC/USDT 2022-11-28 16:00:00 16144.1 16382.6 16000.0 16305.9 837.5801
#>   3: BTC/USDT 2022-11-28 17:00:00 16305.9 16382.0 16195.4 16205.4 507.8351
#>   4: BTC/USDT 2022-11-28 18:00:00 16206.1 16230.7 16146.5 16162.6 252.3387
#>   5: BTC/USDT 2022-11-28 19:00:00 16161.7 16253.3 16150.1 16220.9 225.4121
#>  ---                                                                      
#> 165: BTC/USDT 2022-12-05 11:00:00 17295.2 17314.3 17283.8 17312.0 176.8633
#> 166: BTC/USDT 2022-12-05 12:00:00 17312.0 17318.6 17230.5 17254.5 199.6922
#> 167: BTC/USDT 2022-12-05 13:00:00 17254.5 17282.5 17208.1 17229.7 105.2655
#> 168: BTC/USDT 2022-12-05 14:00:00 17229.8 17241.4 17175.1 17205.2 140.4375
#> 169: BTC/USDT 2022-12-05 15:00:00 17205.1 17205.1 17021.6 17083.0 504.9158
#>      turnover      macd macd_signal   macd_diff
#>         <num>     <num>       <num>       <num>
#>   1:  5301836        NA          NA          NA
#>   2: 13557348        NA          NA          NA
#>   3:  8270203        NA          NA          NA
#>   4:  4082464        NA          NA          NA
#>   5:  3653147        NA          NA          NA
#>  ---                                           
#> 165:  3058929 0.4731906   0.4505607  0.02262998
#> 166:  3447960 0.4303121   0.4465110 -0.01619881
#> 167:  1815447 0.3803542   0.4332796 -0.05292542
#> 168:  2416907 0.3255538   0.4117344 -0.08618062
#> 169:  8630174 0.2223466   0.3738569 -0.15151027

na.omit(dt) |>
    ggplot2::ggplot(ggplot2::aes(x = datetime)) +
    dmplot::stat_macd(ggplot2::aes(macd = macd, macd_signal = macd_signal, macd_diff = macd_diff)) +
    ## ------------------------------------
    # provide the colnames to the calculated indicators as aes values
    ## ------------------------------------
    ggplot2::scale_x_continuous(n.breaks = 25, labels = \(x) {
        lubridate::floor_date(lubridate::as_datetime(x), "hours")
    }) +
    ggplot2::scale_y_continuous(n.breaks = 25) +
    ggplot2::labs(
        title = ticker,
        x = "Date",
        y = "Price (USD)"
    ) +
    dmplot::theme_dereck_dark() +
    ggplot2::theme(
        axis.text.x = ggplot2::element_text(angle = 75, vjust = 0.925, hjust = 0.975),
        panel.grid.minor = ggplot2::element_blank()
    )