diff --git a/NAMESPACE b/NAMESPACE index a42f6df04..aac23c2b9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -246,6 +246,11 @@ S3method(three_white_soldiers,data.frame) S3method(three_white_soldiers,default) S3method(three_white_soldiers,matrix) S3method(three_white_soldiers,plotly) +S3method(trading_volume,data.frame) +S3method(trading_volume,default) +S3method(trading_volume,matrix) +S3method(trading_volume,numeric) +S3method(trading_volume,plotly) S3method(two_crows,data.frame) S3method(two_crows,default) S3method(two_crows,matrix) @@ -369,9 +374,11 @@ export(three_line_strike) export(three_outside) export(three_stars_in_the_south) export(three_white_soldiers) +export(trading_volume) export(triangular_moving_average) export(triple_exponential_moving_average) export(two_crows) export(ultimate_oscillator) +export(volume) export(weighted_moving_average) useDynLib(talib, .registration = TRUE) diff --git a/R/chart.R b/R/chart.R index 9199a2632..862d00819 100644 --- a/R/chart.R +++ b/R/chart.R @@ -23,6 +23,8 @@ #' #' @param x An OHLC object to be charted. #' @param type A [character] of [length] 1. Either `candlestick` or `ohlc`. +#' @param idx A [vector] with the same [length] of `x`. If passed it will replace the x-axis labels. See `vignette("charting")` for more details. +#' @param title An optional [character] vector of [length] 1. #' @param ... Parameters passed into [plotly::plot_ly] #' #' @example man/examples/charting.R @@ -31,6 +33,8 @@ chart <- function( x, type = "candlestick", + idx = NULL, + title, ... ) { ## clear env if called @@ -54,6 +58,7 @@ chart.default <- function( x, type = "candlestick", idx = NULL, + title, ... ) { ## default chart function @@ -71,6 +76,15 @@ chart.default <- function( ## 3. chart: The user-facing TA chart. ## This is empty and is constructed on the fly ## via plotly::subplot. + + ## extract title + if (missing(title)) { + chart_title <- input_name( + substitute(x) + ) + } else { + chart_title <- title + } .color_values <- .chart_theme() .plotting_environment$sub <- .plotting_environment$chart <- list() @@ -81,8 +95,27 @@ chart.default <- function( ## NOTE: it is also a hard requirement on ## {plotly} side x <- as.data.frame(x) - x$idx <- if (is.null(idx)) 1:nrow(x) else idx + x$idx <- if (is.null(idx)) { + ## check if rownames can be + ## converted to integer + is_valid <- suppressWarnings( + !is.na(as.integer(rownames(x)[1])) + ) + if (is_valid) { + as.integer( + rownames(x) + ) + } else { + rownames(x) + } + } else { + idx + } .plotting_environment$x <- data_frame <- x + .plotting_environment$idx <- list( + label = x$idx, + index = seq_along(x$idx) + ) ## generate price chart ## based on type. can be either @@ -129,18 +162,50 @@ chart.default <- function( alpha = 1 ## This should be controlled from .chart_theme() ) ), + + ## remove legend + ## there is no reason to display + ## it in the legend. + ## + ## If there is demand for it we can + ## implement a heuristic to determine intervals + ## for 1h, 2h, etc. Similar to {cryptoQuotes} + showlegend = FALSE, ... ) + ## construct chart meta data + ## + ## There is no relevant information in the range 1:N + ## so if the rownames only contrains integers the chart will + ## skip it + if (is.integer(.plotting_environment$idx$label)) { + title_text <- sprintf( + fmt = "Ticker: %s
N: %d ", + chart_title, + nrow(x) + ) + } else { + title_text <- sprintf( + fmt = "Ticker: %s
N: %d Period: %s ", + chart_title, + nrow(x), + paste( + .plotting_environment$idx$label[1], + "-", + .plotting_environment$idx$label[length( + .plotting_environment$idx$label + )] + ) + ) + } + ## store in main chart ## (see description) .plotting_environment$main <- .chart_layout( x = price_chart, - title_text = sprintf( - "Ticker: %s
Period: %s", - deparse(substitute(x)), - "Period Value" - ) + title_text = title_text, + idx = idx ) .plotting_environment$main diff --git a/R/chart_elements.R b/R/chart_elements.R index 83b8ce6a7..051451b27 100644 --- a/R/chart_elements.R +++ b/R/chart_elements.R @@ -1,11 +1,16 @@ -.chart_layout <- function(x, title_text, ...) { +.chart_layout <- function( + x, + title_text, + idx = NULL, + ... +) { ## extract chart theme ## from R/chart_options.R chart_theme <- .chart_theme() ## hardcoded layout elements ## and added flexibility in ellipsis - plotly::layout( + plotly_object <- plotly::layout( p = x, paper_bgcolor = chart_theme$paper_bgcolor, plot_bgcolor = chart_theme$plot_bgcolor, @@ -18,9 +23,11 @@ color = chart_theme$font_color ), yaxis = list( + title = '', gridcolor = chart_theme$grid_color ), xaxis = list( + title = '', gridcolor = chart_theme$grid_color, rangeslider = list( visible = getOption( @@ -31,7 +38,10 @@ "talib.chart.slider.size", default = 0.05 ) - ) + ), + tickvals = seq_along(idx), + tickmode = "auto", + ticktext = idx ), ## legend start @@ -75,6 +85,29 @@ ... ) + + ## add chart configurations + ## for TA + plotly::config( + p = plotly_object, + + ## options for support + ## and resistance lines + modeBarButtonsToAdd = c( + "drawline", + "drawrect", + "eraseshape" + ), + + ## remove {plotly} logo + ## to reduce clutter + ## + ## NOTE: Some of the other + ## buttons is most likely + ## redundant too. These will be + ## removed later (TM) + displaylogo = FALSE + ) } @@ -101,3 +134,187 @@ add_title <- function( ) ) } + +#' @title subchart +#' +#' @details +#' A helper function for creating subcharts with prespecified +#' xaxis and x values +#' +#' @param data [data.frame] +#' @param ... arguments passed onto [plotly::plot_ly] +#' +#' @keywords internal +subchart <- function( + data, + ... +) { + ## main plotly object to + ## be added to the chart + plotly_object <- plotly::plot_ly( + data = data, + x = ~idx, + ... + ) + + ## finalize subcart + plotly_object <- plotly::layout( + plotly_object, + + ## if this part is not added + ## there is mismatch between the + ## main chart and the subscharts + xaxis = list( + tickvals = seq_along(data$idx), + ticktext = data$idx, + ticmode = "auto" + ) + ) + + ## readd configuations + ## + ## NOTE: This is repeated code + ## from .chart_layout() + ## - should be consolidated at + ## some point (TM) + plotly_object <- plotly::config( + p = plotly_object, + + ## options for support + ## and resistance lines + modeBarButtonsToAdd = c( + "drawline", + "drawrect", + "eraseshape" + ), + + ## remove {plotly} logo + ## to reduce clutter + ## + ## NOTE: Some of the other + ## buttons is most likely + ## redundant too. These will be + ## removed later (TM) + displaylogo = FALSE + ) + + return(plotly_object) +} + +add_ribbons <- function( + plotly_object, + data, + x, + y, + ymin, + ymax, + color, + alpha, + showlegend, + legendgroup, + name, + dash +) { + ## this function adds ribbons + ## to existing plots. It addresses the following + ## issue with plotly::add_ribbons: When adding lines it will + ## box on the right, but not on the left. + + ## check if y have been passed + ## and + y_passed <- as.numeric( + !missing(y) + ) + + ## the name can apply to to each + ## line + if (length(name) < 3) { + name <- rep(name, 3) + } + + if (length(dash) < 3) { + dash <- rep(dash, 3) + } + + ## add ribbon without lines + plotly_object <- plotly::add_ribbons( + p = plotly_object, + inherit = FALSE, + data = data, + x = x, + ymin = ymin, + ymax = ymax, + line = list( + color = "transparent" + ), + fillcolor = plotly::toRGB( + x = color, + alpha = alpha * 0.5 + ), + showlegend = showlegend, + legendgroup = legendgroup, + name = name[1] + ) + + if (!missing(y)) { + plotly_object <- plotly::add_lines( + p = plotly_object, + x = x, + y = y, + line = list( + color = plotly::toRGB( + x = color, + alpha = alpha + ), + dash = dash[1] + ), + showlegend = FALSE, + legendgroup = legendgroup, + inherit = FALSE, + name = name[1] + ) + } + + ## add lower line to the + ## plot + plotly_object <- plotly::add_lines( + p = plotly_object, + x = x, + y = ymin, + line = list( + color = plotly::toRGB( + x = color, + alpha = alpha + ), + dash = dash[2] + ), + showlegend = FALSE, + legendgroup = legendgroup, + inherit = FALSE, + name = name[2] + ) + + ## add upperline to the + ## plot + plotly_object <- plotly::add_lines( + p = plotly_object, + x = x, + y = ymax, + line = list( + color = plotly::toRGB( + x = color, + alpha = alpha + ), + dash = dash[3] + ), + showlegend = FALSE, + legendgroup = legendgroup, + inherit = FALSE, + name = name[3] + ) + + ## return plot + return( + plotly_object + ) +} diff --git a/R/chart_indicator.R b/R/chart_indicator.R index b978af695..a7ce14797 100644 --- a/R/chart_indicator.R +++ b/R/chart_indicator.R @@ -19,6 +19,21 @@ #' #' @author Serkan Korkmaz indicator <- function(FUN, ...) { + ## resolve function name of no + ## title have been passed + title <- input_name( + substitute( + FUN + ) + ) + + ## clean up title + if (any(grepl(x = title, pattern = "_"))) { + title <- to_title( + title + ) + } + ## plotting environment ## does exist chart_called <- TRUE @@ -39,10 +54,39 @@ indicator <- function(FUN, ...) { ## object to trigger .plotly ## method downstream plt <- plotly::plot_ly() + + if (has_arg(idx)) { + idx <- eval.parent( + match.call()[["idx"]] + ) + } else { + idx <- NULL + } + + .plotting_environment$idx$label <- idx + + if (has_arg(data)) { + data <- eval.parent( + match.call()[["data"]] + ) + } else { + stop("'data'-argument has to be provided.") + } } ## construct {plotly}-object ## based on FUN + ## + ## Note to future self: + ## + ## You could add chart layouting here + ## to avoid having to do it for each plotly method + ## but it would require you to add an identifier + ## of whether its a subplot or not. + ## + ## `outcome` by itself is just directly returned + ## and is not attached to the plotting environment + ## downstream outcome <- do.call( what = FUN, args = list( @@ -75,17 +119,27 @@ indicator <- function(FUN, ...) { margin = 0.02, heights = heights ), - showlegend = TRUE + showlegend = TRUE, + yaxis = list(title = ''), + xaxis = list( + title = '', + tickmode = "auto" + ) ) .plotting_environment$chart <- fig - return(fig) + return( + fig + ) } ## reconstruct charting ## as if called from chart() - .chart_layout( + outcome <- .chart_layout( x = outcome, - title_text = "title_text" + title_text = title, + idx = if (is.null(idx)) 1:nrow(data) else idx ) + + outcome } diff --git a/R/chart_pattern.R b/R/chart_pattern.R index bf2ddb8ee..e52990172 100644 --- a/R/chart_pattern.R +++ b/R/chart_pattern.R @@ -3,7 +3,8 @@ pattern <- function( x, # pattern high, low, - pattern_name = "Doji" + pattern_name = "Doji", + agnostic = FALSE ) { ## chart theme controls chart_theme <- .chart_theme() @@ -50,17 +51,40 @@ pattern <- function( p <- plotly::add_trace( p = p, x = idx_bull, - y = low[idx_bull] - offset[idx_bull], + y = if (agnostic) { + high[idx_bull] - offset[idx_bull] + } else { + low[idx_bull] - offset[idx_bull] + }, type = "scatter", mode = "markers+text", marker = list( - symbol = "triangle-up", - color = chart_theme$bull_color, + symbol = if (agnostic) { + "triangle-down" + } else { + "triangle-up" + }, + color = if (agnostic) { + chart_theme$font_color + } else { + chart_theme$bull_color + }, size = 10 ), text = bull_text, - textposition = "bottom center", - textfont = list(color = chart_theme$bull_color, size = 10), + textposition = if (agnostic) { + "top center" + } else { + "bottom center" + }, + textfont = list( + color = if (agnostic) { + chart_theme$font_color + } else { + chart_theme$bull_color + }, + size = 10 + ), hoverinfo = "skip", name = "Bearish", inherit = FALSE, diff --git a/R/series.R b/R/series.R index 7e241db0b..97705dfe1 100644 --- a/R/series.R +++ b/R/series.R @@ -40,13 +40,19 @@ series.plotly <- function( dotsQ$data <- quote(.plotting_environment$x) } - as.data.frame( + out <- as.data.frame( do.call( series.formula, c(list(x = formula, default = default), dotsQ), quote = FALSE ) ) + + ## set subset attribute + ## for the + attr(out, "subset") <- eval(dotsQ$subset) + + out } #' @export @@ -96,6 +102,10 @@ series.formula <- function( ) } + ## set subset attribute + ## for the + attr(out, "subset") <- eval(dotsQ$subset) + as.data.frame( out ) diff --git a/R/ta_ACCBANDS.R b/R/ta_ACCBANDS.R index b693b4315..b193cb1a4 100644 --- a/R/ta_ACCBANDS.R +++ b/R/ta_ACCBANDS.R @@ -124,10 +124,12 @@ acceleration_bands.plotly <- function( x, cols, n = 10, + color = "steelblue", + alpha = 0.5, ... ) { - ## prepare series - ## from + ## prepare HLC series + ## for the acceleration bands HLC <- series( x = x, formula = cols, @@ -135,20 +137,28 @@ acceleration_bands.plotly <- function( ... ) - ## calculate acceleration - ## bands and return as - ## data.frame - .indicator <- as.data.frame( - .Call( - "impl_ta_ACCBANDS", - HLC[[1]], - HLC[[2]], - HLC[[3]], - as.integer(n) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- acceleration_bands.default( + x = HLC, + cols = rebuild_formula( + names(HLC) + ), + n = n ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLC + ) + + ## acceleration bands by itself + ## makes no sense - throw an error + ## if not provided + if (is.null(.plotting_environment$main)) { + stop("No existing chart found.", call. = FALSE) + } ## add upper, middle and lower bands ## to the main chart - wrapped in local @@ -156,46 +166,19 @@ acceleration_bands.plotly <- function( ## ## NOTE: Otherwise it will only evaluate ## and add the last element - for (i in seq_len(ncol(HLC))) { - local({ - j <- i - - .plotting_environment$main <- plotly::add_lines( - .plotting_environment$main, - data = .indicator, - x = ~idx, - y = ~ .indicator[, j], - inherit = FALSE, - line = list( - color = '#4682b4' - ), - showlegend = FALSE, - legendgroup = 'acceleration_band', - name = c( - "Upper Band", - "Middle Band", - "Lower Band" - )[j], - ) - }) - } - - .plotting_environment$main <- plotly::add_ribbons( - p = .plotting_environment$main, - inherit = FALSE, + .plotting_environment$main <- add_ribbons( + plotly_object = .plotting_environment$main, data = .indicator, x = ~idx, - ymin = ~ .indicator[, 3], - ymax = ~ .indicator[, 1], - fillcolor = plotly::toRGB("#4682b4", alpha = 0.2), - line = list( - color = "transparent" - ), + y = ~middle, + ymin = ~lower, + ymax = ~upper, + color = color, + alpha = alpha, showlegend = TRUE, legendgroup = 'acceleration_band', - name = paste0( - "Acceleration Bands" - ) + name = c("Acceleration Bands", "B", "C"), + dash = NULL ) .plotting_environment$main diff --git a/R/ta_AD.R b/R/ta_AD.R index a80034e45..dd521589d 100644 --- a/R/ta_AD.R +++ b/R/ta_AD.R @@ -121,6 +121,7 @@ chaikin_AD_line.plotly <- function( ... ) { ## prepare HLCV series + ## for the chaikin A/D line HLCV <- series( x = x, formula = cols, @@ -128,51 +129,42 @@ chaikin_AD_line.plotly <- function( ... ) - ## construct the chaikin A/D - ## line and store as data.frame - ## for plotly - .indicator <- data.frame( - AD_line = .Call( - "impl_ta_AD", - HLCV[[1]], - HLCV[[2]], - HLCV[[3]], - HLCV[[4]] + ## calculate indicator + ## and return as data.grame + .indicator <- chaikin_AD_line.default( + x = HLCV, + cols = rebuild_formula( + names(HLCV) ) ) - ## add idx for the axis - ## TODO: this should be passed - ## upstream instead - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLCV + ) - ## chart indicator - ## as subplot - output <- add_title( - ## generate plot - ## as line - plotly::plot_ly( - data = .indicator, - x = ~idx, - y = ~AD_line, - type = "scatter", - mode = "lines", - showlegend = FALSE - ), - ## add title to - ## the plot - text = "Chaikin A/D Line" + ## construct chart + ## element + plotly_object <- subchart( + data = .indicator, + y = ~AD_line, + type = "scatter", + mode = "lines", + showlegend = FALSE ) - ## pass to sub as - ## list to preserve - ## types + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Chaikin A/D Line" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - ## return plot - ## if called directly - output + plotly_object } diff --git a/R/ta_ADOSC.R b/R/ta_ADOSC.R index ae59d9803..0643cb3a4 100644 --- a/R/ta_ADOSC.R +++ b/R/ta_ADOSC.R @@ -129,9 +129,11 @@ chaikin_AD_oscillator.plotly <- function( cols, fast = 3, slow = 10, + color = "steelblue", ... ) { - ## prepare series + ## prepare HLCV series + ## for the chaikin A/D line HLCV <- series( x = x, formula = cols, @@ -139,53 +141,67 @@ chaikin_AD_oscillator.plotly <- function( ... ) - .indicator <- data.frame( - AD_line = .Call( - "impl_ta_ADOSC", - HLCV[[1]], - HLCV[[2]], - HLCV[[3]], - HLCV[[4]], - as.integer(fast), - as.integer(slow) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- chaikin_AD_oscillator.default( + x = HLCV, + cols = rebuild_formula( + names(HLCV) + ), + fast = fast, + slow = slow ) - .indicator$idx <- 1:nrow(.indicator) - ad_col <- "#1f77b4" + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLCV + ) - ad_plot <- plotly::plot_ly( + plotly_object <- subchart( data = .indicator, - x = ~idx, - y = ~AD_line, + y = ~AD_oscillator, type = "scatter", mode = "lines", - line = list(color = ad_col), + line = list( + color = plotly::toRGB( + x = color, + alpha = 1 + ) + ), name = "AD", legendgroup = "ChaikinOscillator", showlegend = FALSE ) - # dashed y = 0 line in the same color - ad_plot <- plotly::add_lines( - p = ad_plot, + plotly_object <- plotly::add_lines( + p = plotly_object, x = .indicator$idx, y = 0, - line = list(color = ad_col, dash = "dash"), + line = list( + color = plotly::toRGB( + x = color, + alpha = 1 + ), + dash = "dot" + ), showlegend = FALSE, hoverinfo = "skip", legendgroup = "ChaikinOscillator", name = "Zero" ) - ad_plot <- add_title( - x = ad_plot, - text = "Chaikin A/D Oscillator" - ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Chaikin A/D Oscillator" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(ad_plot) + list(plotly_object) ) - ad_plot + plotly_object } diff --git a/R/ta_AROON.R b/R/ta_AROON.R index 8bdd3e0bb..b33296d8c 100644 --- a/R/ta_AROON.R +++ b/R/ta_AROON.R @@ -121,6 +121,8 @@ aroon.plotly <- function( n = 10, ... ) { + ## prepare HL series + ## for the aroon oscillator HL <- series( x = x, formula = cols, @@ -128,49 +130,53 @@ aroon.plotly <- function( ... ) - .indicator <- as.data.frame( - .Call( - "impl_ta_AROON", - HL[[1]], - HL[[2]], - as.integer(n) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- aroon.default( + x = HL, + cols = rebuild_formula( + names(HL) + ), + n = n ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HL + ) - ad_plot <- plotly::plot_ly( + ## construct chart + ## element + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~aroon_down, type = "scatter", mode = "lines", - # line = list(color = ad_col), name = "AD", legendgroup = "Aroon", showlegend = FALSE ) - # dashed y = 0 line in the same color - ad_plot <- plotly::add_lines( - p = ad_plot, + plotly_object <- plotly::add_lines( + p = plotly_object, x = .indicator$idx, y = ~aroon_up, - # line = list(color = ad_col, dash = "dash"), showlegend = FALSE, - hoverinfo = "skip", - legendgroup = "Aroon", - name = "Zero" + legendgroup = "Aroon" ) - ad_plot <- add_title( - x = ad_plot, - text = "Aroon" - ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Aroon" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(ad_plot) + list(plotly_object) ) - ad_plot + plotly_object } diff --git a/R/ta_AROONOSC.R b/R/ta_AROONOSC.R index a481a16a3..9fc14e166 100644 --- a/R/ta_AROONOSC.R +++ b/R/ta_AROONOSC.R @@ -120,6 +120,8 @@ aroon_oscillator.plotly <- function( n = 10, ... ) { + ## prepare HL series + ## for the aroon oscillator HL <- series( x = x, formula = cols, @@ -127,37 +129,48 @@ aroon_oscillator.plotly <- function( ... ) - .indicator <- data.frame( - aroon_oscillator = .Call( - "impl_ta_AROONOSC", - HL[[1]], - HL[[2]], - as.integer(n) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- aroon_oscillator.default( + x = HL, + cols = rebuild_formula( + names(HL) + ), + n = n ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HL + ) - ad_plot <- plotly::plot_ly( + ## construct chart + ## element + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~aroon_oscillator, type = "scatter", mode = "lines", - # line = list(color = ad_col), - name = "AD", + name = sprintf( + fmt = "AD(%d)", + n + ), legendgroup = "Aroon", showlegend = FALSE ) - ad_plot <- add_title( - x = ad_plot, - text = "Aroon Oscillator" - ) + if (!is.null(.plotting_environment$main)) { + plotly_object <- add_title( + x = plotly_object, + text = "Aroon Oscillator" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(ad_plot) + list(plotly_object) ) - ad_plot + plotly_object } diff --git a/R/ta_BBANDS.R b/R/ta_BBANDS.R index efb634342..11fb25d97 100644 --- a/R/ta_BBANDS.R +++ b/R/ta_BBANDS.R @@ -185,10 +185,13 @@ bollinger_bands.plotly <- function( ma = SMA(n = 10), up = 2, down = 2, + color = "steelblue", + alpha = 0.5, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for the bollinger + ## bands x <- series( x = x, formula = cols, @@ -196,61 +199,46 @@ bollinger_bands.plotly <- function( ... ) - .indicator <- as.data.frame( - .Call( - "impl_ta_BBANDS", - as.double(x[[1]]), - ma$n, - as.numeric(up), - as.numeric(down), - as.integer(ma$maType) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- bollinger_bands.default( + x = x, + cols = rebuild_formula( + names(x) + ), + ma = ma, + up = up, + down = down ) - .indicator$idx <- 1:nrow(.indicator) - - ## constuct chart - ## element - for (i in seq_len(ncol(.indicator) - 1)) { - local({ - j <- i + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) - .plotting_environment$main <- plotly::add_lines( - .plotting_environment$main, - data = .indicator, - x = ~idx, - y = ~ .indicator[, j], - inherit = FALSE, - line = list( - color = '#4682b4' - ), - showlegend = FALSE, - legendgroup = 'bollinger_band', - name = c( - "Upper Band", - "Middle Band", - "Lower Band" - )[j], - ) - }) + ## acceleration bands by itself + ## makes no sense - throw an error + ## if not provided + if (is.null(.plotting_environment$main)) { + stop("No existing chart found.", call. = FALSE) } - .plotting_environment$main <- plotly::add_ribbons( - p = .plotting_environment$main, - inherit = FALSE, + ## constuct chart + ## element + .plotting_environment$main <- add_ribbons( + plotly_object = .plotting_environment$main, data = .indicator, x = ~idx, - ymin = ~ .indicator[, 3], - ymax = ~ .indicator[, 1], - fillcolor = plotly::toRGB("#4682b4", alpha = 0.2), - line = list( - color = "transparent" - ), + y = ~middle, + ymin = ~lower, + ymax = ~upper, + color = color, + alpha = alpha, showlegend = TRUE, - legendgroup = 'bollinger_band', - name = paste0( - "BBand" - ) + legendgroup = "Bollinger Bands", + name = c("Bollinger Bands", "middle", "upper"), + dash = NULL ) .plotting_environment$main diff --git a/R/ta_CCI.R b/R/ta_CCI.R index c399d1d33..a0e0db43e 100644 --- a/R/ta_CCI.R +++ b/R/ta_CCI.R @@ -109,6 +109,8 @@ commodity_channel_index.matrix <- function( x, cols, n = 10, + upper = 100, + lower = -100, ... ) { as.matrix( @@ -123,10 +125,12 @@ commodity_channel_index.plotly <- function( x, cols, n = 10, + lower = -100, + upper = 100, ... ) { - ## prepare series - ## from {plotly}-object + ## prepare HLC series + ## for the commodity channel index HLC <- as.data.frame( series( x = x, @@ -136,23 +140,32 @@ commodity_channel_index.plotly <- function( ) ) - ## construct indicator - .indicator <- as.data.frame( - .Call( - "impl_ta_CCI", - HLC[[1]], - HLC[[2]], - HLC[[3]], - as.integer(n) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- commodity_channel_index.default( + x = HLC, + cols = rebuild_formula( + names(HLC) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLC ) - colnames(.indicator) <- "CCI" - .indicator$idx <- 1:nrow(.indicator) + ## commodity channels by itself + ## makes no sense - throw an error + ## if not provided + if (!main_chart_exists()) { + stop("No existing chart found.", call. = FALSE) + } ## construct plot with ribbons ## on upper and lower limits - output <- plotly::plot_ly( + plotly_object <- plotly::plot_ly( data = .indicator, x = ~idx, y = ~CCI, @@ -161,30 +174,34 @@ commodity_channel_index.plotly <- function( showlegend = FALSE ) - output <- plotly::add_ribbons( - output, - x = ~idx, - ymin = rep(-100, nrow(.indicator)), - ymax = rep(100, nrow(.indicator)), - line = list(width = 0), - fillcolor = plotly::toRGB( - x = "lightgray", - alpha = 0.2 - ) + plotly_object <- add_ribbons( + plotly_object = plotly_object, + data = .indicator, + x = ~ 1:nrow(.indicator), + ymin = rep(lower, nrow(.indicator)), + ymax = rep(upper, nrow(.indicator)), + color = "lightgray", + alpha = 0.1, + showlegend = FALSE, + legendgroup = "placeholder", + name = "CCI", + dash = "dot" ) - output <- add_title( - x = output, - text = sprintf( - "Commodity Channel Index (%d)", - n + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = sprintf( + "Commodity Channel Index (%d)", + n + ) ) - ) + } .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_CDL2CROWS.R b/R/ta_CDL2CROWS.R index 6fb58d88c..af9a06b7f 100644 --- a/R/ta_CDL2CROWS.R +++ b/R/ta_CDL2CROWS.R @@ -145,10 +145,16 @@ two_crows.plotly <- function( ## indicators .indicator <- two_crows.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ two_crows.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Two Crows" + pattern_name = "Two Crows", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDL3BLACKCROWS.R b/R/ta_CDL3BLACKCROWS.R index 4f91c148c..b46864d7d 100644 --- a/R/ta_CDL3BLACKCROWS.R +++ b/R/ta_CDL3BLACKCROWS.R @@ -145,10 +145,16 @@ three_black_crows.plotly <- function( ## indicators .indicator <- three_black_crows.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ three_black_crows.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Three Black Crows" + pattern_name = "Three Black Crows", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDL3INSIDE.R b/R/ta_CDL3INSIDE.R index a16a3cffd..6875a2854 100644 --- a/R/ta_CDL3INSIDE.R +++ b/R/ta_CDL3INSIDE.R @@ -145,10 +145,16 @@ three_inside.plotly <- function( ## indicators .indicator <- three_inside.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ three_inside.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Three Inside" + pattern_name = "Three Inside", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDL3LINESTRIKE.R b/R/ta_CDL3LINESTRIKE.R index b02176815..eb9bcf824 100644 --- a/R/ta_CDL3LINESTRIKE.R +++ b/R/ta_CDL3LINESTRIKE.R @@ -145,10 +145,16 @@ three_line_strike.plotly <- function( ## indicators .indicator <- three_line_strike.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ three_line_strike.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Three Line Strike" + pattern_name = "Three Line Strike", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDL3OUTSIDE.R b/R/ta_CDL3OUTSIDE.R index 53339b54b..34055e2d4 100644 --- a/R/ta_CDL3OUTSIDE.R +++ b/R/ta_CDL3OUTSIDE.R @@ -145,10 +145,16 @@ three_outside.plotly <- function( ## indicators .indicator <- three_outside.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ three_outside.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Three Outside" + pattern_name = "Three Outside", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDL3STARSINSOUTH.R b/R/ta_CDL3STARSINSOUTH.R index c8722d037..ef4dc9a7d 100644 --- a/R/ta_CDL3STARSINSOUTH.R +++ b/R/ta_CDL3STARSINSOUTH.R @@ -145,10 +145,16 @@ three_stars_in_the_south.plotly <- function( ## indicators .indicator <- three_stars_in_the_south.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ three_stars_in_the_south.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Three Stars in the South" + pattern_name = "Three Stars in the South", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDL3WHITESOLDIERS.R b/R/ta_CDL3WHITESOLDIERS.R index 5ff1c524e..6918b4d0e 100644 --- a/R/ta_CDL3WHITESOLDIERS.R +++ b/R/ta_CDL3WHITESOLDIERS.R @@ -145,10 +145,16 @@ three_white_soldiers.plotly <- function( ## indicators .indicator <- three_white_soldiers.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ three_white_soldiers.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Three White Soldiers" + pattern_name = "Three White Soldiers", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLABANDONEDBABY.R b/R/ta_CDLABANDONEDBABY.R index c2dde44d0..bbfd635d7 100644 --- a/R/ta_CDLABANDONEDBABY.R +++ b/R/ta_CDLABANDONEDBABY.R @@ -150,10 +150,16 @@ abandoned_baby.plotly <- function( ## indicators .indicator <- abandoned_baby.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -161,7 +167,8 @@ abandoned_baby.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Abandoned Baby" + pattern_name = "Abandoned Baby", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLADVANCEBLOCK.R b/R/ta_CDLADVANCEBLOCK.R index 9ddfeda8a..6cf3a61fb 100644 --- a/R/ta_CDLADVANCEBLOCK.R +++ b/R/ta_CDLADVANCEBLOCK.R @@ -145,10 +145,16 @@ advance_block.plotly <- function( ## indicators .indicator <- advance_block.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ advance_block.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Advance Block" + pattern_name = "Advance Block", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLBELTHOLD.R b/R/ta_CDLBELTHOLD.R index 00ed85df0..3a977d6d7 100644 --- a/R/ta_CDLBELTHOLD.R +++ b/R/ta_CDLBELTHOLD.R @@ -145,10 +145,16 @@ belt_hold.plotly <- function( ## indicators .indicator <- belt_hold.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ belt_hold.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Belt Hold" + pattern_name = "Belt Hold", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLBREAKAWAY.R b/R/ta_CDLBREAKAWAY.R index 946013d8a..4dd1fabd3 100644 --- a/R/ta_CDLBREAKAWAY.R +++ b/R/ta_CDLBREAKAWAY.R @@ -145,10 +145,16 @@ break_away.plotly <- function( ## indicators .indicator <- break_away.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ break_away.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Break Away" + pattern_name = "Break Away", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLCLOSINGMARUBOZU.R b/R/ta_CDLCLOSINGMARUBOZU.R index 4eae5cc36..3f9627661 100644 --- a/R/ta_CDLCLOSINGMARUBOZU.R +++ b/R/ta_CDLCLOSINGMARUBOZU.R @@ -145,10 +145,16 @@ closing_marubozu.plotly <- function( ## indicators .indicator <- closing_marubozu.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ closing_marubozu.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Closing Marubozu" + pattern_name = "Closing Marubozu", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLCONCEALBABYSWALL.R b/R/ta_CDLCONCEALBABYSWALL.R index 307ca485b..e874465c9 100644 --- a/R/ta_CDLCONCEALBABYSWALL.R +++ b/R/ta_CDLCONCEALBABYSWALL.R @@ -145,10 +145,16 @@ concealing_baby_swallow.plotly <- function( ## indicators .indicator <- concealing_baby_swallow.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ concealing_baby_swallow.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Concealing Baby Swallow" + pattern_name = "Conceal Baby Swallow", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLCOUNTERATTACK.R b/R/ta_CDLCOUNTERATTACK.R index 430a03e3f..dabf26c7f 100644 --- a/R/ta_CDLCOUNTERATTACK.R +++ b/R/ta_CDLCOUNTERATTACK.R @@ -145,10 +145,16 @@ counter_attack.plotly <- function( ## indicators .indicator <- counter_attack.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ counter_attack.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Counter Attack" + pattern_name = "Counter Attack", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLDARKCLOUDCOVER.R b/R/ta_CDLDARKCLOUDCOVER.R index 11512d9ec..b3872e61c 100644 --- a/R/ta_CDLDARKCLOUDCOVER.R +++ b/R/ta_CDLDARKCLOUDCOVER.R @@ -150,10 +150,16 @@ dark_cloud_cover.plotly <- function( ## indicators .indicator <- dark_cloud_cover.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -161,7 +167,8 @@ dark_cloud_cover.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Dark Cloud Cover" + pattern_name = "Dark Cloud Cover", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLDOJI.R b/R/ta_CDLDOJI.R index a3e1daa28..f547d5ff0 100644 --- a/R/ta_CDLDOJI.R +++ b/R/ta_CDLDOJI.R @@ -145,10 +145,16 @@ doji.plotly <- function( ## indicators .indicator <- doji.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ doji.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Doji" + pattern_name = "Doji", + agnostic = TRUE ) .plotting_environment$main diff --git a/R/ta_CDLDOJISTAR.R b/R/ta_CDLDOJISTAR.R index d0138897a..ab4d89996 100644 --- a/R/ta_CDLDOJISTAR.R +++ b/R/ta_CDLDOJISTAR.R @@ -145,10 +145,16 @@ doji_star.plotly <- function( ## indicators .indicator <- doji_star.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ doji_star.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Doji Star" + pattern_name = "Doji Star", + agnostic = TRUE ) .plotting_environment$main diff --git a/R/ta_CDLDRAGONFLYDOJI.R b/R/ta_CDLDRAGONFLYDOJI.R index ff3e89736..4982583e6 100644 --- a/R/ta_CDLDRAGONFLYDOJI.R +++ b/R/ta_CDLDRAGONFLYDOJI.R @@ -145,10 +145,16 @@ dragonfly_doji.plotly <- function( ## indicators .indicator <- dragonfly_doji.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ dragonfly_doji.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Dragonfly Doji" + pattern_name = "Dragonfly Doji", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLENGULFING.R b/R/ta_CDLENGULFING.R index ee0b47adc..e90405b70 100644 --- a/R/ta_CDLENGULFING.R +++ b/R/ta_CDLENGULFING.R @@ -145,10 +145,16 @@ engulfing.plotly <- function( ## indicators .indicator <- engulfing.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ engulfing.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Two Crows" + pattern_name = "Engulfing", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLEVENINGDOJISTAR.R b/R/ta_CDLEVENINGDOJISTAR.R index 9db7e8f20..5c2543a6c 100644 --- a/R/ta_CDLEVENINGDOJISTAR.R +++ b/R/ta_CDLEVENINGDOJISTAR.R @@ -150,10 +150,16 @@ evening_doji_star.plotly <- function( ## indicators .indicator <- evening_doji_star.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -161,7 +167,8 @@ evening_doji_star.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Evening Doji Star" + pattern_name = "Evening Doji Star", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLGAPSIDESIDEWHITE.R b/R/ta_CDLGAPSIDESIDEWHITE.R index b6d9b50b3..5c47e46d6 100644 --- a/R/ta_CDLGAPSIDESIDEWHITE.R +++ b/R/ta_CDLGAPSIDESIDEWHITE.R @@ -145,10 +145,16 @@ gaps_side_white.plotly <- function( ## indicators .indicator <- gaps_side_white.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ gaps_side_white.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Gaps-side White" + pattern_name = "Gap-side White", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLGRAVESTONEDOJI.R b/R/ta_CDLGRAVESTONEDOJI.R index a13c7c592..707f0db3e 100644 --- a/R/ta_CDLGRAVESTONEDOJI.R +++ b/R/ta_CDLGRAVESTONEDOJI.R @@ -145,10 +145,16 @@ gravestone_doji.plotly <- function( ## indicators .indicator <- gravestone_doji.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ gravestone_doji.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Gravestone Doji" + pattern_name = "Gravestone Doji", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLHAMMER.R b/R/ta_CDLHAMMER.R index 5b36e1251..f2277e706 100644 --- a/R/ta_CDLHAMMER.R +++ b/R/ta_CDLHAMMER.R @@ -145,10 +145,16 @@ hammer.plotly <- function( ## indicators .indicator <- hammer.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ hammer.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Hammer" + pattern_name = "Hammer", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLHANGINGMAN.R b/R/ta_CDLHANGINGMAN.R index e405f8e27..e1931a7fc 100644 --- a/R/ta_CDLHANGINGMAN.R +++ b/R/ta_CDLHANGINGMAN.R @@ -145,10 +145,16 @@ hanging_man.plotly <- function( ## indicators .indicator <- hanging_man.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ hanging_man.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Hanging Man" + pattern_name = "Hanging Man", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CDLHARAMI.R b/R/ta_CDLHARAMI.R index de5183daf..d8ad96f61 100644 --- a/R/ta_CDLHARAMI.R +++ b/R/ta_CDLHARAMI.R @@ -145,10 +145,16 @@ harami.plotly <- function( ## indicators .indicator <- harami.default( x = OHLC, - cols = ~ open + high + low + close + cols = rebuild_formula( + names(OHLC) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + OHLC + ) ## chart patterns .plotting_environment$main <- pattern( @@ -156,7 +162,8 @@ harami.plotly <- function( x = .indicator, high = OHLC[[2]], low = OHLC[[3]], - pattern_name = "Harami" + pattern_name = "Harami", + agnostic = FALSE ) .plotting_environment$main diff --git a/R/ta_CMO.R b/R/ta_CMO.R index cfd7d95aa..669ac3201 100644 --- a/R/ta_CMO.R +++ b/R/ta_CMO.R @@ -157,10 +157,14 @@ chande_momentum_oscillator.plotly <- function( x, cols, n = 10, + upper = 50, + lower = -50, + alpha = 0.7, ... ) { - ## prepare series - ## from {plotly}-object + ## prepare univariate + ## series for the chande momentum + ## indicator x <- as.data.frame( series( x = x, @@ -170,56 +174,60 @@ chande_momentum_oscillator.plotly <- function( ) ) - ## construct indicator - ## NOTE: NextMethod might be risky - ## here - .indicator <- as.data.frame( - .Call( - "impl_ta_CMO", - x[[1]], - as.integer(n) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- chande_momentum_oscillator.default( + x = x, + cols = rebuild_formula( + names(x) + ), + n = n ) - colnames(.indicator) <- "CMO" - - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) ## construct plot with ribbons ## on upper and lower limits - output <- plotly::plot_ly( + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~CMO, type = "scatter", mode = "lines", showlegend = FALSE ) - output <- plotly::add_ribbons( - output, - x = ~idx, - ymin = rep(-50, nrow(.indicator)), - ymax = rep(50, nrow(.indicator)), - line = list(width = 0), - fillcolor = plotly::toRGB( - x = "lightgray", - alpha = 0.2 - ) + plotly_object <- add_ribbons( + plotly_object = plotly_object, + data = .indicator, + x = ~ 1:nrow(.indicator), + ymin = rep(lower, nrow(.indicator)), + ymax = rep(upper, nrow(.indicator)), + alpha = alpha, + color = "lightgray", + showlegend = FALSE, + legendgroup = "cmo_area", + name = "cmo_area", + dash = "dot" ) - output <- add_title( - x = output, - text = sprintf( - "Chande Momentum Indicator (%d)", - n + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = sprintf( + "Chande Momentum Indicator (%d)", + n + ) ) - ) + } .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_DEMA.R b/R/ta_DEMA.R index 1d1c1ceeb..645adf678 100644 --- a/R/ta_DEMA.R +++ b/R/ta_DEMA.R @@ -90,7 +90,7 @@ DEMA.default <- function( colnames(x) <- paste0("dema_", colnames(x)) - x + as.data.frame(x) } #' @rdname DEMA @@ -154,8 +154,8 @@ DEMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for DEMA x <- as.data.frame( series( x = x, @@ -165,9 +165,21 @@ DEMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- DEMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = 10 + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -176,7 +188,7 @@ DEMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("DEMA(%d)", n), diff --git a/R/ta_EMA.R b/R/ta_EMA.R index bbd228407..c906e687a 100644 --- a/R/ta_EMA.R +++ b/R/ta_EMA.R @@ -89,7 +89,7 @@ EMA.default <- function( colnames(x) <- paste0("ema_", colnames(x)) - x + as.data.frame(x) } #' @rdname EMA @@ -153,8 +153,8 @@ EMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for EMA x <- as.data.frame( series( x = x, @@ -164,9 +164,21 @@ EMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- EMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -175,7 +187,7 @@ EMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("EMA(%d)", n), diff --git a/R/ta_HT_DCPERIOD.R b/R/ta_HT_DCPERIOD.R index 437a84a18..3c9628c25 100644 --- a/R/ta_HT_DCPERIOD.R +++ b/R/ta_HT_DCPERIOD.R @@ -160,22 +160,38 @@ ht_dcperiod.plotly <- function( ## .indicator <- ht_dcperiod.default( x = x, - cols = cols + cols = rebuild_formula( + names(x) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) - output <- plotly::plot_ly( + ## construct plotly object + ## as lines + markers + plotly_object <- subchart( data = .indicator, - name = "Dominant Cycle Period", - x = ~idx, - y = ~dominant_cycle_period + y = ~dominant_cycle_period, + type = "scatter", + mode = "lines+markers", + name = "DC Period" ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Dominant Cycle Period" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_HT_DCPHASE.R b/R/ta_HT_DCPHASE.R index 21cfd6a84..0307d4eee 100644 --- a/R/ta_HT_DCPHASE.R +++ b/R/ta_HT_DCPHASE.R @@ -145,8 +145,8 @@ ht_dc_phase.plotly <- function( cols, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for DC phase x <- as.data.frame( series( x = x, @@ -156,26 +156,42 @@ ht_dc_phase.plotly <- function( ) ) - ## construct indicator - ## + ## construct DC phase + ## as data.frame .indicator <- ht_dc_phase.default( x = x, - cols = cols + cols = rebuild_formula( + names(x) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) - output <- plotly::plot_ly( + ## construct indicator + ## as plotly object + plotly_object <- subchart( data = .indicator, - name = "Dominant Cycle Phase", - x = ~idx, - y = ~dominant_cycle_phase + y = ~dominant_cycle_phase, + type = "scatter", + mode = "markers", + name = "DC Phase" ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Dominant Cycle Phase" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_HT_PHASOR.R b/R/ta_HT_PHASOR.R index 7dfd6ad98..6d3a4dca4 100644 --- a/R/ta_HT_PHASOR.R +++ b/R/ta_HT_PHASOR.R @@ -143,8 +143,9 @@ ht_phasor.plotly <- function( cols, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for phasor + ## components x <- as.data.frame( series( x = x, @@ -154,34 +155,52 @@ ht_phasor.plotly <- function( ) ) - ## construct indicator - ## + ## construct phasor indicators + ## as data.frame .indicator <- ht_phasor.default( x = x, - cols = cols + cols = rebuild_formula( + names(x) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) - output <- plotly::plot_ly( + ## construct plotly + ## object + plotly_object <- subchart( data = .indicator, - name = "Phasor Components", - x = ~idx, - y = ~inphase + y = ~inphase, + type = "scatter", + mode = "lines", + name = "Inphase", + legendgroup = "phasor_components" ) - output <- plotly::add_lines( - output, + plotly_object <- plotly::add_lines( + p = plotly_object, + data = .indicator, x = ~idx, y = ~quadrature, - data = .indicator, - inherit = FALSE + name = "Quadrature", + legendgroup = "phasor_components" ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Phasor Components" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_HT_SINE.R b/R/ta_HT_SINE.R index ff7ac7a0c..c1305a522 100644 --- a/R/ta_HT_SINE.R +++ b/R/ta_HT_SINE.R @@ -144,8 +144,8 @@ ht_sine_wave.plotly <- function( cols, ... ) { - ## prepare series - ## from + ## prepare univariate + ## seris for sine wave x <- as.data.frame( series( x = x, @@ -155,35 +155,52 @@ ht_sine_wave.plotly <- function( ) ) - ## construct indicator - ## + ## construct sine wave + ## as data.frame .indicator <- ht_sine_wave.default( x = x, - cols = cols, - ... + cols = rebuild_formula( + names(x) + ) ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) - output <- plotly::plot_ly( + ## construct plotly + ## object + plotly_object <- subchart( data = .indicator, - name = "Sine Wave", - x = ~idx, - y = ~sine + y = ~sine, + type = "scatter", + mode = "lines", + name = "Sine", + legendgroup = "sinewave" ) - output <- plotly::add_lines( - p = output, + plotly_object <- plotly::add_lines( + p = plotly_object, x = ~idx, y = ~leadsine, data = .indicator, - inherit = FALSE + name = "Lead Sine", + legendgroup = "sinewave" ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Sine Wave" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_HT_TRENDLINE.R b/R/ta_HT_TRENDLINE.R index d27982db4..e1c550c06 100644 --- a/R/ta_HT_TRENDLINE.R +++ b/R/ta_HT_TRENDLINE.R @@ -146,8 +146,8 @@ ht_trendline.plotly <- function( cols, ... ) { - ## prepare series - ## from + ## prepare univariate series + ## for the trendline x <- as.data.frame( series( x = x, @@ -157,13 +157,22 @@ ht_trendline.plotly <- function( ) ) - ## indicator + ## calculate trendline indicator + ## and return as data.frame .indicator <- ht_trendline.default( x = x, - cols = cols + cols = rebuild_formula( + names(x) + ) + ) + + ## add idx conditional + ## on whether idx is passed + .indicator$idx <- add_idx( + x ) - .indicator$idx <- 1:nrow(.indicator) + ## construct plotly object for (i in 1:ncol(x)) { local({ j <- i @@ -174,7 +183,7 @@ ht_trendline.plotly <- function( y = ~ .indicator[, j], type = "scatter", mode = "lines", - name = sprintf("Trendline"), + name = "Trendline", inherit = FALSE ) }) diff --git a/R/ta_HT_TRENDMODE.R b/R/ta_HT_TRENDMODE.R index 942f98f08..a8e8daa6c 100644 --- a/R/ta_HT_TRENDMODE.R +++ b/R/ta_HT_TRENDMODE.R @@ -145,44 +145,53 @@ ht_trendmode.plotly <- function( cols, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for the the + ## trendmode x <- as.data.frame( series( x = x, - formula = ~ open + high + low + close, - default = ~ open + high + low + close, + formula = cols, + default = ~open, ... ) ) - ## indicator + ## calculate the trendmode + ## and return as data.frame .indicator <- ht_trendmode.default( x = x, - cols = cols + cols = rebuild_formula( + names(x) + ) ) - .indicator$idx <- 1:nrow(.indicator) - .indicator$mid_price <- rowMeans( - x[, c(2, 4)] + ## add idx based on the + ## univariate series + .indicator$idx <- add_idx( + x ) - ## locate all trend modes - trend_idx <- which(.indicator[[1]] == 1) - - .plotting_environment$main <- plotly::add_trace( - .plotting_environment$main, - x = ~ idx[trend_idx], - y = ~ .indicator$mid_price[trend_idx], + plotly_object <- subchart( + data = .indicator, + y = ~dominant_cycle_period, type = "scatter", - mode = "markers", - marker = list( - symbol = "star", - size = 10 - ), - name = sprintf("KAMA(%d)", 3), - inherit = FALSE + mode = "lines", + name = "Trendmode", + line = list(shape = "hvh") + ) + + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Trendmode" + ) + } + + .plotting_environment$sub <- c( + .plotting_environment$sub, + list(plotly_object) ) - .plotting_environment$main + plotly_object } diff --git a/R/ta_KAMA.R b/R/ta_KAMA.R index f66e85918..b84825d6a 100644 --- a/R/ta_KAMA.R +++ b/R/ta_KAMA.R @@ -89,7 +89,7 @@ KAMA.default <- function( colnames(x) <- paste0("kama_", colnames(x)) - x + as.data.frame(x) } #' @rdname KAMA @@ -153,8 +153,8 @@ KAMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for KAMA x <- as.data.frame( series( x = x, @@ -164,9 +164,21 @@ KAMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- KAMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -175,7 +187,7 @@ KAMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("KAMA(%d)", n), diff --git a/R/ta_MACD.R b/R/ta_MACD.R index c74db364b..fa7256830 100644 --- a/R/ta_MACD.R +++ b/R/ta_MACD.R @@ -261,8 +261,8 @@ moving_average_convergence_divergence.plotly <- function( signal = 9, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for MACD x <- series( x = x, formula = cols, @@ -270,61 +270,86 @@ moving_average_convergence_divergence.plotly <- function( ... ) - ## construct indicator - ## + ## calculator indicator + ## and return as data.frame .indicator <- moving_average_convergence_divergence.default( x = x, - cols = cols, + cols = rebuild_formula( + names(x) + ), fast = fast, slow = slow, signal = signal ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) + + ## calculate directions for bull + ## and bear candles .indicator$direction <- .indicator$signal >= .indicator$macd - ## theme + ## generate plotly object + ## of the indicator chart_theme <- .chart_theme() - ## generate indicator plot - output <- plotly::plot_ly( + + ## construct plotly object + plotly_object <- subchart( data = .indicator, - showlegend = FALSE, - name = 'MACD', - x = ~idx, y = ~histogram, color = ~direction, colors = c( chart_theme$bull_color, chart_theme$bear_color ), - type = 'bar' + type = 'bar', + showlegend = FALSE ) - output <- plotly::add_lines( - output, + plotly_object <- plotly::add_lines( + plotly_object, x = ~idx, y = ~signal, data = .indicator, - inherit = FALSE + inherit = FALSE, + name = sprintf( + fmt = "Signal(%d)", + if (is.list(signal)) signal$n else signal + ) ) - output <- plotly::add_lines( - output, + plotly_object <- plotly::add_lines( + plotly_object, x = ~idx, y = ~macd, data = .indicator, - inherit = FALSE + inherit = FALSE, + name = sprintf( + fmt = "MACD(%d, %d)", + if (is.list(fast)) fast$n else fast, + if (is.list(slow)) slow$n else slow + ) ) - output <- add_title( - x = output, - text = "MACD" - ) + if (!is.null(.plotting_environment$main)) { + plotly_object <- add_title( + x = plotly_object, + text = sprintf( + fmt = "MACD(%d, %d, %d)", + if (is.list(fast)) fast$n else fast, + if (is.list(slow)) slow$n else slow, + if (is.list(signal)) signal$n else signal + ) + ) + } .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_MAMA.R b/R/ta_MAMA.R index d6a0e0d21..c3d2f9bef 100644 --- a/R/ta_MAMA.R +++ b/R/ta_MAMA.R @@ -89,7 +89,7 @@ MAMA.default <- function( colnames(x) <- paste0("mama_", colnames(x)) - x + as.data.frame(x) } #' @rdname MAMA @@ -153,8 +153,8 @@ MAMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for MAMA x <- as.data.frame( series( x = x, @@ -164,9 +164,21 @@ MAMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- MAMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -175,7 +187,7 @@ MAMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("MAMA(%d)", n), diff --git a/R/ta_MFI.R b/R/ta_MFI.R index b7cbc3c8e..5793bf915 100644 --- a/R/ta_MFI.R +++ b/R/ta_MFI.R @@ -120,6 +120,8 @@ money_flow_index.plotly <- function( x, cols, n = 10, + lower = -20, + upper = 80, ... ) { ## prepare series @@ -131,40 +133,38 @@ money_flow_index.plotly <- function( ... ) - ## calculate acceleration - ## bands and return as + ## calculate money flow index + ## and return as ## data.frame - .indicator <- as.data.frame( - .Call( - "impl_ta_MFI", - HLCV[[1]], - HLCV[[2]], - HLCV[[3]], - HLCV[[4]], - as.integer(n) - ) + .indicator <- money_flow_index.default( + x = HLCV, + cols = rebuild_formula( + names(HLCV) + ), + n = n ) - colnames(.indicator)[1] <- "MFI" - - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLCV + ) ## construct plot with ribbons ## on upper and lower limits - output <- plotly::plot_ly( + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~MFI, type = "scatter", mode = "lines", showlegend = FALSE ) - output <- plotly::add_ribbons( - output, + plotly_object <- plotly::add_ribbons( + plotly_object, x = ~idx, - ymin = rep(-20, nrow(.indicator)), - ymax = rep(70, nrow(.indicator)), + ymin = rep(lower, nrow(.indicator)), + ymax = rep(upper, nrow(.indicator)), line = list(width = 0), fillcolor = plotly::toRGB( x = "lightgray", @@ -172,18 +172,20 @@ money_flow_index.plotly <- function( ) ) - output <- add_title( - x = output, - text = sprintf( - "Money Flow Index (%d)", - n + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = sprintf( + "Money Flow Index (%d)", + n + ) ) - ) + } .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_OBV.R b/R/ta_OBV.R index ccf840b69..1f1f811b5 100644 --- a/R/ta_OBV.R +++ b/R/ta_OBV.R @@ -128,42 +128,44 @@ on_balance_volume.plotly <- function( ... ) - ## calculate acceleration - ## bands and return as - ## data.frame - .indicator <- as.data.frame( - .Call( - "impl_ta_OBV", - CV[[1]], - CV[[2]] - ) + ## calculate on balance volume + ## and return as data.frame + .indicator <- on_balance_volume.default( + x = CV, + cols = rebuild_formula( + x = names(CV) + ), + n = n ) - colnames(.indicator)[1] <- "OBV" - - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + CV + ) - ## Create - output <- plotly::plot_ly( + ## construct plot + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~OBV, type = "scatter", mode = "lines", - # line = list(color = ad_col), name = "On-Balance Volume", legendgroup = "obv", showlegend = TRUE ) - output <- add_title( - x = output, - text = "On-Balance Volume (OBV)" - ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "On-Balance Volume (OBV)" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_RSI.R b/R/ta_RSI.R index 8b2826a9d..9fbb4e302 100644 --- a/R/ta_RSI.R +++ b/R/ta_RSI.R @@ -55,7 +55,8 @@ relative_strength_index.default <- function( paste0( "'cols' has to be length 1. ", "Got length ", - length(all.vars(cols)) + length(all.vars(cols)), + paste(all.vars(cols), collapse = " and ") ) ) } @@ -143,10 +144,12 @@ relative_strength_index.plotly <- function( n = 10, lower_band = 20, upper_band = 80, + color = "lightgray", + alpha = 0.2, ... ) { - ## prepare series - ## from + ## prepare univariate series + ## for RSI x <- as.data.frame( series( x = x, @@ -156,31 +159,50 @@ relative_strength_index.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculate indicator + ## and return as data.frame + .indicator <- relative_strength_index.default( + x = x, + ## pass the column + ## based on 'x' + cols = rebuild_formula( + names(x) + ), + n = n + ) - rsi_plot <- plotly::plot_ly( - .indicator, - x = ~idx, + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) + + ## generate plotly object + ## of the indicator + plotly_object <- subchart( + data = .indicator, y = ~RSI, type = "scatter", mode = "lines", showlegend = FALSE ) - rsi_plot <- plotly::add_ribbons( - rsi_plot, + + plotly_object <- plotly::add_ribbons( + plotly_object, x = ~idx, ymin = rep(lower_band, nrow(.indicator)), ymax = rep(upper_band, nrow(.indicator)), line = list(width = 0), - fillcolor = "rgba(160,160,160,0.20)" + fillcolor = plotly::toRGB( + x = color, + alpha = alpha + ) ) .plotting_environment$sub <- c( .plotting_environment$sub, - list(rsi_plot) + list(plotly_object) ) - rsi_plot + plotly_object } diff --git a/R/ta_SMA.R b/R/ta_SMA.R index eae9a9968..9723ce37e 100644 --- a/R/ta_SMA.R +++ b/R/ta_SMA.R @@ -82,7 +82,7 @@ SMA.default <- function( colnames(x) <- paste0("sma_", colnames(x)) - x + as.data.frame(x) } #' @rdname SMA @@ -145,8 +145,8 @@ SMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for SMA x <- as.data.frame( series( x = x, @@ -156,9 +156,21 @@ SMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- SMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -167,7 +179,7 @@ SMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("SMA(%d)", n), diff --git a/R/ta_STOCH.R b/R/ta_STOCH.R index fbf4fdcc8..5ee4bdc46 100644 --- a/R/ta_STOCH.R +++ b/R/ta_STOCH.R @@ -135,15 +135,14 @@ stochastic.plotly <- function( fastk = 5, slowk = SMA(n = 10), slowd = SMA(n = 8), + lower = 20, + upper = 80, + color = "lightgray", + alpha = 0.7, ... ) { - # slowk <- map_maType_call(substitute(slowk)) - # slowd <- map_maType_call(substitute(slowd)) - # slowk <- substitute(slowk) - # slowd <- substitute(slowd) - # slowk <- map_maType_call(slowk) - # slowd <- map_maType_call(slowd) ## construct HLC series + ## for stochastic HLC <- as.data.frame( series( x = x, @@ -153,52 +152,62 @@ stochastic.plotly <- function( ) ) - .indicator <- as.data.frame( - .Call( - "impl_ta_STOCH", - HLC[[1]], - HLC[[2]], - HLC[[3]], - as.integer(fastk), - as.integer(slowk$n), - as.integer(slowk$maType), - as.integer(slowd$n), - as.integer(slowd$maType) - ) + ## calculate stochastic + ## and return as data.frame + .indicator <- stochastic.default( + x = HLC, + cols = rebuild_formula( + x = names(HLC) + ), + fastk = fastk, + slowk = slowk, + slowd = slowd ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLC + ) - ## Create - output <- plotly::plot_ly( + ## generate plotly object + ## of the indicator + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~slowk, type = "scatter", mode = "lines", - # line = list(color = ad_col), - name = "Stochastic %K", - legendgroup = "stochastic", + name = "Stocastic %K", + legendgroup = "STOCH", showlegend = TRUE ) - output <- plotly::add_lines( - output, + plotly_object <- add_ribbons( + plotly_object = plotly_object, + data = .indicator, x = ~idx, y = ~slowd, - name = "Stochastic %D", - legendgroup = "stochastic", - showlegend = TRUE + ymin = rep(lower, nrow(.indicator)), + ymax = rep(upper, nrow(.indicator)), + color = color, + alpha = alpha, + showlegend = TRUE, + dash = c("solid", "dot", "dot"), + name = c("Stochastic %D", "Lower", "Upper"), + legendgroup = "STOCH" ) - output <- add_title( - x = output, - text = "Stochastic" - ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Stochastic" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_STOCHF.R b/R/ta_STOCHF.R index 9d01bb270..96a8c44ca 100644 --- a/R/ta_STOCHF.R +++ b/R/ta_STOCHF.R @@ -128,11 +128,18 @@ fast_stochastic.plotly <- function( cols, fast_k = 5, fast_d_MAtype = SMA(n = 10), + lower = 20, + upper = 80, + color = "lightgray", + alpha = 0.7, ... ) { + ## input arguments slowk_ma <- fast_d_MAtype - ## construct HLC series + ## prepare HLC + ## series for stochastic + ## relative strength index HLC <- as.data.frame(series( x = x, formula = cols, @@ -140,49 +147,61 @@ fast_stochastic.plotly <- function( ... )) - .indicator <- as.data.frame( - .Call( - "impl_ta_STOCHF", - HLC[[1]], - HLC[[2]], - HLC[[3]], - as.integer(fast_k), - as.integer(slowk_ma$n), - as.integer(slowk_ma$maType) - ) + ## calculate indicator + ## and return as data.frame + .indicator <- fast_stochastic.default( + x = HLC, + cols = rebuild_formula( + names(HLC) + ), + fast_k = fast_k, + fast_d_MAtype = fast_d_MAtype ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLC + ) - ## Create - output <- plotly::plot_ly( + ## generate plotly object + ## of the indicator + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~fastk, type = "scatter", mode = "lines", - # line = list(color = ad_col), name = "Stochastic %K (Fast)", legendgroup = "stochastic_fast", showlegend = FALSE ) - output <- plotly::add_lines( - output, + plotly_object <- add_ribbons( + plotly_object = plotly_object, + data = .indicator, x = ~idx, y = ~fastd, + ymin = rep(lower, nrow(.indicator)), + ymax = rep(upper, nrow(.indicator)), + color = color, + alpha = alpha, + dash = c("solid", "dot", "dot"), legendgroup = "stochastic_fast", - name = "Stochastic %D (Fast)" + name = c("Stochastic %D (Fast)", "Lower", "Upper"), + showlegend = TRUE ) - output <- add_title( - x = output, - text = "Fast Stochastic" - ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Fast Stochastic" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_STOCHRSI.R b/R/ta_STOCHRSI.R index be8eed63b..8d65e336b 100644 --- a/R/ta_STOCHRSI.R +++ b/R/ta_STOCHRSI.R @@ -157,13 +157,18 @@ stochastic_relative_strength_index.plotly <- function( n_rsi = 10, fast_k = 5, fast_d_MAtype = SMA(n = 10), + lower = 20, + upper = 80, + color = "lightgray", + alpha = 0.7, ... ) { ## input arguments fast_d_MAtype <- fast_d_MAtype - ## prepare series - ## from + ## prepare univariate + ## series for stochastic + ## relative strength index x <- as.data.frame( series( x = x, @@ -173,22 +178,29 @@ stochastic_relative_strength_index.plotly <- function( ) ) - ## indicator + ## calculate indicator + ## and return as data.frame .indicator <- stochastic_relative_strength_index.default( x = x, - cols = cols, + cols = rebuild_formula( + names(x) + ), n = n, n_rsi = n_rsi, fast_k = fast_k, fast_d_MAtype = fast_d_MAtype ) - .indicator$idx <- 1:nrow(.indicator) + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) - # plot - output <- plotly::plot_ly( + ## generate plotly object + ## of the indicator + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~fastk, type = "scatter", mode = "lines", @@ -197,24 +209,32 @@ stochastic_relative_strength_index.plotly <- function( showlegend = TRUE ) - output <- plotly::add_lines( - output, + plotly_object <- add_ribbons( + plotly_object = plotly_object, + data = .indicator, x = ~idx, y = ~fastd, - name = "StochRSI %D", - legendgroup = "stochrsi", - showlegend = TRUE + ymin = rep(lower, nrow(.indicator)), + ymax = rep(upper, nrow(.indicator)), + color = color, + alpha = alpha, + showlegend = TRUE, + dash = c("solid", "dot", "dot"), + name = c("StochRSI %D", "Lower", "Upper"), + legendgroup = "stochrsi" ) - output <- add_title( - x = output, - text = "StochRSI" - ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "StochRSI" + ) + } .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_T3.R b/R/ta_T3.R index 43714a729..a478466e3 100644 --- a/R/ta_T3.R +++ b/R/ta_T3.R @@ -89,7 +89,7 @@ T3.default <- function( colnames(x) <- paste0("T3_", colnames(x)) - x + as.data.frame(x) } #' @rdname T3 @@ -153,8 +153,8 @@ T3.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for T3 x <- as.data.frame( series( x = x, @@ -164,9 +164,21 @@ T3.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- T3.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -175,7 +187,7 @@ T3.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("T3(%d)", n), diff --git a/R/ta_TEMA.R b/R/ta_TEMA.R index 88d4e1352..b63542f87 100644 --- a/R/ta_TEMA.R +++ b/R/ta_TEMA.R @@ -89,7 +89,7 @@ TEMA.default <- function( colnames(x) <- paste0("tema_", colnames(x)) - x + as.data.frame(x) } #' @rdname TEMA @@ -153,8 +153,8 @@ TEMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for TEMA x <- as.data.frame( series( x = x, @@ -164,9 +164,21 @@ TEMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- TEMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -175,7 +187,7 @@ TEMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("TEMA(%d)", n), diff --git a/R/ta_TRIMA.R b/R/ta_TRIMA.R index 1c5dd371a..7b8d03b18 100644 --- a/R/ta_TRIMA.R +++ b/R/ta_TRIMA.R @@ -89,7 +89,7 @@ TRIMA.default <- function( colnames(x) <- paste0("trima_", colnames(x)) - x + as.data.frame(x) } #' @rdname TRIMA @@ -153,8 +153,8 @@ TRIMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for TRIMA x <- as.data.frame( series( x = x, @@ -164,9 +164,21 @@ TRIMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- TRIMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -175,7 +187,7 @@ TRIMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("TRIMA(%d)", n), diff --git a/R/ta_ULTOSC.R b/R/ta_ULTOSC.R index eeeb93d29..bec46d420 100644 --- a/R/ta_ULTOSC.R +++ b/R/ta_ULTOSC.R @@ -109,11 +109,16 @@ ultimate_oscillator.plotly <- function( x, cols, n = c(7, 14, 28), + lower = 30, + upper = 70, + color = "lightgray", + alpha = 0.7, ... ) { - ## prepare series - ## from - x <- as.data.frame( + ## prepare HLC + ## series for ultimate + ## oscillator + HLC <- as.data.frame( series( x = x, formula = cols, @@ -122,14 +127,25 @@ ultimate_oscillator.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculate indicator + ## and return as data.frame + .indicator <- ultimate_oscillator.default( + x = HLC, + cols = rebuild_formula( + names(HLC) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + HLC + ) # plot - output <- plotly::plot_ly( + plotly_object <- subchart( data = .indicator, - x = ~idx, y = ~utimate_oscillator, type = "scatter", mode = "lines", @@ -138,15 +154,31 @@ ultimate_oscillator.plotly <- function( showlegend = TRUE ) - output <- add_title( - x = output, - text = "Ultimate Oscillator" + plotly_object <- add_ribbons( + plotly_object = plotly_object, + data = .indicator, + x = ~idx, + ymin = rep(lower, nrow(.indicator)), + ymax = rep(upper, nrow(.indicator)), + color = color, + alpha = alpha, + showlegend = TRUE, + dash = c("dot", "dot"), + name = c("Lower", "Upper"), + legendgroup = "stochrsi" ) + if (main_chart_exists()) { + plotly_object <- add_title( + x = plotly_object, + text = "Ultimate Oscillator" + ) + } + .plotting_environment$sub <- c( .plotting_environment$sub, - list(output) + list(plotly_object) ) - output + plotly_object } diff --git a/R/ta_VOLUME.R b/R/ta_VOLUME.R new file mode 100644 index 000000000..9c272eb89 --- /dev/null +++ b/R/ta_VOLUME.R @@ -0,0 +1,202 @@ +#' @export +#' @family Volume Indicator +#' +#' @title Trading Volume +#' +#' @templateVar .title Trading Volume +#' @templateVar .author Serkan Korkmaz +#' @templateVar .fun trading_volume +#' +#' @param ma An optional list of moving average specifications. +#' +#' @template description +trading_volume <- function( + x, + cols, + ma, + ... +) { + UseMethod( + "trading_volume" + ) +} + +#' @export +#' +#' @usage NULL +#' +#' @rdname trading_volume +#' @aliases trading_volume +volume <- trading_volume + +#' @rdname trading_volume +#' @usage NULL +#' @export +trading_volume.default <- function( + x, + cols, + ma, + ... +) { + ## default behaviour is to + ## check if its a numeric vector + ## + ## No coercing here as it might + ## lead to overflow + x <- series( + x = cols, + default = ~volume, + data = x, + ... + ) + + ## 0) validate input + ## and stop the script + ## if conditions are not + ## met + if (!missing(ma)) { + xx <- vapply( + ma, + FUN = function(ma_) { + .Call( + "impl_ta_MA", + x[[1]], + ma_$n, + ma_$maType + ) + }, + FUN.VALUE = double(nrow(x)), + USE.NAMES = TRUE + ) + + x <- as.data.frame( + cbind(x, xx) + ) + } + + x +} + +#' @rdname trading_volume +#' @usage NULL +#' @export +trading_volume.numeric <- function( + x, + cols, + ma, + ... +) { + if (!missing(cols)) { + warning( + "'cols' have been passed but is unused in for vectors" + ) + } + + NextMethod() +} + + +#' @rdname trading_volume +#' @usage NULL +#' @export +trading_volume.data.frame <- function( + x, + cols, + ma, + ... +) { + as.data.frame( + NextMethod() + ) +} + +#' @rdname trading_volume +#' @usage NULL +#' @export +trading_volume.matrix <- function( + x, + cols, + ma, + ... +) { + as.matrix( + NextMethod() + ) +} + +#' @rdname trading_volume +#' @usage NULL +#' @export +trading_volume.plotly <- function( + x, + cols, + ma, + ... +) { + ## prepare univariate + ## series for trading_volume + x <- as.data.frame( + series( + x = x, + formula = cols, + default = ~ open + close + volume, + ... + ) + ) + + ## calculator indicator + ## and return as data.frame + .indicator <- trading_volume.default( + x = x, + cols = rebuild_formula( + x = names(x)[names(x) %in% "volume"] + ), + ma = ma + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) + + .indicator$direction <- x$open >= x$close + + ## construct chart + chart_theme <- .chart_theme() + + plotly_object <- subchart( + data = .indicator, + y = ~volume, + color = ~direction, + colors = c( + chart_theme$bull_color, + chart_theme$bear_color + ), + type = 'bar', + showlegend = FALSE + ) + + ## only chart the smoothing lines + ## if passed + if (!missing(ma)) { + for (i in 2:(ncol(.indicator) - 2)) { + plotly_object <- plotly::add_trace( + plotly_object, + data = .indicator, + x = ~idx, + y = .indicator[[i]], + type = "scatter", + mode = "lines", + inherit = FALSE + ) + } + } + + .plotting_environment$sub <- c( + .plotting_environment$sub, + list(plotly_object) + ) + + plotly_object +} diff --git a/R/ta_WMA.R b/R/ta_WMA.R index 08875c93c..b440a5664 100644 --- a/R/ta_WMA.R +++ b/R/ta_WMA.R @@ -89,7 +89,7 @@ WMA.default <- function( colnames(x) <- paste0("wma_", colnames(x)) - x + as.data.frame(x) } #' @rdname WMA @@ -153,8 +153,8 @@ WMA.plotly <- function( n = 10, ... ) { - ## prepare series - ## from + ## prepare univariate + ## series for WMA x <- as.data.frame( series( x = x, @@ -164,9 +164,21 @@ WMA.plotly <- function( ) ) - ## indicator - .indicator <- as.data.frame(NextMethod()) - .indicator$idx <- 1:nrow(.indicator) + ## calculator indicator + ## and return as data.frame + .indicator <- WMA.default( + x = x, + cols = rebuild_formula( + x = names(x) + ), + n = n + ) + + ## add x-axis conditional on whether + ## the data have been subsetted or not + .indicator$idx <- add_idx( + x + ) for (i in 1:ncol(x)) { local({ @@ -175,7 +187,7 @@ WMA.plotly <- function( .plotting_environment$main, data = .indicator, x = ~idx, - y = ~ .indicator[, j], + y = ~ .indicator[[j]], type = "scatter", mode = "lines", name = sprintf("WMA(%d)", n), diff --git a/R/utils.R b/R/utils.R index 9bf1da01b..bc5bbf310 100644 --- a/R/utils.R +++ b/R/utils.R @@ -181,3 +181,88 @@ reclass <- function(x, ...) { is.formula <- function(x) { inherits(x, "formula") } + +## extract input name +input_name <- function(x) { + if (is.call(x) && as.character(x[[1L]]) %in% c("::", ":::")) { + x <- x[[3L]] + } + deparse(x) +} + +rebuild_formula <- function( + x, + exclude = "idx" +) { + if (!is.character(x)) { + x <- names(x) + } + ## this function removes + ## idx and rebuilds the passed + ## series as formulas + idx <- grepl( + pattern = exclude, + x = x, + ignore.case = TRUE + ) + + stats::reformulate( + x[!idx] + ) +} + +add_idx <- function(x) { + ## store idx + idx <- .plotting_environment$idx$label + + if (!is.null(idx)) { + idx[ + if (is.null(attributes(x)$subset)) { + 1:nrow(x) + } else { + attributes(x)$subset + } + ] + } else { + 1:nrow(x) + } +} + +to_title <- function( + x +) { + ## remove underscores + ## if preset + x <- gsub(pattern = "_", replacement = " ", x = x) + gsub("\\b(.)", "\\U\\1", tolower(x), perl = TRUE) +} + + +has_arg <- function(name) { + ## shamelessly stolen from + ## {methods} + aname <- as.character(substitute(name)) + fnames <- names( + formals( + sys.function(sys.parent()) + ) + ) + + if (is.na(match(aname, fnames))) { + if (is.na(match("...", fnames))) { + FALSE + } else { + dotsCall <- eval(quote(substitute(list(...))), sys.parent()) + !is.na(match(aname, names(dotsCall))) + } + } else { + eval(substitute(!missing(name)), sys.frame(sys.parent())) + } +} + + +## main chart called +## function +main_chart_exists <- function() { + !is.null(.plotting_environment$main) +} diff --git a/README.Rmd b/README.Rmd index 290bbabe9..c1a03a76e 100644 --- a/README.Rmd +++ b/README.Rmd @@ -6,19 +6,20 @@ output: github_document ```{r setup, include = FALSE} # set options -Sys.setenv(OPENSSL_CONF="/dev/null") +Sys.setenv(OPENSSL_CONF = "/dev/null") knitr::opts_chunk$set( - collapse = FALSE, - comment = "#>", - fig.path = "man/figures/README-", - message = FALSE, - warning = FALSE, - echo = FALSE + collapse = TRUE, + comment = "#>", + fig.path = "man/figures/README-", + fig.dpi = 120, + message = FALSE, + warning = FALSE, + echo = FALSE ) ``` -# {talib}: R bindings for [TA-Lib](https://github.com/TA-Lib/ta-lib) +# {talib}: A Technical Analysis and Candlestick Pattern Library in R [![R-CMD-check](https://github.com/serkor1/ta-lib-R/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/serkor1/ta-lib-R/actions/workflows/R-CMD-check.yaml) @@ -27,85 +28,100 @@ knitr::opts_chunk$set( [![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/last-month/talib?color=blue)](https://r-pkg.org/pkg/talib) -[{talib}]() provides high-performance R bindings to the [TA-Lib](https://github.com/TA-Lib/ta-lib) C-library for Technical Analysis indicators, Candlestick patterns and interactive charting via [{plotly}](). +[{talib}](https://serkor1.github.io/ta-lib-R/) is an `R`-package for Technical Analysis and algorithmic Candlestick pattern recognition built on the `C` library [TA-Lib](https://github.com/TA-Lib/ta-lib). [{talib}](https://serkor1.github.io/ta-lib-R/) extends [{TTR}](https://github.com/joshuaulrich/TTR) by adding Candlestick pattern recognition to the pool of available indicators, and interactive charts via [{plotly}](https://github.com/plotly/plotly.R). -## Installation +[TA-Lib](https://github.com/TA-Lib/ta-lib) supports 200+ indicators for Technical Analysis and Candlestick Patterns, all of which are available in [{talib}](https://serkor1.github.io/ta-lib-R/). -### Stable version -```{r devel_install, echo = TRUE, eval = FALSE} -pak::pak("talib") -``` +## Types of Indicators and Interface -### Development version +In the core C library functions are named as `TA_INDICATOR()` and `TA_CDLPATTERN()` for indicators and patterns respectively. In the `Python`-wrapper the functions are named `INDICATOR()` and `CDLPATTERN()`---but this `R` package follows the [tidyverse styleguide](https://style.tidyverse.org/) and therefore the naming is inconsistent with the core library and the Python wrapper. See below for an example of the mapping: -The development version can be installed by recursive cloning the repository and using the available build tools as follows: +
-```shell -git clone --recursive https://github.com/serkor1/ta-lib-R.git -cd ta-lib-R -make build +| Function Group | TA-Lib (core) | {talib} | +|:----------------------|:---------------------|:---------------------------| +| Overlap Studies |`TA_BBANDS()` | `bollinger_bands()` | +| Momentum Indicators |`TA_CCI()` | `commodity_channel_index()`| +| Volume Indicators |`TA_OBV()` | `on_balance_volume()` | +| Volatility Indicators | `TA_ATR()` | `average_true_range()` | +| Price Transform | `TA_AVGPRICE()` | `average_price()` | +| Cycle Indicators | `TA_HT_SINE()` | `ht_sine_wave()` | +| Pattern Recognition | `TA_CDLHANGINGMAN()` | `hanging_man()` | + +
+ +However, each function in [{talib}](https://serkor1.github.io/ta-lib-R/) is aliased so its consistent with the remaining ecosystem. See below: + +```{r, echo = TRUE} +all.equal( + target = talib::bollinger_bands(talib::BTC), + current = talib::BBANDS(talib::BTC) +) ``` -Use `make` to see package-level build-tools. +The aliases are exported but are not a part of the documentation, but they behave exactly the same as the main functions as demonstrated above. ## Basic Usage +Below are an example on how to use [{talib}](https://serkor1.github.io/ta-lib-R/) to calculate an indicator and charting it. + ### Indicators -This is a basic example which shows you how to solve a common problem: -```{r indicator, echo = TRUE} +```{r, echo = TRUE} ## calculate bollinger ## bands tail( - talib::bollinger_bands( - talib::BTC - ) + talib::bollinger_bands( + talib::BTC + ) ) ``` ### Charting -```{r charting, fig.align = 'center', fig.dpi = 180, echo = TRUE} -library(talib) - -## calculate bollinger -## bands -x <- talib::BTC +```{r charting, fig.align='center', echo=TRUE} { - ## chart Bitcoin - ## with candlesticks - talib::chart( - x = x - ) - - ## add bollinger bands - ## to the chart - talib::indicator( - FUN = talib::SMA, - cols = ~ close + open - ) - - ## add bollinger bands - ## to the chart - talib::indicator( - FUN = talib::bollinger_bands - ) - - ## add RSI indicator - ## to the chart - talib::indicator( - FUN = talib::relative_strength_index - ) - - ## add harami indicators - ## to the chart - talib::indicator( - FUN = talib::harami - ) + ## main chart + talib::chart( + talib::BTC, + ## optional idx-argument + ## for adding dates to chart + idx = rownames(talib::BTC) + ) + + ## add bollinger bands + ## to chart + talib::indicator( + talib::bollinger_bands + ) } + ``` +## Installation + +[TA-Lib](https://github.com/TA-Lib/ta-lib) is vendored in [{talib}](https://serkor1.github.io/ta-lib-R/) via `CMake`, so it is not necessary to have [TA-Lib](https://github.com/TA-Lib/ta-lib) pre-installed.[^1] + +### Stable version +```{r devel_install, echo = TRUE, eval = FALSE} +pak::pak("talib") +``` + +### Development version + +The development version can be installed by recursive cloning the repository and using the available build tools as follows: + +```shell +git clone --recursive https://github.com/serkor1/ta-lib-R.git +cd ta-lib-R +make build +``` + +Use `make` to see package-level build-tools. + ## Code of Conduct -Please note that [{talib}]() is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. \ No newline at end of file +Please note that [{talib}](https://serkor1.github.io/ta-lib-R/) is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. + +[^1]: Some systems (Windows in particular) may require you to explicitly install and link `CMake` for [{talib}](https://serkor1.github.io/ta-lib-R/) to build properly. \ No newline at end of file diff --git a/README.md b/README.md index 94a8e0fbc..c9dc647c1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# {talib}: R bindings for [TA-Lib](https://github.com/TA-Lib/ta-lib) +# {talib}: A Technical Analysis and Candlestick Pattern Library in R @@ -14,103 +14,138 @@ status](https://www.r-pkg.org/badges/version/talib)](https://CRAN.R-project.org/ downloads](https://cranlogs.r-pkg.org/badges/last-month/talib?color=blue)](https://r-pkg.org/pkg/talib) -[{talib}]() provides high-performance R bindings to the -[TA-Lib](https://github.com/TA-Lib/ta-lib) C-library for Technical -Analysis indicators, Candlestick patterns and interactive charting via -[{plotly}](). - -## Installation - -### Stable version +[{talib}](https://serkor1.github.io/ta-lib-R/) is an `R`-package for +Technical Analysis and algorithmic Candlestick pattern recognition built +on the `C` library [TA-Lib](https://github.com/TA-Lib/ta-lib). +[{talib}](https://serkor1.github.io/ta-lib-R/) extends +[{TTR}](https://github.com/joshuaulrich/TTR) by adding Candlestick +pattern recognition to the pool of available indicators, and interactive +charts via [{plotly}](https://github.com/plotly/plotly.R). + +[TA-Lib](https://github.com/TA-Lib/ta-lib) supports 200+ indicators for +Technical Analysis and Candlestick Patterns, all of which are available +in [{talib}](https://serkor1.github.io/ta-lib-R/). + +## Types of Indicators and Interface + +In the core C library functions are named as `TA_INDICATOR()` and +`TA_CDLPATTERN()` for indicators and patterns respectively. In the +`Python`-wrapper the functions are named `INDICATOR()` and +`CDLPATTERN()`—but this `R` package follows the [tidyverse +styleguide](https://style.tidyverse.org/) and therefore the naming is +inconsistent with the core library and the Python wrapper. See below for +an example of the mapping: + +
+ +| Function Group | TA-Lib (core) | {talib} | +|:----------------------|:---------------------|:----------------------------| +| Overlap Studies | `TA_BBANDS()` | `bollinger_bands()` | +| Momentum Indicators | `TA_CCI()` | `commodity_channel_index()` | +| Volume Indicators | `TA_OBV()` | `on_balance_volume()` | +| Volatility Indicators | `TA_ATR()` | `average_true_range()` | +| Price Transform | `TA_AVGPRICE()` | `average_price()` | +| Cycle Indicators | `TA_HT_SINE()` | `ht_sine_wave()` | +| Pattern Recognition | `TA_CDLHANGINGMAN()` | `hanging_man()` | + +
+ +However, each function in [{talib}](https://serkor1.github.io/ta-lib-R/) +is aliased so its consistent with the remaining ecosystem. See below: ``` r -pak::pak("talib") -``` - -### Development version - -The development version can be installed by recursive cloning the -repository and using the available build tools as follows: - -``` shell -git clone --recursive https://github.com/serkor1/ta-lib-R.git -cd ta-lib-R -make build +all.equal( + target = talib::bollinger_bands(talib::BTC), + current = talib::BBANDS(talib::BTC) +) +#> [1] TRUE ``` -Use `make` to see package-level build-tools. +The aliases are exported but are not a part of the documentation, but +they behave exactly the same as the main functions as demonstrated +above. ## Basic Usage -### Indicators +Below are an example on how to use +[{talib}](https://serkor1.github.io/ta-lib-R/) to calculate an indicator +and charting it. -This is a basic example which shows you how to solve a common problem: +### Indicators ``` r ## calculate bollinger ## bands tail( - talib::bollinger_bands( - talib::BTC - ) + talib::bollinger_bands( + talib::BTC + ) ) +#> upper middle lower +#> 361 106812.14 99260.81 91709.48 +#> 362 104471.11 98218.27 91965.44 +#> 363 100874.66 97021.36 93168.05 +#> 364 99891.29 96519.09 93146.89 +#> 365 99875.94 96136.93 92397.91 +#> 366 99720.50 95622.57 91524.65 ``` - #> upper middle lower - #> 361 106812.14 99260.81 91709.48 - #> 362 104471.11 98218.27 91965.44 - #> 363 100874.66 97021.36 93168.05 - #> 364 99891.29 96519.09 93146.89 - #> 365 99875.94 96136.93 92397.91 - #> 366 99720.50 95622.57 91524.65 - ### Charting ``` r -library(talib) - -## calculate bollinger -## bands -x <- talib::BTC { - ## chart Bitcoin - ## with candlesticks - talib::chart( - x = x - ) - - ## add bollinger bands - ## to the chart - talib::indicator( - FUN = talib::SMA, - cols = ~ close + open - ) - - ## add bollinger bands - ## to the chart - talib::indicator( - FUN = talib::bollinger_bands - ) - - ## add RSI indicator - ## to the chart - talib::indicator( - FUN = talib::relative_strength_index - ) - - ## add harami indicators - ## to the chart - talib::indicator( - FUN = talib::harami - ) + ## main chart + talib::chart( + talib::BTC, + ## optional idx-argument + ## for adding dates to chart + idx = rownames(talib::BTC) + ) + + ## add bollinger bands + ## to chart + talib::indicator( + talib::bollinger_bands + ) } ``` +## Installation + +[TA-Lib](https://github.com/TA-Lib/ta-lib) is vendored in +[{talib}](https://serkor1.github.io/ta-lib-R/) via `CMake`, so it is not +necessary to have [TA-Lib](https://github.com/TA-Lib/ta-lib) +pre-installed.[^1] + +### Stable version + +``` r +pak::pak("talib") +``` + +### Development version + +The development version can be installed by recursive cloning the +repository and using the available build tools as follows: + +``` shell +git clone --recursive https://github.com/serkor1/ta-lib-R.git +cd ta-lib-R +make build +``` + +Use `make` to see package-level build-tools. + ## Code of Conduct -Please note that [{talib}]() is released with a [Contributor Code of +Please note that [{talib}](https://serkor1.github.io/ta-lib-R/) is +released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms. + +[^1]: Some systems (Windows in particular) may require you to explicitly + install and link `CMake` for + [{talib}](https://serkor1.github.io/ta-lib-R/) to build properly. diff --git a/man/chaikin_AD_line.Rd b/man/chaikin_AD_line.Rd index 26e94e7b5..dceacc987 100644 --- a/man/chaikin_AD_line.Rd +++ b/man/chaikin_AD_line.Rd @@ -62,7 +62,8 @@ utils::tail(output) \seealso{ Other Volume Indicator: \code{\link{chaikin_AD_oscillator}()}, -\code{\link{on_balance_volume}()} +\code{\link{on_balance_volume}()}, +\code{\link{trading_volume}()} } \author{ Serkan Korkmaz diff --git a/man/chaikin_AD_oscillator.Rd b/man/chaikin_AD_oscillator.Rd index 816cc45bc..9fa7e6129 100644 --- a/man/chaikin_AD_oscillator.Rd +++ b/man/chaikin_AD_oscillator.Rd @@ -66,7 +66,8 @@ utils::tail(output) \seealso{ Other Volume Indicator: \code{\link{chaikin_AD_line}()}, -\code{\link{on_balance_volume}()} +\code{\link{on_balance_volume}()}, +\code{\link{trading_volume}()} } \author{ Serkan Korkmaz diff --git a/man/chart.Rd b/man/chart.Rd index 461c5672e..181c7ab9b 100644 --- a/man/chart.Rd +++ b/man/chart.Rd @@ -4,13 +4,17 @@ \alias{chart} \title{Chart} \usage{ -chart(x, type = "candlestick", ...) +chart(x, type = "candlestick", idx = NULL, title, ...) } \arguments{ \item{x}{An OHLC object to be charted.} \item{type}{A \link{character} of \link{length} 1. Either \code{candlestick} or \code{ohlc}.} +\item{idx}{A \link{vector} with the same \link{length} of \code{x}. If passed it will replace the x-axis labels. See \code{vignette("charting")} for more details.} + +\item{title}{An optional \link{character} vector of \link{length} 1.} + \item{...}{Parameters passed into \link[plotly:plot_ly]{plotly::plot_ly}} } \description{ diff --git a/man/figures/README-charting-1.png b/man/figures/README-charting-1.png index 92dee688f..a8b21d835 100644 Binary files a/man/figures/README-charting-1.png and b/man/figures/README-charting-1.png differ diff --git a/man/figures/README-unnamed-chunk-3-1.png b/man/figures/README-unnamed-chunk-3-1.png new file mode 100644 index 000000000..bcf777dd0 Binary files /dev/null and b/man/figures/README-unnamed-chunk-3-1.png differ diff --git a/man/on_balance_volume.Rd b/man/on_balance_volume.Rd index 3c6b7e140..db9fcac69 100644 --- a/man/on_balance_volume.Rd +++ b/man/on_balance_volume.Rd @@ -57,7 +57,8 @@ utils::tail(output) \seealso{ Other Volume Indicator: \code{\link{chaikin_AD_line}()}, -\code{\link{chaikin_AD_oscillator}()} +\code{\link{chaikin_AD_oscillator}()}, +\code{\link{trading_volume}()} } \author{ Serkan Korkmaz diff --git a/man/subchart.Rd b/man/subchart.Rd new file mode 100644 index 000000000..51db8b0fa --- /dev/null +++ b/man/subchart.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/chart_elements.R +\name{subchart} +\alias{subchart} +\title{subchart} +\usage{ +subchart(data, ...) +} +\arguments{ +\item{data}{\link{data.frame}} + +\item{...}{arguments passed onto \link[plotly:plot_ly]{plotly::plot_ly}} +} +\description{ +subchart +} +\details{ +A helper function for creating subcharts with prespecified +xaxis and x values +} +\keyword{internal} diff --git a/man/trading_volume.Rd b/man/trading_volume.Rd new file mode 100644 index 000000000..e42e39b1e --- /dev/null +++ b/man/trading_volume.Rd @@ -0,0 +1,75 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ta_VOLUME.R +\name{trading_volume} +\alias{trading_volume} +\alias{volume} +\alias{trading_volume.default} +\alias{trading_volume.numeric} +\alias{trading_volume.data.frame} +\alias{trading_volume.matrix} +\alias{trading_volume.plotly} +\title{Trading Volume} +\usage{ +trading_volume(x, cols, ma, ...) +} +\arguments{ +\item{x}{An OHLC-V series that is coercible to \link{data.frame}. The function assumes that all columns are named in lowercase and order invariant.} + +\item{cols}{An optional \link{formula} passed into \link{model.frame}. If passed into indicators based on univariate series, the function calculates indicators for each element in 'cols'. For indicators based on multivariate series, it will alter the calculation itself. See \code{vignette("talib")} for more details.} + +\item{ma}{An optional list of moving average specifications.} + +\item{...}{Additional parameters passed into \link{model.frame}} +} +\description{ +The \code{trading_volume()} is a generic S3 function that builds upon 'type-safe'-esque workflows limited to classes in in base \code{R}, and the package-wide +dependencies. Ie. \link{class} in, \link{class} out. Each method is a soft wrapper of \link{model.frame} and therefore the OHLC-V series must be coercible to a \link{data.frame}. +This rule does not transfer to indicators that uses univariate series, unless passed as a 1-column \link{data.frame} or \link{matrix}. In such cases, if univariate series +is passed as a \link{vector} the function calculates the indicator 'as is', and returns a \link{data.frame} if the indicator itself is also a univariate series. + +The indicator, by default, follows its mathematical definition. However, the \code{cols} argument allows for simple rearrangement of the definition by passing relevant +columns in a custom order. Refer to the details-section for more on the calculation of the indicators. +} +\examples{ +## load Bitcoin (BTC) +## series +data(BTC, package = "talib") + +## calculate the indicator +## for Bitcoin (BTC) +output <- talib::trading_volume(BTC) + +## display the results +utils::tail(output) + +## visualize the indicator +## with candlesticks +## +## see ?talib::chart or ?talib::indicator +## for more details +{ + ## chart OHLC-V + ## series with candlesticks + talib::chart(BTC) + + ## chart indicator + ## with default values + talib::indicator( + talib::trading_volume + ) +} +} +\seealso{ +Other Volume Indicator: +\code{\link{chaikin_AD_line}()}, +\code{\link{chaikin_AD_oscillator}()}, +\code{\link{on_balance_volume}()} +} +\author{ +Serkan Korkmaz +} +\concept{Volume Indicator} +\concept{algorithmic trading} +\concept{finance} +\concept{technical analysis} +\concept{trading} diff --git a/vignettes/charting.Rmd b/vignettes/charting.Rmd new file mode 100644 index 000000000..c9ca7363e --- /dev/null +++ b/vignettes/charting.Rmd @@ -0,0 +1,147 @@ +--- +title: "Interactive Financial Charts" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Interactive Financial Charts} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +author: Serkan Korkmaz +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + out.width = "100%", + out.height = "680", + fig.align = "center" +) +``` + +## Price Charts + +### Candlestick Chart + +```{r} +talib::chart( + x = talib::NVDA, + type = "candlestick" +) +``` + +### OHLC Chart +```{r} +talib::chart( + x = talib::BTC, + type = "ohlc" +) +``` + +By default the `chart`-function inherits name of the argument `x` as the title. This can be modified via the `title`-argument. + +```{r} +talib::chart( + x = talib::BTC, + type = "ohlc", + title = "SPDR S&P 500 ETF Trust" +) +``` + +## Charting indicators + +The various indicators can be added to the price chart---or charted seperately---with the `indicator`-function. The `indicator`-function will attach itself to the last chart. + +```{r} +talib::indicator( + FUN = talib::MACD +) +``` + +If you have already called the `chart`-function, and want to plot the indicator seperately you will have to clear the existing chart---this is done by calling `talib::chart()` without any arguments. The indicator can now be re-charted using the `indicator`-function. + +```{r} +{ + ## clear the chart + ## by calling talib::chart() + ## without any arguments + talib::chart() + + ## rechart the indicator + ## directly + talib::indicator( + FUN = talib::MACD, + data = talib::BTC + ) +} +``` + +Notice here that you have to pass a `data` argument via `...` which gets passed downstream to `MACD`. + +## Modifying charts + +The charts can be globally modified via `options` use `?talib::chart` to see the full range of modifications available for the charting. Below is an example on how to modify the color scheme of the charts. + +```{r} +## modify options +## to create charts in +## light and color-deficiency mode +options( + talib.chart.dark = FALSE, + talib.chart.deficieny = TRUE +) + +{ + ## price chart + ## with defaults + talib::chart( + talib::SPY + ) + + ## add RSI indicator + talib::indicator( + FUN = talib::RSI + ) + + ## add Bollinger Bands + talib::indicator( + FUN = talib::BBANDS + ) + +} +``` + +### Modifying x-axis labels + +Internally `chart()` and `indicator()` are working on the range of the the data---ie. `1:nrow(data)`---to easy the process of subsetting and for the efficiency. The x-axis can be labelled with dates from the data via the `idx`-argument. + +```{r} +{ + talib::chart( + x = talib::BTC, + idx = rownames(talib::BTC) + ) +} +``` + +### Charting Subsets + +The downstream indicator functions uses `model.frame` as the main function. This is useful in cases where the interest lies in indicators across a specific range without wanting to subset the data itself, or if you want to change indicators over time. + +```{r} +{ + talib::chart( + x = talib::BTC, + idx = rownames(talib::BTC) + ) + + talib::indicator( + talib::BBANDS, + subset = 1:nrow(talib::BTC) %in% c(50:100) + ) + + talib::indicator( + talib::ACCBANDS, + subset = 1:nrow(talib::BTC) %in% c(101:151) + ) +} +```