diff --git a/.github/workflows/remote-install.yaml b/.github/workflows/remote-install.yaml index 4ed686e05..fe38a7e99 100644 --- a/.github/workflows/remote-install.yaml +++ b/.github/workflows/remote-install.yaml @@ -13,6 +13,7 @@ on: paths: - 'configure' - 'configure.win' + workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -21,7 +22,9 @@ concurrency: permissions: read-all jobs: - R-CMD-check: + ## Vanilla remote install - verifies pak::pak("serkor1/ta-lib-R") + ## works on a clean runner with no compiler-wrapping in ~/.R/Makevars. + Remote-Install: runs-on: ${{ matrix.config.os }} name: ${{ matrix.config.os }} (${{ matrix.config.r }}) @@ -31,19 +34,19 @@ jobs: matrix: config: ## macOS - - {os: macos-latest, r: 'devel', http-user-agent: 'release'} - {os: macos-latest, r: 'release'} - {os: macos-latest, r: 'oldrel-1'} + - {os: macos-latest, r: 'oldrel-2'} ## windows - - {os: windows-latest, r: 'devel', http-user-agent: 'release'} - {os: windows-latest, r: 'release'} - {os: windows-latest, r: 'oldrel-1'} - + - {os: windows-latest, r: 'oldrel-2'} + # Ubuntu - - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} - {os: ubuntu-latest, r: 'release'} - {os: ubuntu-latest, r: 'oldrel-1'} + - {os: ubuntu-latest, r: 'oldrel-2'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} @@ -72,3 +75,105 @@ jobs: - name: Calculate an indicator run: talib::bollinger_bands(talib::BTC) shell: Rscript {0} + + ## Remote install with ccache configured in ~/.R/Makevars - regression + ## guard for https://github.com/serkor1/ta-lib-R/issues/57, where installs + ## with `CC = ccache gcc` in Makevars hit + ## "/usr/bin/ccache: invalid option -- 'D'" because the configure script + ## passed `CMAKE_C_COMPILER=ccache` and CMake then invoked ccache with + ## raw `-D` definitions. + Remote-Install-ccache: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}, ccache) + + strategy: + fail-fast: false + matrix: + config: + ## macOS + - {os: macos-latest, r: 'release'} + - {os: macos-latest, r: 'oldrel-1'} + - {os: macos-latest, r: 'oldrel-2'} + + ## windows + - {os: windows-latest, r: 'release'} + - {os: windows-latest, r: 'oldrel-1'} + - {os: windows-latest, r: 'oldrel-2'} + + # Ubuntu + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + - {os: ubuntu-latest, r: 'oldrel-2'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - name: Install ccache (Linux) + if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get install -y ccache + shell: bash + + - name: Install ccache (macOS) + if: runner.os == 'macOS' + run: brew install ccache + shell: bash + + - name: Install ccache (Windows) + if: runner.os == 'Windows' + run: choco install ccache -y --no-progress + shell: pwsh + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::pak any::plotly any::devtools any::roxygen2 + needs: check + + - name: Configure ~/.R/Makevars to use ccache + run: | + dir <- path.expand(file.path("~", ".R")) + dir.create(dir, recursive = TRUE, showWarnings = FALSE) + name <- if (.Platform$OS.type == "windows") "Makevars.win" else "Makevars" + if (Sys.info()[["sysname"]] == "Darwin") { + cc <- "clang"; cxx <- "clang++" + } else { + cc <- "gcc"; cxx <- "g++" + } + path <- file.path(dir, name) + writeLines( + c(paste0("CC=ccache ", cc), + paste0("CXX=ccache ", cxx)), + path + ) + cat("--- ", path, " ---\n", sep = "") + cat(readLines(path), sep = "\n"); cat("\n") + shell: Rscript {0} + + - name: Reset ccache statistics + run: ccache --zero-stats + shell: bash + + - name: Install {talib} + run: pak::pak("serkor1/ta-lib-R") + shell: Rscript {0} + + - name: Show ccache statistics + if: always() + run: ccache -s + shell: bash + + - name: Calculate an indicator + run: talib::bollinger_bands(talib::BTC) + shell: Rscript {0} \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index a75f75351..b165ba4a1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: talib Title: Interface to 'TA-Lib' for Technical Analysis and Candlestick Patterns -Version: 0.9-2 +Version: 0.9-3 Authors@R: c( person( given = "Serkan", diff --git a/Makefile b/Makefile index 012624b1b..687f4028a 100644 --- a/Makefile +++ b/Makefile @@ -80,20 +80,21 @@ pkgdown-preview: ## Preview {pkgdown} documetation @Rscript -e "pkgdown::preview_site()" bench: ## Run benchmark(s) - @echo -e "Running benchmark..." + @echo -e "Running full benchmark suite (overhead + TTR comparison)..." @echo -e "" - @Rscript ./benchmark/benchmark-overhead.R + @Rscript ./benchmark/run-all.R @echo -e "" - @echo -e "Benchmark information:" - @echo -e " -baseline: no R overhead" - @echo -e " -data.frame: data.frame methods" - @echo -e " -baseline: matrix methods" + @echo -e "Rendering benchmark/README.Rmd..." @cd benchmark && Rscript -e "rmarkdown::render('README.Rmd', output_format = rmarkdown::github_document(html_preview = FALSE), clean = TRUE)" - -n ?= 1e6 -bench-data: ## Generate data for benchmark(s) - @Rscript ./benchmark/benchmark-data.R $(n) +bench-overhead: ## Run only the overhead benchmark + @Rscript ./benchmark/benchmark-overhead.R + +bench-ttr: ## Run only the talib-vs-TTR benchmark + @Rscript ./benchmark/benchmark-ttr.R + +bench-plots: ## Regenerate plots from existing RDS results + @Rscript ./benchmark/benchmark-plots.R validate: ## Validate R output against TA-Lib core @PKG_CFLAGS="-Isrc/ta-lib/local/include -Isrc/ta-lib/local/include/ta-lib" \ diff --git a/NAMESPACE b/NAMESPACE index 0175c495d..90d8b5b0d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -841,6 +841,7 @@ export(kicking_baby_length) export(ladder_bottom) export(long_legged_doji) export(long_line) +export(lookback) export(marubozu) export(mat_hold) export(matching_low) diff --git a/NEWS.md b/NEWS.md index 3ef42aab3..f5cca55cb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,22 @@ +# version 0.9-3 + +## improvements + +* A new function for pre-calculating the lookback-period has been implemented. It can be used as follows: + +```R +talib::lookback( + FUN = talib::SMA, + n = 10, + x = talib::BTC +) +``` + +The function returns the minimum required lookback for calculating the indicator. +Its use-case is customized control-flows for downstream wrappers and/or packages that declares dependency on {talib}. + +## bug-fixes + # version 0.9-2 ## improvements diff --git a/R/lookback.R b/R/lookback.R new file mode 100644 index 000000000..fabc081bb --- /dev/null +++ b/R/lookback.R @@ -0,0 +1,126 @@ +#' @export +#' @family Utility +#' +#' Calculate lookback period +#' +#' @description +#' The function calculates the lookback period for a given +#' indicator. +#' Its primarily meant as a helper function for downstream packages +#' that wants to use a customized control-flow. +#' +#' @examples +#' ## calculate the lookback +#' ## for the bollinger bands +#' talib::lookback( +#' talib::bollinger_bands, +#' n = 20, +#' x = talib::BTC +#' ) +#' +#' @param FUN A [call] or [function]. +#' @param ... Additional parameters passed into the indicator function. See examples for more details. +#' +#' @concept finance +#' @concept technical analysis +#' @concept trading +#' @concept algorithmic trading +#' +#' +#' @author Serkan Korkmaz +#' +#' @returns +#' The minimum lookback required to calculate the indicator. +#' If the indicator specification and input data are invalid the function returns [NA], otherwise it returns an [integer] of [length] 1. +lookback <- function( + FUN, + ... +) { + ## store {talib} as a namespace + ## so the function can be found + ## (*_lookback is not exported) + ns <- getNamespace( + "talib" + ) + + ## extract the function call + ## as-is + FUN <- substitute( + FUN + ) + + ## important distinction with substitute: + ## pkg::foo() -> call + ## foo -> function + if (is.call(FUN)) { + FUN <- FUN[[length(FUN)]] + } + + ## all exported indicators has + ## a _lookback post-fix which handles + ## the lookback calculation + FUN <- paste0( + as.character(FUN), + "_lookback" + ) + + if (!exists(FUN, envir = ns, mode = "function", inherits = FALSE)) { + ## strip FUN to get + ## the basename of the passed + ## function + FUN <- gsub( + pattern = "_lookback", + replacement = "", + x = FUN + ) + + ## stop the function with + ## a hard error. + ## TODO: Consider the case for + ## custom indicators, wrapper functions + ## or exported functions that does not have + ## a lookback-calculation. + stop( + "No indicator named `", + FUN, + "` was found.", + call. = FALSE + ) + } + + FUN <- get( + FUN, + envir = ns, + mode = "function", + inherits = FALSE + ) + + ## upstream returns -1 + ## for invalid input data + ## relative to the indicator; + ## SMA, for example, requires at + ## minimum two data points to calculate + ## given n = 2 - and three, if n = 3. + ## + ## if the indicator and input are not + ## satisfying this constraint upstream + ## returns -1, ie. not applicable. + minimum_lookback <- do.call( + FUN, + args = list(...) + ) + + if (minimum_lookback == -1) { + return(NA) + } + + ## volume, for example, returns + ## a lookback of 0 if calculated without + ## moving averages - wrap the lookback + ## in max() as a safety precaution + max( + minimum_lookback, + 1, + na.rm = TRUE + ) +} diff --git a/R/ta_ACCBANDS.R b/R/ta_ACCBANDS.R index 82a7d53ff..3866b181e 100644 --- a/R/ta_ACCBANDS.R +++ b/R/ta_ACCBANDS.R @@ -122,6 +122,38 @@ acceleration_bands.matrix <- function( ) } +#' @usage NULL +ACCBANDS_lookback <- acceleration_bands_lookback <- function( + x, + cols, + n = 20, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_ACCBANDS_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases acceleration_bands diff --git a/R/ta_AD.R b/R/ta_AD.R index e0198b404..9b61ff832 100644 --- a/R/ta_AD.R +++ b/R/ta_AD.R @@ -116,6 +116,37 @@ chaikin_accumulation_distribution_line.matrix <- function( ) } +#' @usage NULL +AD_lookback <- chaikin_accumulation_distribution_line_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close + volume, + data = x, + ... + ) + + .Call( + C_impl_ta_AD_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases chaikin_accumulation_distribution_line diff --git a/R/ta_ADOSC.R b/R/ta_ADOSC.R index 953c06a71..1b16d6f7c 100644 --- a/R/ta_ADOSC.R +++ b/R/ta_ADOSC.R @@ -132,6 +132,41 @@ chaikin_accumulation_distribution_oscillator.matrix <- function( ) } +#' @usage NULL +ADOSC_lookback <- chaikin_accumulation_distribution_oscillator_lookback <- function( + x, + cols, + fast = 3, + slow = 10, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close + volume, + data = x, + ... + ) + + .Call( + C_impl_ta_ADOSC_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + as.integer(fast), + as.integer(slow) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases chaikin_accumulation_distribution_oscillator diff --git a/R/ta_ADX.R b/R/ta_ADX.R index 9e0b41026..a2a6495cc 100644 --- a/R/ta_ADX.R +++ b/R/ta_ADX.R @@ -122,6 +122,38 @@ average_directional_movement_index.matrix <- function( ) } +#' @usage NULL +ADX_lookback <- average_directional_movement_index_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_ADX_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases average_directional_movement_index diff --git a/R/ta_ADXR.R b/R/ta_ADXR.R index 1022b36c4..9923e53c4 100644 --- a/R/ta_ADXR.R +++ b/R/ta_ADXR.R @@ -122,6 +122,38 @@ average_directional_movement_index_rating.matrix <- function( ) } +#' @usage NULL +ADXR_lookback <- average_directional_movement_index_rating_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_ADXR_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases average_directional_movement_index_rating diff --git a/R/ta_APO.R b/R/ta_APO.R index 907ac26ed..ea308b0ee 100644 --- a/R/ta_APO.R +++ b/R/ta_APO.R @@ -137,6 +137,40 @@ absolute_price_oscillator.matrix <- function( ) } +#' @usage NULL +APO_lookback <- absolute_price_oscillator_lookback <- function( + x, + cols, + fast = 12, + slow = 26, + ma = SMA(n = 9), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_APO_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(fast), + as.integer(slow), + ma$maType + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases absolute_price_oscillator @@ -172,16 +206,8 @@ absolute_price_oscillator.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_AROON.R b/R/ta_AROON.R index 0cedc7c0f..3b0578853 100644 --- a/R/ta_AROON.R +++ b/R/ta_AROON.R @@ -121,6 +121,37 @@ aroon.matrix <- function( ) } +#' @usage NULL +AROON_lookback <- aroon_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_AROON_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases aroon diff --git a/R/ta_AROONOSC.R b/R/ta_AROONOSC.R index 81452a9d0..08a4598a1 100644 --- a/R/ta_AROONOSC.R +++ b/R/ta_AROONOSC.R @@ -121,6 +121,37 @@ aroon_oscillator.matrix <- function( ) } +#' @usage NULL +AROONOSC_lookback <- aroon_oscillator_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_AROONOSC_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases aroon_oscillator diff --git a/R/ta_ATR.R b/R/ta_ATR.R index 9c1dbbd60..d98f65450 100644 --- a/R/ta_ATR.R +++ b/R/ta_ATR.R @@ -122,6 +122,38 @@ average_true_range.matrix <- function( ) } +#' @usage NULL +ATR_lookback <- average_true_range_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_ATR_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases average_true_range diff --git a/R/ta_AVGPRICE.R b/R/ta_AVGPRICE.R index 666fd0c66..efcf7e5c2 100644 --- a/R/ta_AVGPRICE.R +++ b/R/ta_AVGPRICE.R @@ -115,3 +115,35 @@ average_price.matrix <- function( ... ) } + +#' @usage NULL +AVGPRICE_lookback <- average_price_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_AVGPRICE_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ## splice:lookback:end + ) +} diff --git a/R/ta_BBANDS.R b/R/ta_BBANDS.R index a02d74e4c..c49b9fca5 100644 --- a/R/ta_BBANDS.R +++ b/R/ta_BBANDS.R @@ -145,6 +145,42 @@ bollinger_bands.matrix <- function( ) } +#' @usage NULL +BBANDS_lookback <- bollinger_bands_lookback <- function( + x, + cols, + ma = SMA(n = 5), + sd = 2, + sd_down, + sd_up, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_BBANDS_lookback, + ## splice:lookback:start + constructed_series[[1]], + ma$n, + as.double(sd_up %or% sd), + as.double(sd_down %or% sd), + ma$maType + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases bollinger_bands @@ -182,16 +218,8 @@ bollinger_bands.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_BETA.R b/R/ta_BETA.R index 78eec1b70..ee3a6c935 100644 --- a/R/ta_BETA.R +++ b/R/ta_BETA.R @@ -49,8 +49,13 @@ rolling_beta.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -72,6 +77,27 @@ rolling_beta.numeric <- function( na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +BETA_lookback <- rolling_beta_lookback <- function( + x, + y, + n = 5 +) { + .Call( + C_impl_ta_BETA_lookback, + ## splice:lookback:start + as.double(x), + as.double(y), + as.integer(n) + ## splice:lookback:end + ) } diff --git a/R/ta_BOP.R b/R/ta_BOP.R index 2e313da83..3e1d5e84a 100644 --- a/R/ta_BOP.R +++ b/R/ta_BOP.R @@ -116,6 +116,37 @@ balance_of_power.matrix <- function( ) } +#' @usage NULL +BOP_lookback <- balance_of_power_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_BOP_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases balance_of_power diff --git a/R/ta_CCI.R b/R/ta_CCI.R index e4b93a9f3..c7c1a04e1 100644 --- a/R/ta_CCI.R +++ b/R/ta_CCI.R @@ -122,6 +122,38 @@ commodity_channel_index.matrix <- function( ) } +#' @usage NULL +CCI_lookback <- commodity_channel_index_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CCI_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases commodity_channel_index diff --git a/R/ta_CDL2CROWS.R b/R/ta_CDL2CROWS.R index 1697f99c1..c79c556d3 100644 --- a/R/ta_CDL2CROWS.R +++ b/R/ta_CDL2CROWS.R @@ -132,6 +132,36 @@ two_crows.matrix <- function( NextMethod() } +#' @usage NULL +CDL2CROWS_lookback <- two_crows_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDL2CROWS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases two_crows #' diff --git a/R/ta_CDL3BLACKCROWS.R b/R/ta_CDL3BLACKCROWS.R index a3f46cea1..4aeb645d0 100644 --- a/R/ta_CDL3BLACKCROWS.R +++ b/R/ta_CDL3BLACKCROWS.R @@ -132,6 +132,36 @@ three_black_crows.matrix <- function( NextMethod() } +#' @usage NULL +CDL3BLACKCROWS_lookback <- three_black_crows_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDL3BLACKCROWS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases three_black_crows #' diff --git a/R/ta_CDL3INSIDE.R b/R/ta_CDL3INSIDE.R index cd46e3309..cf1dffd32 100644 --- a/R/ta_CDL3INSIDE.R +++ b/R/ta_CDL3INSIDE.R @@ -132,6 +132,36 @@ three_inside.matrix <- function( NextMethod() } +#' @usage NULL +CDL3INSIDE_lookback <- three_inside_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDL3INSIDE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases three_inside #' diff --git a/R/ta_CDL3LINESTRIKE.R b/R/ta_CDL3LINESTRIKE.R index ac54cdbbf..13dc938f2 100644 --- a/R/ta_CDL3LINESTRIKE.R +++ b/R/ta_CDL3LINESTRIKE.R @@ -132,6 +132,36 @@ three_line_strike.matrix <- function( NextMethod() } +#' @usage NULL +CDL3LINESTRIKE_lookback <- three_line_strike_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDL3LINESTRIKE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases three_line_strike #' diff --git a/R/ta_CDL3OUTSIDE.R b/R/ta_CDL3OUTSIDE.R index 872ce706b..13afe056f 100644 --- a/R/ta_CDL3OUTSIDE.R +++ b/R/ta_CDL3OUTSIDE.R @@ -132,6 +132,36 @@ three_outside.matrix <- function( NextMethod() } +#' @usage NULL +CDL3OUTSIDE_lookback <- three_outside_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDL3OUTSIDE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases three_outside #' diff --git a/R/ta_CDL3STARSINSOUTH.R b/R/ta_CDL3STARSINSOUTH.R index bf6fbc1ec..2215b1764 100644 --- a/R/ta_CDL3STARSINSOUTH.R +++ b/R/ta_CDL3STARSINSOUTH.R @@ -132,6 +132,36 @@ three_stars_in_the_south.matrix <- function( NextMethod() } +#' @usage NULL +CDL3STARSINSOUTH_lookback <- three_stars_in_the_south_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDL3STARSINSOUTH_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases three_stars_in_the_south #' diff --git a/R/ta_CDL3WHITESOLDIERS.R b/R/ta_CDL3WHITESOLDIERS.R index 3d800b3f7..9e4c35425 100644 --- a/R/ta_CDL3WHITESOLDIERS.R +++ b/R/ta_CDL3WHITESOLDIERS.R @@ -132,6 +132,36 @@ three_white_soldiers.matrix <- function( NextMethod() } +#' @usage NULL +CDL3WHITESOLDIERS_lookback <- three_white_soldiers_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDL3WHITESOLDIERS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases three_white_soldiers #' diff --git a/R/ta_CDLABANDONEDBABY.R b/R/ta_CDLABANDONEDBABY.R index 5decd6880..a3ec95c7d 100644 --- a/R/ta_CDLABANDONEDBABY.R +++ b/R/ta_CDLABANDONEDBABY.R @@ -137,6 +137,38 @@ abandoned_baby.matrix <- function( NextMethod() } +#' @usage NULL +CDLABANDONEDBABY_lookback <- abandoned_baby_lookback <- function( + x, + cols, + eps = 0, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLABANDONEDBABY_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + eps + ) +} + #' @usage NULL #' @aliases abandoned_baby #' diff --git a/R/ta_CDLADVANCEBLOCK.R b/R/ta_CDLADVANCEBLOCK.R index 7ffa59eb0..16c10bca5 100644 --- a/R/ta_CDLADVANCEBLOCK.R +++ b/R/ta_CDLADVANCEBLOCK.R @@ -132,6 +132,36 @@ advance_block.matrix <- function( NextMethod() } +#' @usage NULL +CDLADVANCEBLOCK_lookback <- advance_block_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLADVANCEBLOCK_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases advance_block #' diff --git a/R/ta_CDLBELTHOLD.R b/R/ta_CDLBELTHOLD.R index d241985d7..8e3a056d7 100644 --- a/R/ta_CDLBELTHOLD.R +++ b/R/ta_CDLBELTHOLD.R @@ -132,6 +132,36 @@ belt_hold.matrix <- function( NextMethod() } +#' @usage NULL +CDLBELTHOLD_lookback <- belt_hold_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLBELTHOLD_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases belt_hold #' diff --git a/R/ta_CDLBREAKAWAY.R b/R/ta_CDLBREAKAWAY.R index 05fd11f8b..d90f1f10d 100644 --- a/R/ta_CDLBREAKAWAY.R +++ b/R/ta_CDLBREAKAWAY.R @@ -132,6 +132,36 @@ break_away.matrix <- function( NextMethod() } +#' @usage NULL +CDLBREAKAWAY_lookback <- break_away_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLBREAKAWAY_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases break_away #' diff --git a/R/ta_CDLCLOSINGMARUBOZU.R b/R/ta_CDLCLOSINGMARUBOZU.R index 8c12755f5..c26fa3299 100644 --- a/R/ta_CDLCLOSINGMARUBOZU.R +++ b/R/ta_CDLCLOSINGMARUBOZU.R @@ -132,6 +132,36 @@ closing_marubozu.matrix <- function( NextMethod() } +#' @usage NULL +CDLCLOSINGMARUBOZU_lookback <- closing_marubozu_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLCLOSINGMARUBOZU_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases closing_marubozu #' diff --git a/R/ta_CDLCONCEALBABYSWALL.R b/R/ta_CDLCONCEALBABYSWALL.R index 1abe77544..bcccd5ab3 100644 --- a/R/ta_CDLCONCEALBABYSWALL.R +++ b/R/ta_CDLCONCEALBABYSWALL.R @@ -132,6 +132,36 @@ concealing_baby_swallow.matrix <- function( NextMethod() } +#' @usage NULL +CDLCONCEALBABYSWALL_lookback <- concealing_baby_swallow_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLCONCEALBABYSWALL_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases concealing_baby_swallow #' diff --git a/R/ta_CDLCOUNTERATTACK.R b/R/ta_CDLCOUNTERATTACK.R index 3fb8660c4..703654191 100644 --- a/R/ta_CDLCOUNTERATTACK.R +++ b/R/ta_CDLCOUNTERATTACK.R @@ -132,6 +132,36 @@ counter_attack.matrix <- function( NextMethod() } +#' @usage NULL +CDLCOUNTERATTACK_lookback <- counter_attack_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLCOUNTERATTACK_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases counter_attack #' diff --git a/R/ta_CDLDARKCLOUDCOVER.R b/R/ta_CDLDARKCLOUDCOVER.R index b56bd5113..553c1a7c4 100644 --- a/R/ta_CDLDARKCLOUDCOVER.R +++ b/R/ta_CDLDARKCLOUDCOVER.R @@ -137,6 +137,38 @@ dark_cloud_cover.matrix <- function( NextMethod() } +#' @usage NULL +CDLDARKCLOUDCOVER_lookback <- dark_cloud_cover_lookback <- function( + x, + cols, + eps = 0, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLDARKCLOUDCOVER_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + eps + ) +} + #' @usage NULL #' @aliases dark_cloud_cover #' diff --git a/R/ta_CDLDOJI.R b/R/ta_CDLDOJI.R index 2ca3a5002..da7c64f14 100644 --- a/R/ta_CDLDOJI.R +++ b/R/ta_CDLDOJI.R @@ -132,6 +132,36 @@ doji.matrix <- function( NextMethod() } +#' @usage NULL +CDLDOJI_lookback <- doji_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLDOJI_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases doji #' diff --git a/R/ta_CDLDOJISTAR.R b/R/ta_CDLDOJISTAR.R index 9691c0ef6..6a6656a0c 100644 --- a/R/ta_CDLDOJISTAR.R +++ b/R/ta_CDLDOJISTAR.R @@ -132,6 +132,36 @@ doji_star.matrix <- function( NextMethod() } +#' @usage NULL +CDLDOJISTAR_lookback <- doji_star_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLDOJISTAR_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases doji_star #' diff --git a/R/ta_CDLDRAGONFLYDOJI.R b/R/ta_CDLDRAGONFLYDOJI.R index 602530860..bba237b42 100644 --- a/R/ta_CDLDRAGONFLYDOJI.R +++ b/R/ta_CDLDRAGONFLYDOJI.R @@ -132,6 +132,36 @@ dragonfly_doji.matrix <- function( NextMethod() } +#' @usage NULL +CDLDRAGONFLYDOJI_lookback <- dragonfly_doji_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLDRAGONFLYDOJI_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases dragonfly_doji #' diff --git a/R/ta_CDLENGULFING.R b/R/ta_CDLENGULFING.R index 24038dd37..770935ea4 100644 --- a/R/ta_CDLENGULFING.R +++ b/R/ta_CDLENGULFING.R @@ -132,6 +132,36 @@ engulfing.matrix <- function( NextMethod() } +#' @usage NULL +CDLENGULFING_lookback <- engulfing_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLENGULFING_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases engulfing #' diff --git a/R/ta_CDLEVENINGDOJISTAR.R b/R/ta_CDLEVENINGDOJISTAR.R index 907656aa7..d23789049 100644 --- a/R/ta_CDLEVENINGDOJISTAR.R +++ b/R/ta_CDLEVENINGDOJISTAR.R @@ -137,6 +137,38 @@ evening_doji_star.matrix <- function( NextMethod() } +#' @usage NULL +CDLEVENINGDOJISTAR_lookback <- evening_doji_star_lookback <- function( + x, + cols, + eps = 0, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLEVENINGDOJISTAR_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + eps + ) +} + #' @usage NULL #' @aliases evening_doji_star #' diff --git a/R/ta_CDLEVENINGSTAR.R b/R/ta_CDLEVENINGSTAR.R index 944020248..1c6e9db5f 100644 --- a/R/ta_CDLEVENINGSTAR.R +++ b/R/ta_CDLEVENINGSTAR.R @@ -137,6 +137,38 @@ evening_star.matrix <- function( NextMethod() } +#' @usage NULL +CDLEVENINGSTAR_lookback <- evening_star_lookback <- function( + x, + cols, + eps = 0, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLEVENINGSTAR_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + eps + ) +} + #' @usage NULL #' @aliases evening_star #' diff --git a/R/ta_CDLGAPSIDESIDEWHITE.R b/R/ta_CDLGAPSIDESIDEWHITE.R index 50410f78b..1caf72e03 100644 --- a/R/ta_CDLGAPSIDESIDEWHITE.R +++ b/R/ta_CDLGAPSIDESIDEWHITE.R @@ -132,6 +132,36 @@ gaps_side_white.matrix <- function( NextMethod() } +#' @usage NULL +CDLGAPSIDESIDEWHITE_lookback <- gaps_side_white_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLGAPSIDESIDEWHITE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases gaps_side_white #' diff --git a/R/ta_CDLGRAVESTONEDOJI.R b/R/ta_CDLGRAVESTONEDOJI.R index 931163072..3bbf10d63 100644 --- a/R/ta_CDLGRAVESTONEDOJI.R +++ b/R/ta_CDLGRAVESTONEDOJI.R @@ -132,6 +132,36 @@ gravestone_doji.matrix <- function( NextMethod() } +#' @usage NULL +CDLGRAVESTONEDOJI_lookback <- gravestone_doji_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLGRAVESTONEDOJI_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases gravestone_doji #' diff --git a/R/ta_CDLHAMMER.R b/R/ta_CDLHAMMER.R index bf74d0411..f129e628a 100644 --- a/R/ta_CDLHAMMER.R +++ b/R/ta_CDLHAMMER.R @@ -132,6 +132,36 @@ hammer.matrix <- function( NextMethod() } +#' @usage NULL +CDLHAMMER_lookback <- hammer_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHAMMER_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases hammer #' diff --git a/R/ta_CDLHANGINGMAN.R b/R/ta_CDLHANGINGMAN.R index 427325177..464d17b63 100644 --- a/R/ta_CDLHANGINGMAN.R +++ b/R/ta_CDLHANGINGMAN.R @@ -132,6 +132,36 @@ hanging_man.matrix <- function( NextMethod() } +#' @usage NULL +CDLHANGINGMAN_lookback <- hanging_man_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHANGINGMAN_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases hanging_man #' diff --git a/R/ta_CDLHARAMI.R b/R/ta_CDLHARAMI.R index 0e1a5403f..d27ef9645 100644 --- a/R/ta_CDLHARAMI.R +++ b/R/ta_CDLHARAMI.R @@ -132,6 +132,36 @@ harami.matrix <- function( NextMethod() } +#' @usage NULL +CDLHARAMI_lookback <- harami_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHARAMI_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases harami #' diff --git a/R/ta_CDLHARAMICROSS.R b/R/ta_CDLHARAMICROSS.R index 749141b97..73e808e05 100644 --- a/R/ta_CDLHARAMICROSS.R +++ b/R/ta_CDLHARAMICROSS.R @@ -132,6 +132,36 @@ harami_cross.matrix <- function( NextMethod() } +#' @usage NULL +CDLHARAMICROSS_lookback <- harami_cross_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHARAMICROSS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases harami_cross #' diff --git a/R/ta_CDLHIGHWAVE.R b/R/ta_CDLHIGHWAVE.R index 17100b4e3..6c344513d 100644 --- a/R/ta_CDLHIGHWAVE.R +++ b/R/ta_CDLHIGHWAVE.R @@ -132,6 +132,36 @@ high_wave.matrix <- function( NextMethod() } +#' @usage NULL +CDLHIGHWAVE_lookback <- high_wave_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHIGHWAVE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases high_wave #' diff --git a/R/ta_CDLHIKKAKE.R b/R/ta_CDLHIKKAKE.R index f5e218e47..620a7d9b6 100644 --- a/R/ta_CDLHIKKAKE.R +++ b/R/ta_CDLHIKKAKE.R @@ -132,6 +132,36 @@ hikakke.matrix <- function( NextMethod() } +#' @usage NULL +CDLHIKKAKE_lookback <- hikakke_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHIKKAKE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases hikakke #' diff --git a/R/ta_CDLHIKKAKEMOD.R b/R/ta_CDLHIKKAKEMOD.R index 43fdab5ee..d5bc0e46b 100644 --- a/R/ta_CDLHIKKAKEMOD.R +++ b/R/ta_CDLHIKKAKEMOD.R @@ -132,6 +132,36 @@ hikakke_mod.matrix <- function( NextMethod() } +#' @usage NULL +CDLHIKKAKEMOD_lookback <- hikakke_mod_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHIKKAKEMOD_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases hikakke_mod #' diff --git a/R/ta_CDLHOMINGPIGEON.R b/R/ta_CDLHOMINGPIGEON.R index 82566f6b6..aa59697fa 100644 --- a/R/ta_CDLHOMINGPIGEON.R +++ b/R/ta_CDLHOMINGPIGEON.R @@ -132,6 +132,36 @@ homing_pigeon.matrix <- function( NextMethod() } +#' @usage NULL +CDLHOMINGPIGEON_lookback <- homing_pigeon_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLHOMINGPIGEON_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases homing_pigeon #' diff --git a/R/ta_CDLIDENTICAL3CROWS.R b/R/ta_CDLIDENTICAL3CROWS.R index 6d53e8b46..f53a60013 100644 --- a/R/ta_CDLIDENTICAL3CROWS.R +++ b/R/ta_CDLIDENTICAL3CROWS.R @@ -132,6 +132,36 @@ three_identical_crows.matrix <- function( NextMethod() } +#' @usage NULL +CDLIDENTICAL3CROWS_lookback <- three_identical_crows_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLIDENTICAL3CROWS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases three_identical_crows #' diff --git a/R/ta_CDLINNECK.R b/R/ta_CDLINNECK.R index 0ad45078d..ae93052c8 100644 --- a/R/ta_CDLINNECK.R +++ b/R/ta_CDLINNECK.R @@ -132,6 +132,36 @@ in_neck.matrix <- function( NextMethod() } +#' @usage NULL +CDLINNECK_lookback <- in_neck_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLINNECK_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases in_neck #' diff --git a/R/ta_CDLINVERTEDHAMMER.R b/R/ta_CDLINVERTEDHAMMER.R index 46b28e3a1..6013b62b9 100644 --- a/R/ta_CDLINVERTEDHAMMER.R +++ b/R/ta_CDLINVERTEDHAMMER.R @@ -132,6 +132,36 @@ inverted_hammer.matrix <- function( NextMethod() } +#' @usage NULL +CDLINVERTEDHAMMER_lookback <- inverted_hammer_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLINVERTEDHAMMER_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases inverted_hammer #' diff --git a/R/ta_CDLKICKING.R b/R/ta_CDLKICKING.R index 079feb387..027447af4 100644 --- a/R/ta_CDLKICKING.R +++ b/R/ta_CDLKICKING.R @@ -132,6 +132,36 @@ kicking.matrix <- function( NextMethod() } +#' @usage NULL +CDLKICKING_lookback <- kicking_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLKICKING_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases kicking #' diff --git a/R/ta_CDLKICKINGBYLENGTH.R b/R/ta_CDLKICKINGBYLENGTH.R index 9e60f5a56..694df66eb 100644 --- a/R/ta_CDLKICKINGBYLENGTH.R +++ b/R/ta_CDLKICKINGBYLENGTH.R @@ -132,6 +132,36 @@ kicking_baby_length.matrix <- function( NextMethod() } +#' @usage NULL +CDLKICKINGBYLENGTH_lookback <- kicking_baby_length_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLKICKINGBYLENGTH_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases kicking_baby_length #' diff --git a/R/ta_CDLLADDERBOTTOM.R b/R/ta_CDLLADDERBOTTOM.R index a43a9cf41..f844980a0 100644 --- a/R/ta_CDLLADDERBOTTOM.R +++ b/R/ta_CDLLADDERBOTTOM.R @@ -132,6 +132,36 @@ ladder_bottom.matrix <- function( NextMethod() } +#' @usage NULL +CDLLADDERBOTTOM_lookback <- ladder_bottom_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLLADDERBOTTOM_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases ladder_bottom #' diff --git a/R/ta_CDLLONGLEGGEDDOJI.R b/R/ta_CDLLONGLEGGEDDOJI.R index 342e5c135..86e1274b1 100644 --- a/R/ta_CDLLONGLEGGEDDOJI.R +++ b/R/ta_CDLLONGLEGGEDDOJI.R @@ -132,6 +132,36 @@ long_legged_doji.matrix <- function( NextMethod() } +#' @usage NULL +CDLLONGLEGGEDDOJI_lookback <- long_legged_doji_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLLONGLEGGEDDOJI_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases long_legged_doji #' diff --git a/R/ta_CDLLONGLINE.R b/R/ta_CDLLONGLINE.R index 7c907f73c..57c3adbd3 100644 --- a/R/ta_CDLLONGLINE.R +++ b/R/ta_CDLLONGLINE.R @@ -132,6 +132,36 @@ long_line.matrix <- function( NextMethod() } +#' @usage NULL +CDLLONGLINE_lookback <- long_line_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLLONGLINE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases long_line #' diff --git a/R/ta_CDLMARUBOZU.R b/R/ta_CDLMARUBOZU.R index fe592ac37..a5f6eb9f5 100644 --- a/R/ta_CDLMARUBOZU.R +++ b/R/ta_CDLMARUBOZU.R @@ -132,6 +132,36 @@ marubozu.matrix <- function( NextMethod() } +#' @usage NULL +CDLMARUBOZU_lookback <- marubozu_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLMARUBOZU_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases marubozu #' diff --git a/R/ta_CDLMATCHINGLOW.R b/R/ta_CDLMATCHINGLOW.R index c1aab57d1..92b4f5280 100644 --- a/R/ta_CDLMATCHINGLOW.R +++ b/R/ta_CDLMATCHINGLOW.R @@ -132,6 +132,36 @@ matching_low.matrix <- function( NextMethod() } +#' @usage NULL +CDLMATCHINGLOW_lookback <- matching_low_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLMATCHINGLOW_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases matching_low #' diff --git a/R/ta_CDLMATHOLD.R b/R/ta_CDLMATHOLD.R index afe98eabf..15ea8f526 100644 --- a/R/ta_CDLMATHOLD.R +++ b/R/ta_CDLMATHOLD.R @@ -137,6 +137,38 @@ mat_hold.matrix <- function( NextMethod() } +#' @usage NULL +CDLMATHOLD_lookback <- mat_hold_lookback <- function( + x, + cols, + eps = 0, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLMATHOLD_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + eps + ) +} + #' @usage NULL #' @aliases mat_hold #' diff --git a/R/ta_CDLMORNINGDOJISTAR.R b/R/ta_CDLMORNINGDOJISTAR.R index 5aa05cb81..6de0f62d1 100644 --- a/R/ta_CDLMORNINGDOJISTAR.R +++ b/R/ta_CDLMORNINGDOJISTAR.R @@ -137,6 +137,38 @@ morning_doji_star.matrix <- function( NextMethod() } +#' @usage NULL +CDLMORNINGDOJISTAR_lookback <- morning_doji_star_lookback <- function( + x, + cols, + eps = 0, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLMORNINGDOJISTAR_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + eps + ) +} + #' @usage NULL #' @aliases morning_doji_star #' diff --git a/R/ta_CDLMORNINGSTAR.R b/R/ta_CDLMORNINGSTAR.R index d2fd17206..aa5404d8d 100644 --- a/R/ta_CDLMORNINGSTAR.R +++ b/R/ta_CDLMORNINGSTAR.R @@ -137,6 +137,38 @@ morning_star.matrix <- function( NextMethod() } +#' @usage NULL +CDLMORNINGSTAR_lookback <- morning_star_lookback <- function( + x, + cols, + eps = 0, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLMORNINGSTAR_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + eps + ) +} + #' @usage NULL #' @aliases morning_star #' diff --git a/R/ta_CDLONNECK.R b/R/ta_CDLONNECK.R index 4d9ed7fe6..dde28b5b1 100644 --- a/R/ta_CDLONNECK.R +++ b/R/ta_CDLONNECK.R @@ -132,6 +132,36 @@ on_neck.matrix <- function( NextMethod() } +#' @usage NULL +CDLONNECK_lookback <- on_neck_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLONNECK_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases on_neck #' diff --git a/R/ta_CDLPIERCING.R b/R/ta_CDLPIERCING.R index 5df9f1330..a5fda9945 100644 --- a/R/ta_CDLPIERCING.R +++ b/R/ta_CDLPIERCING.R @@ -132,6 +132,36 @@ piercing.matrix <- function( NextMethod() } +#' @usage NULL +CDLPIERCING_lookback <- piercing_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLPIERCING_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases piercing #' diff --git a/R/ta_CDLRICKSHAWMAN.R b/R/ta_CDLRICKSHAWMAN.R index f96e13579..093178afd 100644 --- a/R/ta_CDLRICKSHAWMAN.R +++ b/R/ta_CDLRICKSHAWMAN.R @@ -132,6 +132,36 @@ rickshaw_man.matrix <- function( NextMethod() } +#' @usage NULL +CDLRICKSHAWMAN_lookback <- rickshaw_man_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLRICKSHAWMAN_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases rickshaw_man #' diff --git a/R/ta_CDLRISEFALL3METHODS.R b/R/ta_CDLRISEFALL3METHODS.R index 116fa14ee..279bd00c3 100644 --- a/R/ta_CDLRISEFALL3METHODS.R +++ b/R/ta_CDLRISEFALL3METHODS.R @@ -132,6 +132,36 @@ rise_fall_3_methods.matrix <- function( NextMethod() } +#' @usage NULL +CDLRISEFALL3METHODS_lookback <- rise_fall_3_methods_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLRISEFALL3METHODS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases rise_fall_3_methods #' diff --git a/R/ta_CDLSEPARATINGLINES.R b/R/ta_CDLSEPARATINGLINES.R index e0ff5f769..878c9d226 100644 --- a/R/ta_CDLSEPARATINGLINES.R +++ b/R/ta_CDLSEPARATINGLINES.R @@ -132,6 +132,36 @@ separating_lines.matrix <- function( NextMethod() } +#' @usage NULL +CDLSEPARATINGLINES_lookback <- separating_lines_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLSEPARATINGLINES_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases separating_lines #' diff --git a/R/ta_CDLSHOOTINGSTAR.R b/R/ta_CDLSHOOTINGSTAR.R index a99cea3f1..ba4fadd0a 100644 --- a/R/ta_CDLSHOOTINGSTAR.R +++ b/R/ta_CDLSHOOTINGSTAR.R @@ -132,6 +132,36 @@ shooting_star.matrix <- function( NextMethod() } +#' @usage NULL +CDLSHOOTINGSTAR_lookback <- shooting_star_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLSHOOTINGSTAR_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases shooting_star #' diff --git a/R/ta_CDLSHORTLINE.R b/R/ta_CDLSHORTLINE.R index c5dd4c8bf..749d270fe 100644 --- a/R/ta_CDLSHORTLINE.R +++ b/R/ta_CDLSHORTLINE.R @@ -132,6 +132,36 @@ short_line.matrix <- function( NextMethod() } +#' @usage NULL +CDLSHORTLINE_lookback <- short_line_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLSHORTLINE_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases short_line #' diff --git a/R/ta_CDLSPINNINGTOP.R b/R/ta_CDLSPINNINGTOP.R index cfb3609dd..f21273aac 100644 --- a/R/ta_CDLSPINNINGTOP.R +++ b/R/ta_CDLSPINNINGTOP.R @@ -132,6 +132,36 @@ spinning_top.matrix <- function( NextMethod() } +#' @usage NULL +CDLSPINNINGTOP_lookback <- spinning_top_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLSPINNINGTOP_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases spinning_top #' diff --git a/R/ta_CDLSTALLEDPATTERN.R b/R/ta_CDLSTALLEDPATTERN.R index 472c88d01..855622010 100644 --- a/R/ta_CDLSTALLEDPATTERN.R +++ b/R/ta_CDLSTALLEDPATTERN.R @@ -132,6 +132,36 @@ stalled_pattern.matrix <- function( NextMethod() } +#' @usage NULL +CDLSTALLEDPATTERN_lookback <- stalled_pattern_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLSTALLEDPATTERN_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases stalled_pattern #' diff --git a/R/ta_CDLSTICKSANDWICH.R b/R/ta_CDLSTICKSANDWICH.R index 75b91ed4c..2c27022f4 100644 --- a/R/ta_CDLSTICKSANDWICH.R +++ b/R/ta_CDLSTICKSANDWICH.R @@ -132,6 +132,36 @@ stick_sandwich.matrix <- function( NextMethod() } +#' @usage NULL +CDLSTICKSANDWICH_lookback <- stick_sandwich_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLSTICKSANDWICH_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases stick_sandwich #' diff --git a/R/ta_CDLTAKURI.R b/R/ta_CDLTAKURI.R index da480fd62..313cd90bf 100644 --- a/R/ta_CDLTAKURI.R +++ b/R/ta_CDLTAKURI.R @@ -132,6 +132,36 @@ takuri.matrix <- function( NextMethod() } +#' @usage NULL +CDLTAKURI_lookback <- takuri_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLTAKURI_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases takuri #' diff --git a/R/ta_CDLTASUKIGAP.R b/R/ta_CDLTASUKIGAP.R index 5ecd06cad..4a6e25fe7 100644 --- a/R/ta_CDLTASUKIGAP.R +++ b/R/ta_CDLTASUKIGAP.R @@ -132,6 +132,36 @@ tasuki_gap.matrix <- function( NextMethod() } +#' @usage NULL +CDLTASUKIGAP_lookback <- tasuki_gap_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLTASUKIGAP_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases tasuki_gap #' diff --git a/R/ta_CDLTHRUSTING.R b/R/ta_CDLTHRUSTING.R index 08b496e3e..3c2341de1 100644 --- a/R/ta_CDLTHRUSTING.R +++ b/R/ta_CDLTHRUSTING.R @@ -132,6 +132,36 @@ thrusting.matrix <- function( NextMethod() } +#' @usage NULL +CDLTHRUSTING_lookback <- thrusting_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLTHRUSTING_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases thrusting #' diff --git a/R/ta_CDLTRISTAR.R b/R/ta_CDLTRISTAR.R index fb99feeef..8144bea0b 100644 --- a/R/ta_CDLTRISTAR.R +++ b/R/ta_CDLTRISTAR.R @@ -132,6 +132,36 @@ tristar.matrix <- function( NextMethod() } +#' @usage NULL +CDLTRISTAR_lookback <- tristar_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLTRISTAR_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases tristar #' diff --git a/R/ta_CDLUNIQUE3RIVER.R b/R/ta_CDLUNIQUE3RIVER.R index ee608e3ce..a16348018 100644 --- a/R/ta_CDLUNIQUE3RIVER.R +++ b/R/ta_CDLUNIQUE3RIVER.R @@ -132,6 +132,36 @@ unique_3_river.matrix <- function( NextMethod() } +#' @usage NULL +CDLUNIQUE3RIVER_lookback <- unique_3_river_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLUNIQUE3RIVER_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases unique_3_river #' diff --git a/R/ta_CDLUPSIDEGAP2CROWS.R b/R/ta_CDLUPSIDEGAP2CROWS.R index 977c2b4e0..35f32c0c5 100644 --- a/R/ta_CDLUPSIDEGAP2CROWS.R +++ b/R/ta_CDLUPSIDEGAP2CROWS.R @@ -132,6 +132,36 @@ upside_gap_2_crows.matrix <- function( NextMethod() } +#' @usage NULL +CDLUPSIDEGAP2CROWS_lookback <- upside_gap_2_crows_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLUPSIDEGAP2CROWS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases upside_gap_2_crows #' diff --git a/R/ta_CDLXSIDEGAP3METHODS.R b/R/ta_CDLXSIDEGAP3METHODS.R index ee6fa3088..3ae89e583 100644 --- a/R/ta_CDLXSIDEGAP3METHODS.R +++ b/R/ta_CDLXSIDEGAP3METHODS.R @@ -132,6 +132,36 @@ xside_gap_3_methods.matrix <- function( NextMethod() } +#' @usage NULL +CDLXSIDEGAP3METHODS_lookback <- xside_gap_3_methods_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_CDLXSIDEGAP3METHODS_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] + ) +} + #' @usage NULL #' @aliases xside_gap_3_methods #' diff --git a/R/ta_CMO.R b/R/ta_CMO.R index 746249e3e..56575b837 100644 --- a/R/ta_CMO.R +++ b/R/ta_CMO.R @@ -120,6 +120,36 @@ chande_momentum_oscillator.matrix <- function( ) } +#' @usage NULL +CMO_lookback <- chande_momentum_oscillator_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_CMO_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases chande_momentum_oscillator @@ -151,16 +181,8 @@ chande_momentum_oscillator.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_CORREL.R b/R/ta_CORREL.R index ebfabfb6a..a4b15df43 100644 --- a/R/ta_CORREL.R +++ b/R/ta_CORREL.R @@ -49,8 +49,13 @@ rolling_correlation.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -72,6 +77,27 @@ rolling_correlation.numeric <- function( na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +CORREL_lookback <- rolling_correlation_lookback <- function( + x, + y, + n = 30 +) { + .Call( + C_impl_ta_CORREL_lookback, + ## splice:lookback:start + as.double(x), + as.double(y), + as.integer(n) + ## splice:lookback:end + ) } diff --git a/R/ta_DEMA.R b/R/ta_DEMA.R index 8dc00b6cf..a52d0f60d 100644 --- a/R/ta_DEMA.R +++ b/R/ta_DEMA.R @@ -163,21 +163,44 @@ double_exponential_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +DEMA_lookback <- double_exponential_moving_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_DEMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases double_exponential_moving_average #' diff --git a/R/ta_DX.R b/R/ta_DX.R index 1db4d604a..22788b760 100644 --- a/R/ta_DX.R +++ b/R/ta_DX.R @@ -122,6 +122,38 @@ directional_movement_index.matrix <- function( ) } +#' @usage NULL +DX_lookback <- directional_movement_index_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_DX_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases directional_movement_index diff --git a/R/ta_EMA.R b/R/ta_EMA.R index e85e4d49c..c9c285f27 100644 --- a/R/ta_EMA.R +++ b/R/ta_EMA.R @@ -163,21 +163,44 @@ exponential_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +EMA_lookback <- exponential_moving_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_EMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases exponential_moving_average #' diff --git a/R/ta_HT_DCPERIOD.R b/R/ta_HT_DCPERIOD.R index e806d99c3..4df7ed2e4 100644 --- a/R/ta_HT_DCPERIOD.R +++ b/R/ta_HT_DCPERIOD.R @@ -113,6 +113,34 @@ dominant_cycle_period.matrix <- function( ) } +#' @usage NULL +HT_DCPERIOD_lookback <- dominant_cycle_period_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_HT_DCPERIOD_lookback, + ## splice:lookback:start + constructed_series[[1]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases dominant_cycle_period @@ -142,16 +170,8 @@ dominant_cycle_period.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_HT_DCPHASE.R b/R/ta_HT_DCPHASE.R index 315e5007b..2b7edbc18 100644 --- a/R/ta_HT_DCPHASE.R +++ b/R/ta_HT_DCPHASE.R @@ -113,6 +113,34 @@ dominant_cycle_phase.matrix <- function( ) } +#' @usage NULL +HT_DCPHASE_lookback <- dominant_cycle_phase_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_HT_DCPHASE_lookback, + ## splice:lookback:start + constructed_series[[1]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases dominant_cycle_phase @@ -142,16 +170,8 @@ dominant_cycle_phase.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_HT_PHASOR.R b/R/ta_HT_PHASOR.R index 27f29560a..88acf387a 100644 --- a/R/ta_HT_PHASOR.R +++ b/R/ta_HT_PHASOR.R @@ -113,6 +113,34 @@ phasor_components.matrix <- function( ) } +#' @usage NULL +HT_PHASOR_lookback <- phasor_components_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_HT_PHASOR_lookback, + ## splice:lookback:start + constructed_series[[1]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases phasor_components @@ -142,16 +170,8 @@ phasor_components.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_HT_SINE.R b/R/ta_HT_SINE.R index dad2622eb..c0f4df3d0 100644 --- a/R/ta_HT_SINE.R +++ b/R/ta_HT_SINE.R @@ -113,6 +113,34 @@ sine_wave.matrix <- function( ) } +#' @usage NULL +HT_SINE_lookback <- sine_wave_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_HT_SINE_lookback, + ## splice:lookback:start + constructed_series[[1]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases sine_wave @@ -142,16 +170,8 @@ sine_wave.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_HT_TRENDLINE.R b/R/ta_HT_TRENDLINE.R index f0051a5a9..ffe15f917 100644 --- a/R/ta_HT_TRENDLINE.R +++ b/R/ta_HT_TRENDLINE.R @@ -113,6 +113,34 @@ trendline.matrix <- function( ) } +#' @usage NULL +HT_TRENDLINE_lookback <- trendline_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_HT_TRENDLINE_lookback, + ## splice:lookback:start + constructed_series[[1]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases trendline @@ -142,16 +170,8 @@ trendline.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_HT_TRENDMODE.R b/R/ta_HT_TRENDMODE.R index dcbbacf1a..3369c1745 100644 --- a/R/ta_HT_TRENDMODE.R +++ b/R/ta_HT_TRENDMODE.R @@ -113,6 +113,34 @@ trend_cycle_mode.matrix <- function( ) } +#' @usage NULL +HT_TRENDMODE_lookback <- trend_cycle_mode_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_HT_TRENDMODE_lookback, + ## splice:lookback:start + constructed_series[[1]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases trend_cycle_mode @@ -142,16 +170,8 @@ trend_cycle_mode.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_IMI.R b/R/ta_IMI.R index 753987df7..741057842 100644 --- a/R/ta_IMI.R +++ b/R/ta_IMI.R @@ -121,6 +121,37 @@ intraday_movement_index.matrix <- function( ) } +#' @usage NULL +IMI_lookback <- intraday_movement_index_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ open + close, + data = x, + ... + ) + + .Call( + C_impl_ta_IMI_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases intraday_movement_index diff --git a/R/ta_KAMA.R b/R/ta_KAMA.R index 5f0f0d315..89af3fc3b 100644 --- a/R/ta_KAMA.R +++ b/R/ta_KAMA.R @@ -163,21 +163,44 @@ kaufman_adaptive_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +KAMA_lookback <- kaufman_adaptive_moving_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_KAMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases kaufman_adaptive_moving_average #' diff --git a/R/ta_MACD.R b/R/ta_MACD.R index 364b16b81..d580e6488 100644 --- a/R/ta_MACD.R +++ b/R/ta_MACD.R @@ -137,6 +137,40 @@ moving_average_convergence_divergence.matrix <- function( ) } +#' @usage NULL +MACD_lookback <- moving_average_convergence_divergence_lookback <- function( + x, + cols, + fast = 12, + slow = 26, + signal = 9, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_MACD_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(fast), + as.integer(slow), + as.integer(signal) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases moving_average_convergence_divergence @@ -172,16 +206,8 @@ moving_average_convergence_divergence.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_MACDEXT.R b/R/ta_MACDEXT.R index 23d99dd0e..6c5fa34f6 100644 --- a/R/ta_MACDEXT.R +++ b/R/ta_MACDEXT.R @@ -140,6 +140,43 @@ extended_moving_average_convergence_divergence.matrix <- function( ) } +#' @usage NULL +MACDEXT_lookback <- extended_moving_average_convergence_divergence_lookback <- function( + x, + cols, + fast = SMA(n = 12), + slow = SMA(n = 26), + signal = SMA(n = 9), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_MACDEXT_lookback, + ## splice:lookback:start + constructed_series[[1]], + fast$n, + fast$maType, + slow$n, + slow$maType, + signal$n, + signal$maType + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases extended_moving_average_convergence_divergence @@ -178,16 +215,8 @@ extended_moving_average_convergence_divergence.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_MACDFIX.R b/R/ta_MACDFIX.R index 636895fc3..2585baeee 100644 --- a/R/ta_MACDFIX.R +++ b/R/ta_MACDFIX.R @@ -121,6 +121,36 @@ fixed_moving_average_convergence_divergence.matrix <- function( ) } +#' @usage NULL +MACDFIX_lookback <- fixed_moving_average_convergence_divergence_lookback <- function( + x, + cols, + signal = 9, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_MACDFIX_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(signal) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases fixed_moving_average_convergence_divergence @@ -152,16 +182,8 @@ fixed_moving_average_convergence_divergence.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_MAMA.R b/R/ta_MAMA.R index 7918e21e9..f13d758fa 100644 --- a/R/ta_MAMA.R +++ b/R/ta_MAMA.R @@ -182,21 +182,47 @@ mesa_adaptive_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +MAMA_lookback <- mesa_adaptive_moving_average_lookback <- function( + x, + cols, + n = 30, + fast = 0.5, + slow = 0.05, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_MAMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.double(fast), + as.double(slow) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases mesa_adaptive_moving_average #' diff --git a/R/ta_MAX.R b/R/ta_MAX.R index 4f65c5298..f8f6d4097 100644 --- a/R/ta_MAX.R +++ b/R/ta_MAX.R @@ -46,8 +46,13 @@ rolling_max.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -67,6 +72,25 @@ rolling_max.numeric <- function( na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +MAX_lookback <- rolling_max_lookback <- function( + x, + n = 30 +) { + .Call( + C_impl_ta_MAX_lookback, + ## splice:lookback:start + as.double(x), + as.integer(n) + ## splice:lookback:end + ) } diff --git a/R/ta_MEDPRICE.R b/R/ta_MEDPRICE.R index d3dbb04dc..4535323ef 100644 --- a/R/ta_MEDPRICE.R +++ b/R/ta_MEDPRICE.R @@ -113,3 +113,33 @@ median_price.matrix <- function( ... ) } + +#' @usage NULL +MEDPRICE_lookback <- median_price_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_MEDPRICE_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]] + ## splice:lookback:end + ) +} diff --git a/R/ta_MFI.R b/R/ta_MFI.R index 7849841d2..0f6ef5d31 100644 --- a/R/ta_MFI.R +++ b/R/ta_MFI.R @@ -123,6 +123,39 @@ money_flow_index.matrix <- function( ) } +#' @usage NULL +MFI_lookback <- money_flow_index_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close + volume, + data = x, + ... + ) + + .Call( + C_impl_ta_MFI_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases money_flow_index diff --git a/R/ta_MIDPRICE.R b/R/ta_MIDPRICE.R index ef6a798fe..05f071ed6 100644 --- a/R/ta_MIDPRICE.R +++ b/R/ta_MIDPRICE.R @@ -120,3 +120,35 @@ midpoint_price.matrix <- function( ... ) } + +#' @usage NULL +MIDPRICE_lookback <- midpoint_price_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_MIDPRICE_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + as.integer(n) + ## splice:lookback:end + ) +} diff --git a/R/ta_MIN.R b/R/ta_MIN.R index d9535346e..50e8693b8 100644 --- a/R/ta_MIN.R +++ b/R/ta_MIN.R @@ -46,8 +46,13 @@ rolling_min.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -67,6 +72,25 @@ rolling_min.numeric <- function( na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +MIN_lookback <- rolling_min_lookback <- function( + x, + n = 30 +) { + .Call( + C_impl_ta_MIN_lookback, + ## splice:lookback:start + as.double(x), + as.integer(n) + ## splice:lookback:end + ) } diff --git a/R/ta_MINUS_DI.R b/R/ta_MINUS_DI.R index 22dcea0d3..dd54051dd 100644 --- a/R/ta_MINUS_DI.R +++ b/R/ta_MINUS_DI.R @@ -122,6 +122,38 @@ minus_directional_indicator.matrix <- function( ) } +#' @usage NULL +MINUS_DI_lookback <- minus_directional_indicator_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_MINUS_DI_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases minus_directional_indicator diff --git a/R/ta_MINUS_DM.R b/R/ta_MINUS_DM.R index c46367eee..e02717913 100644 --- a/R/ta_MINUS_DM.R +++ b/R/ta_MINUS_DM.R @@ -121,6 +121,37 @@ minus_directional_movement.matrix <- function( ) } +#' @usage NULL +MINUS_DM_lookback <- minus_directional_movement_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_MINUS_DM_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases minus_directional_movement diff --git a/R/ta_MOM.R b/R/ta_MOM.R index df7120207..71a72cb78 100644 --- a/R/ta_MOM.R +++ b/R/ta_MOM.R @@ -120,6 +120,36 @@ momentum.matrix <- function( ) } +#' @usage NULL +MOM_lookback <- momentum_lookback <- function( + x, + cols, + n = 10, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_MOM_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases momentum @@ -151,16 +181,8 @@ momentum.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_NATR.R b/R/ta_NATR.R index aaa630e4a..b4f33977e 100644 --- a/R/ta_NATR.R +++ b/R/ta_NATR.R @@ -122,6 +122,38 @@ normalized_average_true_range.matrix <- function( ) } +#' @usage NULL +NATR_lookback <- normalized_average_true_range_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_NATR_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases normalized_average_true_range diff --git a/R/ta_OBV.R b/R/ta_OBV.R index 829fb3365..0d9b4c0cb 100644 --- a/R/ta_OBV.R +++ b/R/ta_OBV.R @@ -114,6 +114,35 @@ on_balance_volume.matrix <- function( ) } +#' @usage NULL +OBV_lookback <- on_balance_volume_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ close + volume, + data = x, + ... + ) + + .Call( + C_impl_ta_OBV_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases on_balance_volume diff --git a/R/ta_PLUS_DI.R b/R/ta_PLUS_DI.R index 98563a504..3e9022746 100644 --- a/R/ta_PLUS_DI.R +++ b/R/ta_PLUS_DI.R @@ -122,6 +122,38 @@ plus_directional_indicator.matrix <- function( ) } +#' @usage NULL +PLUS_DI_lookback <- plus_directional_indicator_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_PLUS_DI_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases plus_directional_indicator diff --git a/R/ta_PLUS_DM.R b/R/ta_PLUS_DM.R index b24dd5c7e..8f1615dca 100644 --- a/R/ta_PLUS_DM.R +++ b/R/ta_PLUS_DM.R @@ -121,6 +121,37 @@ plus_directional_movement.matrix <- function( ) } +#' @usage NULL +PLUS_DM_lookback <- plus_directional_movement_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_PLUS_DM_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases plus_directional_movement diff --git a/R/ta_PPO.R b/R/ta_PPO.R index 0b54a3a7f..ef11b663d 100644 --- a/R/ta_PPO.R +++ b/R/ta_PPO.R @@ -137,6 +137,40 @@ percentage_price_oscillator.matrix <- function( ) } +#' @usage NULL +PPO_lookback <- percentage_price_oscillator_lookback <- function( + x, + cols, + fast = 12, + slow = 26, + ma = SMA(n = 9), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_PPO_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(fast), + as.integer(slow), + ma$maType + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases percentage_price_oscillator @@ -172,16 +206,8 @@ percentage_price_oscillator.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_ROC.R b/R/ta_ROC.R index 65a5b4325..c050d5464 100644 --- a/R/ta_ROC.R +++ b/R/ta_ROC.R @@ -120,6 +120,36 @@ rate_of_change.matrix <- function( ) } +#' @usage NULL +ROC_lookback <- rate_of_change_lookback <- function( + x, + cols, + n = 10, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_ROC_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases rate_of_change @@ -151,16 +181,8 @@ rate_of_change.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_ROCR.R b/R/ta_ROCR.R index a387f2573..476f46f53 100644 --- a/R/ta_ROCR.R +++ b/R/ta_ROCR.R @@ -120,6 +120,36 @@ ratio_of_change.matrix <- function( ) } +#' @usage NULL +ROCR_lookback <- ratio_of_change_lookback <- function( + x, + cols, + n = 10, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_ROCR_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases ratio_of_change @@ -151,16 +181,8 @@ ratio_of_change.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_RSI.R b/R/ta_RSI.R index 557646de3..b1bec585c 100644 --- a/R/ta_RSI.R +++ b/R/ta_RSI.R @@ -120,6 +120,36 @@ relative_strength_index.matrix <- function( ) } +#' @usage NULL +RSI_lookback <- relative_strength_index_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_RSI_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases relative_strength_index @@ -151,16 +181,8 @@ relative_strength_index.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_SAR.R b/R/ta_SAR.R index 948915275..8698e7a69 100644 --- a/R/ta_SAR.R +++ b/R/ta_SAR.R @@ -130,6 +130,39 @@ parabolic_stop_and_reverse.matrix <- function( ) } +#' @usage NULL +SAR_lookback <- parabolic_stop_and_reverse_lookback <- function( + x, + cols, + acceleration = 0.02, + maximum = 0.2, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_SAR_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + as.double(acceleration), + as.double(maximum) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases parabolic_stop_and_reverse diff --git a/R/ta_SAREXT.R b/R/ta_SAREXT.R index 36b24f643..8229f3c74 100644 --- a/R/ta_SAREXT.R +++ b/R/ta_SAREXT.R @@ -178,6 +178,51 @@ extended_parabolic_stop_and_reverse.matrix <- function( ) } +#' @usage NULL +SAREXT_lookback <- extended_parabolic_stop_and_reverse_lookback <- function( + x, + cols, + init = 0, + offset = 0, + init_long = 0.02, + long = 0.02, + max_long = 0.2, + init_short = 0.02, + short = 0.02, + max_short = 0.2, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low, + data = x, + ... + ) + + .Call( + C_impl_ta_SAREXT_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + init, + offset, + init_long, + long, + max_long, + init_short, + short, + max_short + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases extended_parabolic_stop_and_reverse diff --git a/R/ta_SMA.R b/R/ta_SMA.R index da7f19954..ce9400d98 100644 --- a/R/ta_SMA.R +++ b/R/ta_SMA.R @@ -163,21 +163,44 @@ simple_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +SMA_lookback <- simple_moving_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_SMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases simple_moving_average #' diff --git a/R/ta_STDDEV.R b/R/ta_STDDEV.R index 4bc21d5ad..21ae6b9af 100644 --- a/R/ta_STDDEV.R +++ b/R/ta_STDDEV.R @@ -50,8 +50,13 @@ rolling_standard_deviation.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -73,6 +78,27 @@ rolling_standard_deviation.numeric <- function( na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +STDDEV_lookback <- rolling_standard_deviation_lookback <- function( + x, + n = 5, + k = 1 +) { + .Call( + C_impl_ta_STDDEV_lookback, + ## splice:lookback:start + as.double(x), + as.integer(n), + as.double(k) + ## splice:lookback:end + ) } diff --git a/R/ta_STOCH.R b/R/ta_STOCH.R index 735c6aa5d..c1598beeb 100644 --- a/R/ta_STOCH.R +++ b/R/ta_STOCH.R @@ -141,6 +141,44 @@ stochastic.matrix <- function( ) } +#' @usage NULL +STOCH_lookback <- stochastic_lookback <- function( + x, + cols, + fastk = 5, + slowk = SMA(n = 3), + slowd = SMA(n = 3), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_STOCH_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(fastk), + as.integer(slowk$n), + as.integer(slowk$maType), + as.integer(slowd$n), + as.integer(slowd$maType) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases stochastic diff --git a/R/ta_STOCHF.R b/R/ta_STOCHF.R index 77fe43ad0..28939fc24 100644 --- a/R/ta_STOCHF.R +++ b/R/ta_STOCHF.R @@ -132,6 +132,41 @@ fast_stochastic.matrix <- function( ) } +#' @usage NULL +STOCHF_lookback <- fast_stochastic_lookback <- function( + x, + cols, + fastk = 5, + fastd = SMA(n = 3), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_STOCHF_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(fastk), + as.integer(fastd$n), + as.integer(fastd$maType) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases fast_stochastic diff --git a/R/ta_STOCHRSI.R b/R/ta_STOCHRSI.R index c42c46426..04c9fe201 100644 --- a/R/ta_STOCHRSI.R +++ b/R/ta_STOCHRSI.R @@ -137,6 +137,41 @@ stochastic_relative_strength_index.matrix <- function( ) } +#' @usage NULL +STOCHRSI_lookback <- stochastic_relative_strength_index_lookback <- function( + x, + cols, + n = 14, + fastk = 5, + fastd = SMA(n = 3), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_STOCHRSI_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(n), + as.integer(fastk), + as.integer(fastd$n), + as.integer(fastd$maType) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases stochastic_relative_strength_index @@ -173,16 +208,8 @@ stochastic_relative_strength_index.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_SUM.R b/R/ta_SUM.R index 7cdf8cef3..f8fc6020f 100644 --- a/R/ta_SUM.R +++ b/R/ta_SUM.R @@ -46,8 +46,13 @@ rolling_sum.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -67,6 +72,25 @@ rolling_sum.numeric <- function( na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +SUM_lookback <- rolling_sum_lookback <- function( + x, + n = 30 +) { + .Call( + C_impl_ta_SUM_lookback, + ## splice:lookback:start + as.double(x), + as.integer(n) + ## splice:lookback:end + ) } diff --git a/R/ta_T3.R b/R/ta_T3.R index 34ac9aca2..5d3d00bf6 100644 --- a/R/ta_T3.R +++ b/R/ta_T3.R @@ -173,21 +173,46 @@ t3_exponential_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +T3_lookback <- t3_exponential_moving_average_lookback <- function( + x, + cols, + n = 5, + vfactor = 0.7, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_T3_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n), + as.double(vfactor) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases t3_exponential_moving_average #' diff --git a/R/ta_TEMA.R b/R/ta_TEMA.R index 07c502522..ec7832ffe 100644 --- a/R/ta_TEMA.R +++ b/R/ta_TEMA.R @@ -163,21 +163,44 @@ triple_exponential_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +TEMA_lookback <- triple_exponential_moving_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_TEMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases triple_exponential_moving_average #' diff --git a/R/ta_TRANGE.R b/R/ta_TRANGE.R index 943ca796c..549858324 100644 --- a/R/ta_TRANGE.R +++ b/R/ta_TRANGE.R @@ -115,6 +115,36 @@ true_range.matrix <- function( ) } +#' @usage NULL +TRANGE_lookback <- true_range_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_TRANGE_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]] + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases true_range diff --git a/R/ta_TRIMA.R b/R/ta_TRIMA.R index 5b49db271..1884c1a47 100644 --- a/R/ta_TRIMA.R +++ b/R/ta_TRIMA.R @@ -163,21 +163,44 @@ triangular_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +TRIMA_lookback <- triangular_moving_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_TRIMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases triangular_moving_average #' diff --git a/R/ta_TRIX.R b/R/ta_TRIX.R index 269a686cd..c019ef9ac 100644 --- a/R/ta_TRIX.R +++ b/R/ta_TRIX.R @@ -120,6 +120,36 @@ triple_exponential_average.matrix <- function( ) } +#' @usage NULL +TRIX_lookback <- triple_exponential_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_TRIX_lookback, + ## splice:lookback:start + constructed_series[[1]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases triple_exponential_average @@ -151,16 +181,8 @@ triple_exponential_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_TYPPRICE.R b/R/ta_TYPPRICE.R index a1628d57f..ef6b1f07a 100644 --- a/R/ta_TYPPRICE.R +++ b/R/ta_TYPPRICE.R @@ -114,3 +114,34 @@ typical_price.matrix <- function( ... ) } + +#' @usage NULL +TYPPRICE_lookback <- typical_price_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_TYPPRICE_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]] + ## splice:lookback:end + ) +} diff --git a/R/ta_ULTOSC.R b/R/ta_ULTOSC.R index b9792b5b9..5a41dc974 100644 --- a/R/ta_ULTOSC.R +++ b/R/ta_ULTOSC.R @@ -124,6 +124,40 @@ ultimate_oscillator.matrix <- function( ) } +#' @usage NULL +ULTOSC_lookback <- ultimate_oscillator_lookback <- function( + x, + cols, + n = c(7, 14, 28), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_ULTOSC_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n[1]), + as.integer(n[2]), + as.integer(n[3]) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases ultimate_oscillator diff --git a/R/ta_VAR.R b/R/ta_VAR.R index 092542f11..4b6e9a010 100644 --- a/R/ta_VAR.R +++ b/R/ta_VAR.R @@ -50,8 +50,13 @@ rolling_variance.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -73,6 +78,27 @@ rolling_variance.numeric <- function( na.bridge = na.bridge ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +VAR_lookback <- rolling_variance_lookback <- function( + x, + n = 5, + k = 1 +) { + .Call( + C_impl_ta_VAR_lookback, + ## splice:lookback:start + as.double(x), + as.integer(n), + as.double(k) + ## splice:lookback:end + ) } diff --git a/R/ta_VOLUME.R b/R/ta_VOLUME.R index 11e587d66..e2319d8b1 100644 --- a/R/ta_VOLUME.R +++ b/R/ta_VOLUME.R @@ -128,6 +128,43 @@ trading_volume.matrix <- function( ) } +#' @usage NULL +VOLUME_lookback <- trading_volume_lookback <- function( + x, + cols, + ma = list(SMA(n = 7), SMA(n = 15)), + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ volume + open + close, + data = x, + ... + ) + + .Call( + C_impl_ta_VOLUME_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + lapply( + ma, + function(x) { + as.integer( + unlist(x, use.names = FALSE) + ) + } + ) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases trading_volume @@ -159,16 +196,8 @@ trading_volume.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/R/ta_WCLPRICE.R b/R/ta_WCLPRICE.R index f0e20bbfe..b4940943f 100644 --- a/R/ta_WCLPRICE.R +++ b/R/ta_WCLPRICE.R @@ -114,3 +114,34 @@ weighted_close_price.matrix <- function( ... ) } + +#' @usage NULL +WCLPRICE_lookback <- weighted_close_price_lookback <- function( + x, + cols, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_WCLPRICE_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]] + ## splice:lookback:end + ) +} diff --git a/R/ta_WILLR.R b/R/ta_WILLR.R index 21c0a78de..2f48ea2a9 100644 --- a/R/ta_WILLR.R +++ b/R/ta_WILLR.R @@ -122,6 +122,38 @@ williams_oscillator.matrix <- function( ) } +#' @usage NULL +WILLR_lookback <- williams_oscillator_lookback <- function( + x, + cols, + n = 14, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~ high + low + close, + data = x, + ... + ) + + .Call( + C_impl_ta_WILLR_lookback, + ## splice:lookback:start + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + as.integer(n) + ## splice:lookback:end + ) +} #' @usage NULL #' @aliases williams_oscillator diff --git a/R/ta_WMA.R b/R/ta_WMA.R index e6fcc602a..917817d28 100644 --- a/R/ta_WMA.R +++ b/R/ta_WMA.R @@ -163,21 +163,44 @@ weighted_moving_average.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +WMA_lookback <- weighted_moving_average_lookback <- function( + x, + cols, + n = 30, + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ~close, + data = x, + ... + ) + + .Call( + C_impl_ta_WMA_lookback, + ## splice:lookback:start + as.double(constructed_series[[1]]), + as.integer(n) + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases weighted_moving_average #' diff --git a/README.md b/README.md index b2b2428b5..e69809f15 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# {talib}: A Technical Analysis and Candlestick Pattern Library in R +# {talib}: Fast TA-Lib indicators and candlestick patterns for R @@ -16,163 +16,160 @@ 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}](https://serkor1.github.io/ta-lib-R/) is an R package for -technical analysis, candlestick pattern recognition, and interactive -financial charting—built on the -[TA-Lib](https://github.com/TA-Lib/ta-lib) C library. It provides 67 -technical indicators, 61 candlestick patterns, and a composable charting -system powered by [{plotly}](https://github.com/plotly/plotly.R) and -[{ggplot2}](https://ggplot2.tidyverse.org/). All indicator computations -are implemented in C via `.Call()` for minimal overhead. +[{talib}](https://serkor1.github.io/ta-lib-R/) provides fast R bindings +to the [TA-Lib](https://github.com/TA-Lib/ta-lib) C library for OHLCV +data: technical indicators, candlestick pattern recognition, +rolling-window utilities, and composable financial charts. It is +designed for researchers, analysts, and quant developers who need +technical-analysis features in R without building a heavy dependency +stack. Core computations are executed in C through `.Call()`, while +charting support is available through optional +[{plotly}](https://github.com/plotly/plotly.R) and +[{ggplot2}](https://ggplot2.tidyverse.org/) integrations.[^1] -Alongside [{TTR}](https://github.com/joshuaulrich/TTR), -[{talib}](https://serkor1.github.io/ta-lib-R/) adds candlestick pattern -recognition and interactive charts to the R technical analysis -ecosystem. +The API covers 150+ [TA-Lib](https://github.com/TA-Lib/ta-lib)-backed +functions across momentum, overlap, volatility, volume, cycle, +price-transform, rolling-statistics, and candlestick-pattern families, +including 61 candlestick pattern detectors. -``` r -{ - ## create a candlestick chart - talib::chart(BTC, title = "Bitcoin (BTC)") +## Why {talib}? - ## overlay Bollinger Bands on - ## the price panel - talib::indicator(talib::bollinger_bands) +
- ## mark Engulfing candlestick - ## patterns on the chart - talib::indicator(talib::engulfing, data = BTC) +| Need | {talib} | +|:---------------------|:----------------------------------------------------------------------------------------| +| Technical indicators | TA-Lib-backed moving averages, momentum, volatility, volume, cycle, and overlap studies | +| Candlestick patterns | Built-in Japanese candlestick pattern recognition | +| OHLCV workflows | Works directly with open, high, low, close, and volume columns | +| Performance | Computation delegated to C routines through `.Call()` | +| Dependencies | Minimal required R dependencies; plotting packages are optional | +| Charts | Composable financial charts with optional `{plotly}` and `{ggplot2}` support | - ## add RSI and volume as - ## separate sub-panels - talib::indicator(talib::RSI) - talib::indicator(talib::trading_volume) -} -``` +
- +## Installation[^2] -## Indicators +Install the release version from CRAN: -Every indicator follows the same interface: pass an OHLCV `data.frame` -or `matrix` and get the same type back. The return type always matches -the input. +``` r +install.packages("talib") +``` + +Install the development version from GitHub: ``` r -## compute Bollinger Bands -## on BTC OHLCV data -tail( - talib::bollinger_bands(BTC) -) -#> UpperBand MiddleBand LowerBand -#> 2024-12-26 01:00:00 100487.38 96698.61 92909.83 -#> 2024-12-27 01:00:00 100670.65 96512.96 92355.27 -#> 2024-12-28 01:00:00 100632.13 96581.91 92531.69 -#> 2024-12-29 01:00:00 99628.77 95576.60 91524.43 -#> 2024-12-30 01:00:00 96403.53 94231.31 92059.09 -#> 2024-12-31 01:00:00 95441.13 93774.23 92107.34 +pak::pak("serkor1/ta-lib-R") ``` -## Candlestick Patterns +## Quick start -{talib} recognizes 61 candlestick patterns—from single-candle formations -like Doji and Hammer to multi-candle patterns like Morning Star and -Three White Soldiers. Each pattern returns a normalized score: `1` -(bullish), `-1` (bearish), or `0` (no pattern). +All functions provide S3 methods for ``, ``, +and—where applicable—`` inputs. The general convention is +simple: the output uses the same container type as the input. ``` r -## detect Engulfing patterns: -## 1 = bullish, -1 = bearish, 0 = none +## calculate the +## relative strength index +relative_strength_index <- talib::RSI( + talib::BTC +) + +## display results tail( - talib::engulfing(BTC) + relative_strength_index ) -#> CDLENGULFING -#> 2024-12-26 01:00:00 -1 -#> 2024-12-27 01:00:00 0 -#> 2024-12-28 01:00:00 0 -#> 2024-12-29 01:00:00 -1 -#> 2024-12-30 01:00:00 0 -#> 2024-12-31 01:00:00 0 +#> RSI +#> 2024-12-26 01:00:00 46.48851 +#> 2024-12-27 01:00:00 43.85488 +#> 2024-12-28 01:00:00 45.93888 +#> 2024-12-29 01:00:00 43.12301 +#> 2024-12-30 01:00:00 41.47686 +#> 2024-12-31 01:00:00 43.37358 ``` -## Charts - -Charts are built in two steps: `chart()` creates the price chart, then -`indicator()` layers on technical indicators. Overlap indicators (moving -averages, Bollinger Bands) draw on the price panel; oscillators (RSI, -MACD) get their own sub-panels. +Indicator outputs preserve input length, which keeps results aligned +with the original OHLCV rows. ``` r -{ - ## price chart with two moving - ## averages and MACD below - talib::chart(BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::MACD) -} +## combine multiple +## indicators +features <- cbind( + talib::relative_strength_index(talib::BTC), + talib::bollinger_bands(talib::BTC), + talib::engulfing(talib::BTC) +) + +tail(features) +#> RSI UpperBand MiddleBand LowerBand CDLENGULFING +#> 2024-12-26 01:00:00 46.48851 100487.38 96698.61 92909.83 -1 +#> 2024-12-27 01:00:00 43.85488 100670.65 96512.96 92355.27 0 +#> 2024-12-28 01:00:00 45.93888 100632.13 96581.91 92531.69 0 +#> 2024-12-29 01:00:00 43.12301 99628.77 95576.60 91524.43 -1 +#> 2024-12-30 01:00:00 41.47686 96403.53 94231.31 92059.09 0 +#> 2024-12-31 01:00:00 43.37358 95441.13 93774.23 92107.34 0 ``` - +## Charting -Multiple indicators can share a sub-panel by passing them as calls: +[{talib}](https://serkor1.github.io/ta-lib-R/) comes with a composable +charting API built on two core functions: `indicator()` and +`chart()`—both functions are built on `model.frame` for maximum +flexibility: ``` r +## subset data and +## store as 'BTC' +BTC <- talib::BTC[1:75, ] + +## construct chart in a brace block +## alternatively use `|>` { - talib::chart(BTC) - talib::indicator(talib::BBANDS) + ## initialize main chart + talib::chart( + x = BTC, + title = "Bitcoin" + ) - ## pass multiple calls to combine - ## them on a single sub-panel + ## add Bollinger Bands to + ## the existing chart + talib::indicator( + talib::BBANDS + ) + + ## add Simple Moving Averages (SMA) + ## to the chart in a loop + for (n in seq(5, 15, by = 3)) { + talib::indicator( + talib::SMA, + n = n + ) + } + + ## similar subchart indicators + ## like the Relative Strength Index + ## can be grouped to avoid repeated + ## subpanels talib::indicator( talib::RSI(n = 10), talib::RSI(n = 14), talib::RSI(n = 21) ) -} -``` - - -The charting system ships with 5 built-in themes: `default`, -`hawks_and_doves`, `payout`, `tp_slapped`, and `trust_the_process`. -Switch themes with `set_theme()`. Both -[{plotly}](https://github.com/plotly/plotly.R) (interactive, default) -and [{ggplot2}](https://ggplot2.tidyverse.org/) (static) backends are -supported: - -``` r -{ - ## switch to ggplot2 backend with - ## the "Hawks and Doves" theme - talib::set_theme("hawks_and_doves") - talib::chart(BTC, title = "Bitcoin (BTC)") - talib::indicator(talib::BBANDS) - talib::indicator(talib::RSI) - talib::indicator(talib::trading_volume) + ## identify Doji patterns + ## and add them to the chart + talib::indicator( + talib::doji + ) } ``` - - -## Column selection +![](man/figures/README-charting-example-1.png) -Indicators use the columns they need automatically. When your data has -non-standard column names, remap them with formula syntax: - -``` r -## remap 'price' to the close column -talib::RSI(x, cols = ~price) - -## remap hi, lo, last to high, low, close -talib::stochastic(x, cols = ~ hi + lo + last) -``` - -## Naming +## Implementation: {talib} vs upstream (TA-Lib Core) Functions use descriptive snake_case names, but every function is -aliased to its TA-Lib shorthand for compatibility with the broader -ecosystem: +aliased to its [TA-Lib](https://github.com/TA-Lib/ta-lib) shorthand for +compatibility with the broader ecosystem:
@@ -188,52 +185,79 @@ ecosystem:
-``` r -## snake_case and TA-Lib aliases -## are identical -all.equal( - target = talib::bollinger_bands(BTC), - current = talib::BBANDS(BTC) -) -#> [1] TRUE -``` +### Interface: R vs Python -## Installation[^1] +The main difference between the R and Python interfaces is how OHLCV +series are passed into each indicator function. Below is an example of +identifying `Doji` patterns in R and Python. -Install the release version from CRAN: +In Python, each series is passed independently: -``` r -install.packages("talib") -``` +``` python +import numpy as np +import talib -Install the development version from GitHub: +o = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=float) +h = np.array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], dtype=float) +l = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=float) +c = np.array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], dtype=float) -``` r -pak::pak("serkor1/ta-lib-R") +print( + talib.CDLDOJI(o, h, l, c) +) ``` -### Aggressive optimizations - -Unknown flags passed to `configure` are forwarded verbatim to both the -CMake build of the vendored TA-Lib and the R wrapper compile step. -Rebuild from source with any compiler flags you like: +In R the series are passed as a tabular container: ``` r -install.packages( - "talib", - type = "source", - configure.args = "-O3 -march=native" +ohlc <- data.frame( + open = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + high = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), + low = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + close = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1) +) + +talib::CDLDOJI( + ohlc ) ``` -Or from a local clone: +All default series arguments are handled internally, and the `R` +interface is therefore higher-level: users pass one OHLC container +rather than manually splitting the series. -``` shell -git clone --recursive https://github.com/serkor1/ta-lib-R.git +## Contributing and cloning + +Contributions are welcome. For non-trivial changes, please open an issue +first to discuss the proposed design, API impact, and testing approach. + +This repository vendors [TA-Lib](https://github.com/TA-Lib/ta-lib) as a +Git submodule. Clone the repository with submodules enabled: + +``` sh +git clone --recurse-submodules https://github.com/serkor1/ta-lib-R.git cd ta-lib-R -R CMD INSTALL . --configure-args="-O3 -march=native" ``` +If you already cloned the repository without submodules, initialize them +with: + +``` sh +git submodule update --init --recursive +``` + +Most indicator wrappers, helper functions, documentation fragments, and +unit tests are generated from the scripts in `codegen/`. The charting +interface is maintained separately. + +Common development tasks are exposed through Make targets: + +``` sh +make help +``` + +See CONTRIBUTING.md for the full development workflow. + ## Code of Conduct Please note that [{talib}](https://serkor1.github.io/ta-lib-R/) is @@ -241,7 +265,10 @@ 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]: [TA-Lib](https://github.com/TA-Lib/ta-lib) is vendored via - `CMake`, so a pre-installed TA-Lib is not required. Some systems - (Windows in particular) may require `CMake` to be explicitly - installed. +[^1]: See `benchmark/` for detailed benchmarks against [{TTR}]() and + general performance across multiple indicators. + +[^2]: `{talib}` is a compiled package. CRAN binaries are available for + standard platforms when provided by CRAN. Source installation + requires a working compiler toolchain and + [CMake](https://cmake.org/). diff --git a/_pkgdown.yml b/_pkgdown.yml index b2ac7948b..9725b704f 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -76,6 +76,11 @@ reference: Transform raw OHLC prices into derived series. Average Price, Median Price, Typical Price, and Weighted Close Price. - contents: has_concept('Price Transform') +- title: Utility Functions + desc: > + Utility functions used for downstream packages and wrappers that + improves and simplifies the control-flow. +- contents: has_concept('Utility') - title: Financial Data desc: > Built-in OHLCV datasets for examples, testing, and exploration. diff --git a/benchmark/README.Rmd b/benchmark/README.Rmd index b2f54ea71..db543814e 100644 --- a/benchmark/README.Rmd +++ b/benchmark/README.Rmd @@ -1,10 +1,9 @@ --- output: github_document --- + ```{r setup, include = FALSE} -# set options Sys.setenv(OPENSSL_CONF = "/dev/null") - knitr::opts_chunk$set( collapse = TRUE, comment = "#>", @@ -14,22 +13,131 @@ knitr::opts_chunk$set( ) ``` +```{r load, include = FALSE} +## The plot PNGs are produced by benchmark/run-all.R and referenced as +## static markdown images below. The Rmd only computes the summary tables. +source("benchmark-utils.R") + +overhead <- readRDS("results/overhead.rds") +ttr <- readRDS("results/ttr.rds") +``` + # Benchmarks -The benchmarks are run on the `bollinger_bands()` function, with three different specifications: +These benchmarks answer two questions: + +1. **How fast is `{talib}`?** We compare `{talib}` to [`{TTR}`](https://cran.r-project.org/package=TTR), the canonical R technical-analysis package, on eight indicators across the natural API in each package. +2. **What does the R wrapper around `.Call` cost?** We measure three call paths into the same C routine: a bare `.Call`, the `` S3 method, and the `` S3 method. + +## Method + +* **Indicators**: BBANDS, RSI, MACD, ATR, SMA, EMA, ADX, STOCH +* **Sizes**: `r paste(format(BENCHMARK_SIZES, big.mark = ","), collapse = " / ")` observations of synthetic OHLCV +* **Iterations**: `r BENCHMARK_ITERATIONS` timed iterations per cell, after `r BENCHMARK_WARMUP` warmup calls +* **Sequential**: every `(indicator, n, expression)` cell is timed on its own, after a per-cell warmup +* **Engine**: [`bench::mark()`](https://bench.r-lib.org) with `filter_gc = FALSE`, `memory = TRUE` + +Reported timings below are the **median** over the timed iterations. Ribbons show the min-to-max range across iterations. -1. *baseline:* This specification calls the C routine directly, without any calls to R functions. -2. *data.frame:* This specification is the S3 `` dispatch. -3. *matrix:* This specification is the S3 `` dispatch. +## `{talib}` vs `{TTR}` -All benchmarks uses a `r nrow(readRDS("dataframe.rds"))` row OHLC `` +`{talib}` is faster than `{TTR}` across every indicator and every size, though the size of the speedup varies considerably and depends on what each package computes internally. -## Benchmark results +The benchmark compares **equivalent output bundles**, not raw function calls. `{TTR}` returns more columns than `{talib}` for several indicators (`pctB` alongside Bollinger Bands; `tr` / `trueHigh` / `trueLow` alongside ATR; `DIp` / `DIn` / `DX` alongside ADX; `fastK` alongside the smoothed stochastic), and `{talib}` returns more for MACD (`hist`). To keep the comparison apples-to-apples each branch produces the same set of derived series per call: where the package's API does not return a column natively, the closure composes the equivalent talib calls (or a one-line arithmetic derivation) to recover it. The residual gap reflects the inner loops, not API shape. -```{r} -library(bench) -readRDS( - "overhead_benchmark.rds" +* **Wide gap** is concentrated where `{TTR}` implements the indicator in pure R with rolling-window helpers that allocate intermediate vectors per step. +* **Narrow gap** appears for the moving averages (`SMA`, `EMA`) and a few others where `{TTR}`'s implementation is also C-backed via `.Call`. These facets are a fair benchmark of the wrappers, not of the algorithms. + +![{talib} vs {TTR} -- median execution time across observations](results/plot-ttr.png) + +![{talib} speedup over {TTR}](results/plot-speedup.png) + +### Speedup at the largest size + +
+ +```{r ttr-table} +big <- ttr[ttr$n == max(ttr$n), c("indicator", "spec", "median")] +big_wide <- reshape( + big, + idvar = "indicator", + timevar = "spec", + direction = "wide" +) +names(big_wide) <- sub("^median\\.", "", names(big_wide)) +big_wide$speedup <- big_wide$TTR / big_wide$talib + +fmt_time <- function(x) { + vapply(x, function(v) { + if (v < 1e-6) sprintf("%.0f ns", v * 1e9) + else if (v < 1e-3) sprintf("%.0f us", v * 1e6) + else if (v < 1) sprintf("%.1f ms", v * 1e3) + else sprintf("%.2f s", v) + }, character(1)) +} + +display <- data.frame( + Indicator = big_wide$indicator, + `{talib} (median)` = fmt_time(big_wide$talib), + `{TTR} (median)` = fmt_time(big_wide$TTR), + Speedup = sprintf("%.1fx", big_wide$speedup), + check.names = FALSE +) +knitr::kable( + display, + caption = sprintf("n = %s observations", format(max(ttr$n), big.mark = ",")) ) ``` +
+ +## R-side overhead + +For each indicator we time the same C routine three different ways: + +1. **baseline** -- raw `.Call` directly into the registered native symbol, with the same arguments the wrapper would emit. +2. **data.frame** -- the natural `` S3 method (column selection via `series()`, result rewrapped via `map_dfr()`). +3. **matrix** -- the `` S3 method (column selection via `series()`, no `map_dfr()`). + +![{talib} R-side overhead by dispatch path](results/plot-overhead.png) + +### Overhead at the largest size + +
+ +```{r overhead-table} +big <- overhead[overhead$n == max(overhead$n), c("indicator", "spec", "median")] +big_wide <- reshape( + big, + idvar = "indicator", + timevar = "spec", + direction = "wide" +) +names(big_wide) <- sub("^median\\.", "", names(big_wide)) +big_wide$df_over <- (big_wide$data.frame - big_wide$baseline) / big_wide$baseline +big_wide$mat_over <- (big_wide$matrix - big_wide$baseline) / big_wide$baseline + +display <- data.frame( + Indicator = big_wide$indicator, + baseline = fmt_time(big_wide$baseline), + data.frame = fmt_time(big_wide$data.frame), + matrix = fmt_time(big_wide$matrix), + `data.frame +%` = sprintf("%+.1f%%", 100 * big_wide$df_over), + `matrix +%` = sprintf("%+.1f%%", 100 * big_wide$mat_over), + check.names = FALSE +) +knitr::kable( + display, + caption = sprintf("n = %s observations", format(max(overhead$n), big.mark = ",")) +) +``` + +
+ +## Reproducing + +```bash +make bench +``` + +This runs `benchmark/run-all.R`, which writes RDS results and PNG plots to `benchmark/results/`, then re-renders this README. diff --git a/benchmark/README.md b/benchmark/README.md index 09f058fbb..49366a8a5 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -1,21 +1,128 @@ # Benchmarks -The benchmarks are run on the `bollinger_bands()` function, with three -different specifications: +These benchmarks answer two questions: -1. *baseline:* This specification calls the C routine directly, without - any calls to R functions. -2. *data.frame:* This specification is the S3 `` dispatch. -3. *matrix:* This specification is the S3 `` dispatch. +1. **How fast is `{talib}`?** We compare `{talib}` to + [`{TTR}`](https://cran.r-project.org/package=TTR), the canonical R + technical-analysis package, on eight indicators across the natural + API in each package. +2. **What does the R wrapper around `.Call` cost?** We measure three + call paths into the same C routine: a bare `.Call`, the + `` S3 method, and the `` S3 method. -All benchmarks uses a 200000 row OHLC `` +## Method -## Benchmark results +- **Indicators**: BBANDS, RSI, MACD, ATR, SMA, EMA, ADX, STOCH +- **Sizes**: 1,000 / 10,000 / 100,000 / 1,000,000 observations of + synthetic OHLCV +- **Iterations**: 1000 timed iterations per cell, after 3 warmup calls +- **Sequential**: every `(indicator, n, expression)` cell is timed on + its own, after a per-cell warmup +- **Engine**: [`bench::mark()`](https://bench.r-lib.org) with + `filter_gc = FALSE`, `memory = TRUE` - #> # A data frame: 3 × 6 - #> expression min median `itr/sec` mem_alloc `gc/sec` - #> - #> 1 baseline 846.75µs 1.47ms 682. 4.58MB 97.4 - #> 2 data.frame 1.19ms 1.27ms 688. 9.17MB 442. - #> 3 matrix 1.69ms 1.82ms 484. 13.74MB 730. +Reported timings below are the **median** over the timed iterations. +Ribbons show the min-to-max range across iterations. + +## `{talib}` vs `{TTR}` + +`{talib}` is faster than `{TTR}` across every indicator and every size, +though the size of the speedup varies considerably and depends on what +each package computes internally. + +The benchmark compares **equivalent output bundles**, not raw function +calls. `{TTR}` returns more columns than `{talib}` for several +indicators (`pctB` alongside Bollinger Bands; `tr` / `trueHigh` / +`trueLow` alongside ATR; `DIp` / `DIn` / `DX` alongside ADX; `fastK` +alongside the smoothed stochastic), and `{talib}` returns more for MACD +(`hist`). To keep the comparison apples-to-apples each branch produces +the same set of derived series per call: where the package’s API does +not return a column natively, the closure composes the equivalent talib +calls (or a one-line arithmetic derivation) to recover it. The residual +gap reflects the inner loops, not API shape. + +- **Wide gap** is concentrated where `{TTR}` implements the indicator in + pure R with rolling-window helpers that allocate intermediate vectors + per step. +- **Narrow gap** appears for the moving averages (`SMA`, `EMA`) and a + few others where `{TTR}`’s implementation is also C-backed via + `.Call`. These facets are a fair benchmark of the wrappers, not of the + algorithms. + +
+ + +
+ +
+{talib} speedup over {TTR} + +
+ +### Speedup at the largest size + +
+ +| Indicator | {talib} (median) | {TTR} (median) | Speedup | +|:----------|:-----------------|:---------------|:--------| +| BBANDS | 11.2 ms | 86.7 ms | 7.7x | +| RSI | 4.9 ms | 22.4 ms | 4.6x | +| MACD | 13.2 ms | 26.3 ms | 2.0x | +| ATR | 21.1 ms | 33.3 ms | 1.6x | +| SMA | 1.9 ms | 4.2 ms | 2.2x | +| EMA | 2.6 ms | 3.4 ms | 1.3x | +| ADX | 29.6 ms | 157.1 ms | 5.3x | +| STOCH | 11.0 ms | 42.9 ms | 3.9x | + +n = 1,000,000 observations + +
+ +## R-side overhead + +For each indicator we time the same C routine three different ways: + +1. **baseline** – raw `.Call` directly into the registered native + symbol, with the same arguments the wrapper would emit. +2. **data.frame** – the natural `` S3 method (column + selection via `series()`, result rewrapped via `map_dfr()`). +3. **matrix** – the `` S3 method (column selection via + `series()`, no `map_dfr()`). + +
+ + +
+ +### Overhead at the largest size + +
+ +| Indicator | baseline | data.frame | matrix | data.frame +% | matrix +% | +|:----------|:---------|:-----------|:--------|:--------------|:----------| +| BBANDS | 9.5 ms | 13.4 ms | 9.4 ms | +41.2% | -1.2% | +| RSI | 4.4 ms | 5.0 ms | 8.3 ms | +14.5% | +90.6% | +| MACD | 11.2 ms | 13.0 ms | 12.7 ms | +15.6% | +13.3% | +| ATR | 5.2 ms | 5.8 ms | 9.3 ms | +12.2% | +79.6% | +| SMA | 1.5 ms | 2.1 ms | 5.5 ms | +37.8% | +269.3% | +| EMA | 2.1 ms | 2.6 ms | 6.5 ms | +24.1% | +212.4% | +| ADX | 6.8 ms | 7.5 ms | 10.8 ms | +9.5% | +58.6% | +| STOCH | 9.1 ms | 12.3 ms | 11.1 ms | +35.6% | +22.5% | + +n = 1,000,000 observations + +
+ +## Reproducing + +``` bash +make bench +``` + +This runs `benchmark/run-all.R`, which writes RDS results and PNG plots +to `benchmark/results/`, then re-renders this README. diff --git a/benchmark/benchmark-data.R b/benchmark/benchmark-data.R deleted file mode 100644 index 62b6708b2..000000000 --- a/benchmark/benchmark-data.R +++ /dev/null @@ -1,41 +0,0 @@ -## script: benchmark-data -## objective: -## This script can be called as -## make bench-data n=1e3 to generate -## a - and -object -## used for benchmarking -## -## 1) number of observations -n <- commandArgs( - trailingOnly = TRUE -) - -## 2) construct -## as OHLC -set.seed(1903) -DT <- data.frame( - open = runif( - n = n, - min = 100, - max = 1000 - ) -) - -## 2.1) -DT$high <- DT$open + 20 -DT$close <- DT$open - 10 -DT$low <- DT$open - 20 - -## 3) stroe data -## -## 3.1) -saveRDS( - DT, - "benchmark/dataframe.rds" -) - -## 3.2) -saveRDS( - as.matrix(DT), - "benchmark/matrix.rds" -) diff --git a/benchmark/benchmark-overhead.R b/benchmark/benchmark-overhead.R index 698ad6817..c01d2dda3 100644 --- a/benchmark/benchmark-overhead.R +++ b/benchmark/benchmark-overhead.R @@ -1,96 +1,240 @@ -## script: benchmark-overhead -## objective: +## benchmark/benchmark-overhead.R ## -## Create a naïve benchmark comparing -## the C implementation to the R wrapper -## to determine the amount of overhead -## induced by the wrapper +## Measure the overhead that talib's R wrappers add on top of the bare +## .Call into the bundled TA-Lib C library. For each indicator we time +## three expressions at every n: ## -## 1) load libraries -## and data -library(talib) -DF <- readRDS("benchmark/dataframe.rds") -X <- readRDS("benchmark/matrix.rds") +## 1. baseline - a raw .Call against the registered native symbol, +## using exactly the arguments the wrapper would pass. +## 2. data.frame - talib's data.frame S3 method (series() column +## selection + map_dfr() to wrap the result). +## 3. matrix - talib's matrix S3 method (series() column selection, +## no map_dfr). +## +## All three call the same underlying C routine. Any difference in +## timing is pure R-side overhead. Every talib symbol is referenced +## through talib:: so that load order with TTR (whose SMA / EMA / RSI / +## ATR / ADX / MACD shadow talib's exports) cannot perturb the result. + +suppressPackageStartupMessages({ + library(talib) + library(bench) +}) -## 2) load utils source("benchmark/benchmark-utils.R") -## 3) construct wrappers -## for benchmarking -## -## 3.1) direct call to 'C' -## without any processing -## this is the baseline -foo <- function() { - .Call( - "impl_ta_BBANDS", - DF$close, - 10L, - 2, - 2, - 0L, - PACKAGE = "talib" - ) -} -## 3.2) -bar <- function() { - talib:::bollinger_bands( - DF - ) -} +## Native symbols -## 3.3) -baz <- function() { - talib::bollinger_bands( - X - ) -} +## Resolve the registered C symbols once. Caching them out of talib's +## namespace makes the baseline expression a literal .Call against a +## pointer, with no per-iteration symbol lookup. +ns <- asNamespace("talib") +C_BBANDS <- get("C_impl_ta_BBANDS", envir = ns) +C_RSI <- get("C_impl_ta_RSI", envir = ns) +C_MACD <- get("C_impl_ta_MACD", envir = ns) +C_ATR <- get("C_impl_ta_ATR", envir = ns) +C_SMA <- get("C_impl_ta_SMA", envir = ns) +C_EMA <- get("C_impl_ta_EMA", envir = ns) +C_ADX <- get("C_impl_ta_ADX", envir = ns) +C_STOCH <- get("C_impl_ta_STOCH", envir = ns) -## 4) benchmark -## -## 4.1) check that all core values -## are equal -## -## NOTE: all values can just be converted -## to a long vector and compare the values -stopifnot( - all.equal( - as.double(foo()), - as.double(as.matrix(bar())), - check.attributes = FALSE, - check.class = FALSE - ) -) -stopifnot( - all.equal( - as.double(foo()), - as.double(baz()), - check.attributes = FALSE, - check.class = FALSE - ) -) +## Indicator factories -## 4.2) store the benchmark -## so it can be exported -benchmark_results <- benchmark( - "baseline" = foo(), - "data.frame" = bar(), - "matrix" = baz() +## Each factory takes the OHLCV data.frame and its matrix mirror and +## returns three nullary closures whose bodies are the .Call the wrapper +## would emit. Using closures (rather than substituted expressions) lets +## bench::mark see uniform call sites across indicators and lets the +## driver share one warmup loop. The closures capture df / mat by +## reference, so the inner timed expressions allocate nothing extra. +overhead_factories <- list( + BBANDS = function(df, mat) { + list( + baseline = function() { + .Call(C_BBANDS, df$close, 20L, 2, 2, 0L, FALSE) + }, + data.frame = function() { + talib::bollinger_bands(df, ma = talib::SMA(n = 20)) + }, + matrix = function() { + talib::bollinger_bands(mat, ma = talib::SMA(n = 20)) + } + ) + }, + RSI = function(df, mat) { + list( + baseline = function() .Call(C_RSI, df$close, 14L, FALSE), + data.frame = function() talib::relative_strength_index(df, n = 14), + matrix = function() talib::relative_strength_index(mat, n = 14) + ) + }, + MACD = function(df, mat) { + list( + baseline = function() { + .Call(C_MACD, df$close, 12L, 26L, 9L, FALSE) + }, + data.frame = function() { + talib::moving_average_convergence_divergence(df) + }, + matrix = function() { + talib::moving_average_convergence_divergence(mat) + } + ) + }, + ATR = function(df, mat) { + list( + baseline = function() { + .Call(C_ATR, df$high, df$low, df$close, 14L, FALSE) + }, + data.frame = function() talib::average_true_range(df, n = 14), + matrix = function() talib::average_true_range(mat, n = 14) + ) + }, + SMA = function(df, mat) { + ## The talib wrapper coerces with as.double() before .Call, so the + ## baseline does the same; we want the C work to be apples to apples. + list( + baseline = function() { + .Call(C_SMA, as.double(df$close), 20L, FALSE) + }, + data.frame = function() { + talib::simple_moving_average(df, n = 20) + }, + matrix = function() { + talib::simple_moving_average(mat, n = 20) + } + ) + }, + EMA = function(df, mat) { + ## Same as SMA: the wrapper does an explicit as.double() coercion. + list( + baseline = function() { + .Call(C_EMA, as.double(df$close), 20L, FALSE) + }, + data.frame = function() { + talib::exponential_moving_average(df, n = 20) + }, + matrix = function() { + talib::exponential_moving_average(mat, n = 20) + } + ) + }, + ADX = function(df, mat) { + list( + baseline = function() { + .Call( + C_ADX, + df$high, + df$low, + df$close, + 14L, + FALSE + ) + }, + data.frame = function() { + talib::average_directional_movement_index(df, n = 14) + }, + matrix = function() { + talib::average_directional_movement_index(mat, n = 14) + } + ) + }, + STOCH = function(df, mat) { + list( + baseline = function() { + .Call( + C_STOCH, + df$high, + df$low, + df$close, + 14L, + 3L, + 0L, + 3L, + 0L, + FALSE + ) + }, + data.frame = function() { + talib::stochastic( + df, + fastk = 14, + slowk = talib::SMA(n = 3), + slowd = talib::SMA(n = 3) + ) + }, + matrix = function() { + talib::stochastic( + mat, + fastk = 14, + slowk = talib::SMA(n = 3), + slowd = talib::SMA(n = 3) + ) + } + ) + } ) -## 4.2) print the necessary -## results -pretty( - x = benchmark_results, - indicator = "Bollinger Bands", - n = nrow(DF) -) -## 4.3) store the benchmark -## results -saveRDS( - benchmark_results, - "benchmark/overhead_benchmark.rds" -) +## Driver + +## Sweep every (indicator, n) cell. For each cell we build fresh data, +## warm up, then hand the three closures to bench::mark and tag the tidy +## result with the indicator name and size. Rows from all cells are +## rbind-ed at the end into one long data.frame for plotting. +run_overhead <- function( + indicators = names(overhead_factories), + sizes = BENCHMARK_SIZES, + iterations = BENCHMARK_ITERATIONS, + warmup_n = BENCHMARK_WARMUP +) { + results <- list() + for (indicator in indicators) { + factory <- overhead_factories[[indicator]] + message(sprintf("\n[overhead] %s", indicator)) + for (n in sizes) { + banner(indicator, n) + df <- make_ohlc(n) + mat <- as.matrix(df) + exprs <- factory(df, mat) + + ## Prime caches and the allocator before bench starts the clock. + warmup(exprs, reps = warmup_n) + + bm <- bench::mark( + baseline = exprs$baseline(), + data.frame = exprs$data.frame(), + matrix = exprs$matrix(), + iterations = iterations, + check = FALSE, + filter_gc = FALSE, + memory = TRUE, + time_unit = "s" + ) + + results[[length(results) + 1L]] <- tidy_bench( + bm, + indicator = indicator, + n = n + ) + } + } + do.call(rbind, results) +} + + +## Entry point + +## Only runs when this file is invoked directly (Rscript / make +## bench-overhead). When sourced from run-all.R the guard skips this +## block; run-all.R calls run_overhead() and saves the result itself. +if (sys.nframe() == 0L) { + overhead <- run_overhead() + + out_dir <- file.path("benchmark", "results") + dir.create(out_dir, showWarnings = FALSE, recursive = TRUE) + saveRDS(overhead, file.path(out_dir, "overhead.rds")) + + message("\nSaved overhead results to benchmark/results/overhead.rds") +} diff --git a/benchmark/benchmark-plots.R b/benchmark/benchmark-plots.R new file mode 100644 index 000000000..10fe6ee95 --- /dev/null +++ b/benchmark/benchmark-plots.R @@ -0,0 +1,267 @@ +## benchmark/benchmark-plots.R +## +## ggplot2 visualizations for the talib benchmark suite. Each plot +## function takes a tidy data.frame produced by tidy_bench() and returns +## a ggplot object; save_plots() writes all three to disk and is the +## single entry point used both by this script's stand-alone mode and by +## run-all.R, so the I/O lives in exactly one place. +## +## All themes use transparent backgrounds so the resulting PNGs blend in +## with both GitHub's light and dark color schemes. + +suppressPackageStartupMessages({ + library(ggplot2) + library(scales) +}) + + +## Shared theme + +## Transparent backgrounds plus a single mid-gray ink colour. The README +## is embedded in both GitHub's light (#ffffff) and dark (#0d1117) +## chrome, and one ~50% luminance gray (#7d7d7d) reads on either side +## without needing per-theme inversion. Titles get bold weight rather +## than a darker colour so they stay prominent on both backgrounds. +bench_theme <- function(base_size = 12) { + transparent <- element_rect(fill = "transparent", colour = NA) + ink <- "#7d7d7d" + grid <- "#7d7d7d" + theme_minimal(base_size = base_size) + + theme( + plot.background = transparent, + panel.background = transparent, + legend.background = transparent, + legend.box.background = transparent, + legend.key = transparent, + strip.background = transparent, + plot.title = element_text(face = "bold", color = ink), + plot.subtitle = element_text(color = ink), + plot.caption = element_text(color = ink, hjust = 0), + strip.text = element_text(face = "bold", color = ink), + axis.title = element_text(color = ink), + axis.text = element_text(color = ink), + panel.grid.minor = element_line(colour = grid, linewidth = 0.15), + panel.grid.major = element_line(colour = grid, linewidth = 0.3), + legend.position = "top", + legend.title = element_blank(), + legend.text = element_text(color = ink) + ) +} + +## Palette for the three R-side dispatch paths in the overhead plot. +spec_colors <- c( + "baseline" = "#1F77B4", + "data.frame" = "#FF7F0E", + "matrix" = "#2CA02C" +) + +## Palette for the talib-vs-TTR plot. {talib} in steel-blue matches the +## package's house style; {TTR} in red provides clear contrast. +package_colors <- c( + "{talib}" = "#1F77B4", + "{TTR}" = "#D62728" +) + + +## Axis label helpers + +## Render n as 1k / 10k / 100k / 1M so the x-axis ticks stay short and +## readable on a four-point log scale. +format_obs <- function(x) { + out <- character(length(x)) + for (i in seq_along(x)) { + v <- x[[i]] + if (is.na(v)) { + out[[i]] <- NA_character_ + } else if (v >= 1e6) { + out[[i]] <- paste0(v / 1e6, "M") + } else if (v >= 1e3) { + out[[i]] <- paste0(v / 1e3, "k") + } else { + out[[i]] <- as.character(v) + } + } + out +} + +## Pick a sensible unit (ns / us / ms / s) per tick so a log-time y-axis +## reads like wall-clock numbers rather than scientific notation. +format_time <- function(x) { + out <- character(length(x)) + for (i in seq_along(x)) { + v <- x[[i]] + if (is.na(v) || v <= 0) { + out[[i]] <- NA_character_ + } else if (v < 1e-6) { + out[[i]] <- sprintf("%.0fns", v * 1e9) + } else if (v < 1e-3) { + out[[i]] <- sprintf("%.0fus", v * 1e6) + } else if (v < 1) { + out[[i]] <- sprintf("%.0fms", v * 1e3) + } else { + out[[i]] <- sprintf("%.1fs", v) + } + } + out +} + + +## Plots + +## Overhead: one facet per indicator, three lines (baseline / data.frame +## / matrix). Each facet gets its own y scale because the absolute work +## per indicator differs by orders of magnitude. +plot_overhead <- function(data) { + data$spec <- factor( + data$spec, + levels = c("baseline", "data.frame", "matrix") + ) + data$indicator <- factor(data$indicator, levels = unique(data$indicator)) + + ggplot( + data, + aes(x = n, y = median, colour = spec, group = spec) + ) + + geom_ribbon( + aes(ymin = min, ymax = max, fill = spec), + alpha = 0.15, + colour = NA + ) + + geom_line(linewidth = 0.7) + + geom_point(size = 1.7) + + scale_x_log10(labels = format_obs, breaks = unique(data$n)) + + scale_y_log10(labels = format_time) + + scale_colour_manual(values = spec_colors) + + scale_fill_manual(values = spec_colors, guide = "none") + + facet_wrap(~indicator, ncol = 4, scales = "free_y") + + labs( + title = "{talib} R-side overhead", + subtitle = "Median execution time vs observations, by dispatch path", + x = "Observations", + y = "Execution time (log)", + caption = sprintf( + "%d iterations per cell; ribbon shows min-max range.", + max(data$n_itr) + ) + ) + + bench_theme() +} + +## TTR comparison: one facet per indicator, two lines ({talib} / {TTR}). +## The spec column is relabelled before becoming a factor so the legend +## matches the curly-fenced form used in the rest of the README. +plot_ttr <- function(data) { + data$spec <- factor( + paste0("{", data$spec, "}"), + levels = c("{talib}", "{TTR}") + ) + data$indicator <- factor(data$indicator, levels = unique(data$indicator)) + + ggplot( + data, + aes(x = n, y = median, colour = spec, group = spec) + ) + + geom_ribbon( + aes(ymin = min, ymax = max, fill = spec), + alpha = 0.15, + colour = NA + ) + + geom_line(linewidth = 0.7) + + geom_point(size = 1.7) + + scale_x_log10(labels = format_obs, breaks = unique(data$n)) + + scale_y_log10(labels = format_time) + + scale_colour_manual(values = package_colors) + + scale_fill_manual(values = package_colors, guide = "none") + + facet_wrap(~indicator, ncol = 4, scales = "free_y") + + labs( + title = "{talib} vs {TTR}", + subtitle = "Median execution time vs observations, equivalent output bundles in each branch", + x = "Observations", + y = "Execution time (log)", + caption = sprintf( + "%d iterations per cell; ribbon shows min-max range.", + max(data$n_itr) + ) + ) + + bench_theme() +} + +## Speedup: median(TTR) / median(talib), one number per (indicator, n) +## drawn as a labelled point. The x and y scales get extra expansion so +## the per-point "Nx" annotations do not collide with axes or facets. +plot_speedup <- function(data) { + wide <- reshape( + data[, c("indicator", "n", "spec", "median")], + idvar = c("indicator", "n"), + timevar = "spec", + direction = "wide" + ) + names(wide) <- sub("^median\\.", "", names(wide)) + wide$speedup <- wide$TTR / wide$talib + wide$indicator <- factor(wide$indicator, levels = unique(data$indicator)) + + ggplot(wide, aes(x = n, y = speedup)) + + geom_hline(yintercept = 1, linetype = "dashed", colour = "grey60") + + geom_line(linewidth = 0.7, colour = "#1F77B4") + + geom_point(size = 1.7, colour = "#1F77B4") + + geom_text( + aes(label = sprintf("%.1fx", speedup)), + vjust = -0.9, + size = 3, + colour = "#7d7d7d" + ) + + scale_x_log10( + labels = format_obs, + breaks = unique(wide$n), + expand = expansion(mult = 0.12) + ) + + scale_y_log10(expand = expansion(mult = c(0.08, 0.25))) + + facet_wrap(~indicator, ncol = 4) + + labs( + title = "{talib} speedup over {TTR}", + subtitle = "{TTR} median / {talib} median; values above 1 mean {talib} is faster", + x = "Observations", + y = "Speedup (log)", + caption = "Computed from median execution times in the same run." + ) + + bench_theme() +} + + +## I/O + +## Single place where the three PNGs are written. Called from the +## stand-alone entry point and from run-all.R so the ggsave arguments +## (size, dpi, transparent background) live in one location. +save_plots <- function(overhead, ttr, out_dir) { + plots <- list( + "plot-overhead.png" = plot_overhead(overhead), + "plot-ttr.png" = plot_ttr(ttr), + "plot-speedup.png" = plot_speedup(ttr) + ) + for (name in names(plots)) { + ggsave( + file.path(out_dir, name), + plots[[name]], + width = 12, + height = 6, + dpi = 150, + bg = "transparent" + ) + } + invisible(plots) +} + + +## Entry point + +## Stand-alone invocation (Rscript / make bench-plots). Reads the +## existing RDS results and rewrites the PNGs. Skipped when sourced from +## run-all.R, which calls save_plots() itself with the in-memory data. +if (sys.nframe() == 0L) { + out_dir <- file.path("benchmark", "results") + overhead <- readRDS(file.path(out_dir, "overhead.rds")) + ttr <- readRDS(file.path(out_dir, "ttr.rds")) + save_plots(overhead, ttr, out_dir) + message("\nSaved plots to benchmark/results/") +} diff --git a/benchmark/benchmark-ttr.R b/benchmark/benchmark-ttr.R new file mode 100644 index 000000000..6cd9dcd74 --- /dev/null +++ b/benchmark/benchmark-ttr.R @@ -0,0 +1,221 @@ +## benchmark/benchmark-ttr.R +## +## Compare talib (C implementation) against TTR (R implementation, with +## some indicators C-backed) at the user level. For each indicator we +## time two expressions: +## +## 1. talib - the talib equivalent of what TTR returns. +## 2. TTR - the natural TTR call, with the same period / deviation +## parameters so the algorithms are matched. +## +## "Equivalent" means the two branches produce the same set of derived +## series per call. TTR tends to return bundles (e.g. TTR::ADX returns +## DIp, DIn, DX, ADX in one matrix), while talib exposes each indicator +## as a separate function. Where TTR's API forces extra outputs we +## compose the matching talib calls (or derive the extras in R) so both +## packages do the same algorithmic work in each timed cell. Where +## talib's API returns the extras (MACD histogram) we synthesise the +## same column on the TTR side. The result is an apples-to-apples +## comparison; the residual gap reflects the inner loops, not API shape. + +suppressPackageStartupMessages({ + library(talib) + library(TTR) + library(bench) +}) + +source("benchmark/benchmark-utils.R") + + +## Indicator factories + +ttr_factories <- list( + BBANDS = function(df, hlc) { + close <- df$close + list( + ## TTR::BBands returns dn/mavg/up plus pctB (the %B oscillator). + ## talib's bollinger_bands omits pctB, so we derive it from the + ## same series as TTR does: pctB = (close - dn) / (up - dn). + talib = function() { + bb <- talib::bollinger_bands(df, ma = talib::SMA(n = 20)) + bb$pctB <- (close - bb$LowerBand) / + (bb$UpperBand - bb$LowerBand) + bb + }, + TTR = function() TTR::BBands(close, n = 20, sd = 2) + ) + }, + RSI = function(df, hlc) { + ## Both branches return a single column already. + close <- df$close + list( + talib = function() talib::relative_strength_index(df, n = 14), + TTR = function() TTR::RSI(close, n = 14) + ) + }, + MACD = function(df, hlc) { + close <- df$close + list( + ## talib's MACD returns MACD, Signal, Hist (3 columns); TTR's + ## MACD returns only macd and signal. Compute hist on the TTR + ## side to match the bundle size; hist is just macd - signal. + talib = function() { + talib::moving_average_convergence_divergence(df) + }, + TTR = function() { + m <- TTR::MACD( + close, + nFast = 12, + nSlow = 26, + nSig = 9, + maType = "EMA" + ) + cbind(m, hist = m[, "macd"] - m[, "signal"]) + } + ) + }, + ATR = function(df, hlc) { + ## TTR::ATR returns tr, atr, trueHigh, trueLow. talib::ATR only + ## returns atr, so we derive the other three from the same H/L/C + ## inputs that TTR uses: + ## trueHigh = pmax(high, lag(close)) + ## trueLow = pmin(low, lag(close)) + ## tr = trueHigh - trueLow + ## This requires one talib C call plus three vectorized R ops. + high <- df$high + low <- df$low + close <- df$close + list( + talib = function() { + atr <- talib::average_true_range(df, n = 14) + prevC <- c(NA, close[-length(close)]) + trueHigh <- pmax(high, prevC) + trueLow <- pmin(low, prevC) + cbind( + tr = trueHigh - trueLow, + atr = atr[, 1], + trueHigh = trueHigh, + trueLow = trueLow + ) + }, + TTR = function() TTR::ATR(hlc, n = 14) + ) + }, + SMA = function(df, hlc) { + ## Single column in both branches. + close <- df$close + list( + talib = function() talib::simple_moving_average(df, n = 20), + TTR = function() TTR::SMA(close, n = 20) + ) + }, + EMA = function(df, hlc) { + ## Single column in both branches. + close <- df$close + list( + talib = function() talib::exponential_moving_average(df, n = 20), + TTR = function() TTR::EMA(close, n = 20) + ) + }, + ADX = function(df, hlc) { + ## TTR::ADX returns the full DI+/DI-/DX/ADX bundle from one + ## internal pass. talib exposes each as a separate wrapper, so we + ## call all four and cbind them. This is the "fair" cost: a real + ## user wanting all four outputs from talib pays exactly this. + list( + talib = function() { + cbind( + DIp = talib::PLUS_DI(df, n = 14)[, 1], + DIn = talib::MINUS_DI(df, n = 14)[, 1], + DX = talib::DX(df, n = 14)[, 1], + ADX = talib::average_directional_movement_index( + df, + n = 14 + )[, 1] + ) + }, + TTR = function() TTR::ADX(hlc, n = 14) + ) + }, + STOCH = function(df, hlc) { + ## TTR::stoch returns fastK, fastD, slowD. talib::stochastic only + ## exposes the smoothed pair SlowK (= fastD) and SlowD; the raw + ## fastK is computed internally but not returned. We use + ## talib::STOCHF (which returns FastK and FastD) and add a third + ## SMA pass to recover slowD. Two C calls vs TTR's single + ## internal pipeline; matches the work TTR does. + list( + talib = function() { + sf <- talib::STOCHF(df, fastk = 14, fastd = talib::SMA(n = 3)) + cbind( + fastK = sf$FastK, + fastD = sf$FastD, + slowD = talib::SMA(sf$FastD, n = 3) + ) + }, + TTR = function() { + TTR::stoch(hlc, nFastK = 14, nFastD = 3, nSlowD = 3) + } + ) + } +) + + +## Driver + +## Same shape as run_overhead: walk every (indicator, n) cell, warm up, +## time, collect tidy rows. The only structural difference is the HLC +## matrix prep, which TTR's multi-input indicators need. +run_ttr <- function( + indicators = names(ttr_factories), + sizes = BENCHMARK_SIZES, + iterations = BENCHMARK_ITERATIONS, + warmup_n = BENCHMARK_WARMUP +) { + results <- list() + for (indicator in indicators) { + factory <- ttr_factories[[indicator]] + message(sprintf("\n[ttr] %s", indicator)) + for (n in sizes) { + banner(indicator, n) + df <- make_ohlc(n) + hlc <- as.matrix(df[, c("high", "low", "close")]) + exprs <- factory(df, hlc) + + ## Prime caches and the allocator before bench starts the clock. + warmup(exprs, reps = warmup_n) + + bm <- bench::mark( + talib = exprs$talib(), + TTR = exprs$TTR(), + iterations = iterations, + check = FALSE, + filter_gc = FALSE, + memory = TRUE, + time_unit = "s" + ) + + results[[length(results) + 1L]] <- tidy_bench( + bm, + indicator = indicator, + n = n + ) + } + } + do.call(rbind, results) +} + + +## Entry point + +## Stand-alone invocation (Rscript / make bench-ttr). When this file is +## sourced from run-all.R the guard skips this block. +if (sys.nframe() == 0L) { + ttr <- run_ttr() + + out_dir <- file.path("benchmark", "results") + dir.create(out_dir, showWarnings = FALSE, recursive = TRUE) + saveRDS(ttr, file.path(out_dir, "ttr.rds")) + + message("\nSaved TTR comparison to benchmark/results/ttr.rds") +} diff --git a/benchmark/benchmark-utils.R b/benchmark/benchmark-utils.R index 7578d4d3a..64c41ab33 100644 --- a/benchmark/benchmark-utils.R +++ b/benchmark/benchmark-utils.R @@ -1,24 +1,114 @@ -## script: benchmark-utils -## objective: -## create proper abstractions around -## {bench} for running the benchmarks +## benchmark/benchmark-utils.R ## -## benchmark function -benchmark <- function(...) { - ## run benchmark - x <- bench::mark( - ..., - iterations = 1e3, - # NOTE: there is no checks here as the - # comparision is three different methods - check = FALSE +## Shared helpers for the talib benchmark suite. The benchmarks compare: +## 1. The raw .Call into talib's C entry points (no R overhead). +## 2. talib's data.frame and matrix S3 methods around that .Call. +## 3. The equivalent TTR implementation, called with its natural API. +## +## Everything here is dependency-free (base R only) so the helpers load +## even when only {bench}, {ggplot2}, {talib}, and {TTR} are installed. + + +## Configuration + +## Observation counts to sweep over. Log-spaced because the plots use a +## log x-axis; four points keep the grid readable while still spanning +## three orders of magnitude. +BENCHMARK_SIZES <- as.integer(c(1e3, 1e4, 1e5, 1e6)) + +## Number of timed iterations bench::mark runs per (expression, n) cell. +BENCHMARK_ITERATIONS <- 1000L + +## Calls made against each expression before timing starts. Three is +## enough to prime CPU caches, branch predictors, and the R allocator +## for the data size we are about to time. +BENCHMARK_WARMUP <- 3L + + +## Synthetic data + +## Build an OHLCV data.frame with n rows. We construct the series so +## that high >= max(open, close) and low <= min(open, close); both talib +## and TTR assume that contract on HLC indicators (ATR, ADX, STOCH). +## The seed is fixed so every (indicator, n) cell sees the same data, +## which keeps the comparison fair across runs. +make_ohlc <- function(n, seed = 1903L) { + set.seed(seed) + open <- runif(n, min = 100, max = 1000) + close <- open + stats::rnorm(n, mean = 0, sd = 5) + wick <- abs(stats::rnorm(n, mean = 10, sd = 5)) + high <- pmax(open, close) + wick + low <- pmin(open, close) - wick + volume <- runif(n, min = 1e6, max = 1e7) + + data.frame( + open = open, + high = high, + low = low, + close = close, + volume = volume ) +} + + +## Warmup + +## Call each nullary function reps times. We do not need the results; +## the goal is to pull the data into cache and let R amortise any +## first-call costs (function lookup, allocator slabs) before bench::mark +## starts measuring. +warmup <- function(fns, reps = BENCHMARK_WARMUP) { + for (i in seq_len(reps)) { + for (fn in fns) { + invisible(fn()) + } + } + invisible(NULL) +} - x + +## Tidying + +## Pull the numeric columns out of a bench::mark result and tag every +## row with the indicator name and the size n. {bench} stores per-iter +## timings as list columns; we collapse them to plain doubles (in +## seconds) so the result round-trips through saveRDS cleanly and so the +## ggplot2 layer below has nothing fancy to handle. +tidy_bench <- function(x, indicator, n) { + data.frame( + indicator = indicator, + n = n, + spec = as.character(x[["expression"]]), + min = as.numeric(x[["min"]]), + median = as.numeric(x[["median"]]), + mean = vapply( + x[["time"]], + function(t) mean(as.numeric(t)), + numeric(1) + ), + max = vapply( + x[["time"]], + function(t) max(as.numeric(t)), + numeric(1) + ), + itr_per_sec = as.numeric(x[["itr/sec"]]), + mem_alloc = as.numeric(x[["mem_alloc"]]), + n_itr = as.integer(x[["n_itr"]]), + n_gc = as.integer(x[["n_gc"]]), + stringsAsFactors = FALSE + ) } -## pretty printer -pretty <- function(x, indicator, n) { - cat("Benchmarking:", indicator, paste0("N = (", n, ")"), "\n") - x[, c(1, 3, 5)] + +## Progress reporting + +## One line per cell, padded so the indicator name lines up with the +## sibling output from bench::mark. Used purely so a long run is not a +## silent black box. +banner <- function(label, n) { + message(sprintf( + " [%-12s] n = %s", + label, + format(n, big.mark = ",", scientific = FALSE) + )) } diff --git a/benchmark/results/overhead.rds b/benchmark/results/overhead.rds new file mode 100644 index 000000000..9fcc65511 Binary files /dev/null and b/benchmark/results/overhead.rds differ diff --git a/benchmark/results/plot-overhead.png b/benchmark/results/plot-overhead.png new file mode 100644 index 000000000..fd84a47e1 Binary files /dev/null and b/benchmark/results/plot-overhead.png differ diff --git a/benchmark/results/plot-speedup.png b/benchmark/results/plot-speedup.png new file mode 100644 index 000000000..cb6388a0c Binary files /dev/null and b/benchmark/results/plot-speedup.png differ diff --git a/benchmark/results/plot-ttr.png b/benchmark/results/plot-ttr.png new file mode 100644 index 000000000..e690162df Binary files /dev/null and b/benchmark/results/plot-ttr.png differ diff --git a/benchmark/results/ttr.rds b/benchmark/results/ttr.rds new file mode 100644 index 000000000..c92a10eef Binary files /dev/null and b/benchmark/results/ttr.rds differ diff --git a/benchmark/run-all.R b/benchmark/run-all.R new file mode 100644 index 000000000..d6b67779e --- /dev/null +++ b/benchmark/run-all.R @@ -0,0 +1,51 @@ +## benchmark/run-all.R +## +## Drive the full benchmark suite end to end: +## +## 1. Overhead benchmark (.Call vs data.frame vs matrix). +## 2. TTR comparison (talib vs TTR). +## 3. Save PNGs of the three plots. +## +## Invoke via `make bench` or `Rscript benchmark/run-all.R`. The full +## grid (8 indicators x 4 sizes x 1000 iters, twice) runs in minutes; +## the largest TTR cells dominate the wall clock. + +source("benchmark/benchmark-utils.R") + +out_dir <- file.path("benchmark", "results") +dir.create(out_dir, showWarnings = FALSE, recursive = TRUE) + +## Echo the configuration once so the log shows what was actually run. +message("Sizes: ", paste(format(BENCHMARK_SIZES, big.mark = ","), collapse = ", ")) +message("Iterations: ", BENCHMARK_ITERATIONS) +message("Warmup: ", BENCHMARK_WARMUP) + + +## Overhead benchmark + +## local = TRUE keeps run_overhead in this frame so we can call it +## directly without polluting the global env. The sourced file's +## stand-alone entry point is skipped because sys.nframe() > 0 here. +message("\n=== Overhead benchmark (.Call vs data.frame vs matrix) ===") +source("benchmark/benchmark-overhead.R", local = TRUE) +overhead <- run_overhead() +saveRDS(overhead, file.path(out_dir, "overhead.rds")) + + +## TTR comparison + +message("\n=== TTR comparison (talib vs TTR) ===") +source("benchmark/benchmark-ttr.R", local = TRUE) +ttr <- run_ttr() +saveRDS(ttr, file.path(out_dir, "ttr.rds")) + + +## Plots + +## save_plots writes all three PNGs with the same ggsave settings; we +## delegate so the I/O parameters live in benchmark-plots.R only. +message("\n=== Plots ===") +source("benchmark/benchmark-plots.R", local = TRUE) +save_plots(overhead, ttr, out_dir) + +message("\nAll done. Results in benchmark/results/") diff --git a/codegen/generate_indicator_core.sh b/codegen/generate_indicator_core.sh index 56d2e5d8c..b0141d3af 100755 --- a/codegen/generate_indicator_core.sh +++ b/codegen/generate_indicator_core.sh @@ -144,7 +144,7 @@ done for i in "${!in_scalars_name[@]}"; do R_SIGNATURE+=$'\tSEXP '"${in_scalars_name[$i]}"$',\n' done -R_SIGNATURE=${R_SIGNATURE%$'\n'} +R_SIGNATURE=${R_SIGNATURE%,$'\n'} ## 6) PARAM_DOC ## diff --git a/codegen/generate_unit-tests.sh b/codegen/generate_unit-tests.sh index 07e5dd983..9f907b6b2 100755 --- a/codegen/generate_unit-tests.sh +++ b/codegen/generate_unit-tests.sh @@ -66,15 +66,33 @@ output <- ${FUN}( ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) ) }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + +output <- attr( + ${FUN}(x = SPY[,1]${ADDITIONAL}), + "lookback" +) + +testthat::expect_equal( + object = output, + expected = lookback(FUN = ${FUN}, x = SPY[,1]${ADDITIONAL}) + ) + +} +) + + EOF exit 0; @@ -232,6 +250,24 @@ testthat::test_that(desc = 'Row names are respected for ', code = { ) }) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + +output <- attr( + ${FUN}(SPY), + "lookback" +) + +testthat::expect_equal( + object = output, + expected = lookback(FUN = ${FUN}, x = SPY) + ) + +} +) + EOF ## Add plotly methods @@ -345,20 +381,16 @@ testthat::test_that(desc = ' methods', code = { ${FUN}(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) EOF -fi \ No newline at end of file +fi diff --git a/codegen/parity/test_parity_template.R b/codegen/parity/test_parity_template.R index c275a39d8..f7df970ea 100644 --- a/codegen/parity/test_parity_template.R +++ b/codegen/parity/test_parity_template.R @@ -210,7 +210,7 @@ call_r_wrapper <- function(name, btc, snap) { ) { expect_equal( as.integer(lb), - as.integer(snap$lookback), + max(as.integer(snap$lookback), 1), info = paste0(name, ": lookback attribute") ) } diff --git a/codegen/templates/candlestick_template.R.in b/codegen/templates/candlestick_template.R.in index a1d685cb1..1f18d98c5 100644 --- a/codegen/templates/candlestick_template.R.in +++ b/codegen/templates/candlestick_template.R.in @@ -130,6 +130,36 @@ $FUN.matrix <- function( NextMethod() } +#' @usage NULL +${ALIAS}_lookback <- ${FUN}_lookback <- function( + x, + cols,${ARGS} + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ${FORMULA}, + data = x, + ... + ) + + .Call( + C_impl_ta_${TA_FUN}_lookback, + constructed_series[[1]], + constructed_series[[2]], + constructed_series[[3]], + constructed_series[[4]] ${CARGS} + ) +} + #' @usage NULL #' @aliases $FUN #' diff --git a/codegen/templates/candlestick_template.c.in b/codegen/templates/candlestick_template.c.in index ac9564a02..79e6e6e74 100644 --- a/codegen/templates/candlestick_template.c.in +++ b/codegen/templates/candlestick_template.c.in @@ -24,6 +24,37 @@ #include "normalize.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_${NAME}_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose{{PEN_ARG}} +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + {{PEN_READ}} + + // calculate lookback + const int lookback = {{LOOKBACK}} + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_{{NAME}}( SEXP inOpen, diff --git a/codegen/templates/indicator_template.R.in b/codegen/templates/indicator_template.R.in index 0abd895ba..84b84f02d 100644 --- a/codegen/templates/indicator_template.R.in +++ b/codegen/templates/indicator_template.R.in @@ -110,3 +110,31 @@ ${FUN}.matrix <- function( ... ) } + +#' @usage NULL +${ALIAS}_lookback <- ${FUN}_lookback <- function( + x, + cols,${ARGS} + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ${FORMULA}, + data = x, + ... + ) + + .Call( + C_impl_ta_${TA_FUN}_lookback, + ## splice:lookback:start + ## splice:lookback:end + ) +} \ No newline at end of file diff --git a/codegen/templates/indicator_template.c.in b/codegen/templates/indicator_template.c.in index c8ade4f0f..48d38ab7d 100644 --- a/codegen/templates/indicator_template.c.in +++ b/codegen/templates/indicator_template.c.in @@ -20,8 +20,29 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers // clang-format off -SEXP impl_ta_${NAME}($R_SIGNATURE +SEXP impl_ta_${NAME}_lookback($R_SIGNATURE +) +// clang-format on +{ + // values + $VALUES + + // calculate lookback + const int lookback = TA_${NAME}_Lookback($LOOKBACK_ARGS); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + +// clang-format off +SEXP impl_ta_${NAME}($R_SIGNATURE, SEXP na_bridge ) // clang-format on diff --git a/codegen/templates/moving_average_template.R.in b/codegen/templates/moving_average_template.R.in index a7fbec5ca..10ce0dbe6 100644 --- a/codegen/templates/moving_average_template.R.in +++ b/codegen/templates/moving_average_template.R.in @@ -155,22 +155,42 @@ $FUN.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x } +#' @usage NULL +${ALIAS}_lookback <- ${FUN}_lookback <- function( + x, + cols,${ARGS} + ... +) { + ## validate 'cols'-argument + ## if explicitly passed + if (!missing(cols)) { + assert_formula(cols) + } + + ## construct series + ## from input + constructed_series <- series( + x = cols, + default_formula = ${FORMULA}, + data = x, + ... + ) + + .Call( + C_impl_ta_${TA_FUN}_lookback, + ## splice:lookback:start + ## splice:lookback:end + ) +} + #' @usage NULL #' @aliases $FUN #' diff --git a/codegen/templates/numeric_template.R.in b/codegen/templates/numeric_template.R.in index adc86c376..755b20b27 100644 --- a/codegen/templates/numeric_template.R.in +++ b/codegen/templates/numeric_template.R.in @@ -26,16 +26,8 @@ ${FUN}.numeric <- function( as.logical(na.bridge) ) - ## check if it has 'dims' - ## and convert to double if - ## not to honor the 'type-safety'-esque - ## approach - ## - ## NOTE: this adds a few ns overhead but - ## its a robust alternative to code it - ## manually. Any suggestions are welcome - if (is.null(dim(x))) { - x <- as.double(x) + if (dim(x)[2] == 1L) { + dim(x) <- NULL } x diff --git a/codegen/templates/rolling_template.R.in b/codegen/templates/rolling_template.R.in index 5a8a965eb..70683b2f6 100644 --- a/codegen/templates/rolling_template.R.in +++ b/codegen/templates/rolling_template.R.in @@ -45,8 +45,13 @@ ${FUN}.default <- function( as.logical(na.bridge) ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x } #' @usage NULL @@ -67,6 +72,24 @@ ${FUN}.numeric <- function( ) + ## strip dimensions + ## while preserving + ## attributes + dim(x) <- NULL + ## return indicator - as.double(x) + x +} + +#' @usage NULL +${ALIAS}_lookback <- ${FUN}_lookback <- function( + x,${ARGS} +) { + + .Call( + C_impl_ta_${TA_FUN}_lookback, + ## splice:lookback:start + ## splice:lookback:end + ) + } diff --git a/configure b/configure index 4ff76bd4c..66de6340b 100755 --- a/configure +++ b/configure @@ -152,6 +152,25 @@ R_CXXFLAGS=$("$R_BIN" CMD config CXXFLAGS) R_CPPFLAGS=$("$R_BIN" CMD config CPPFLAGS) R_LDFLAGS=$("$R_BIN" CMD config LDFLAGS) +## Detect a compiler launcher (ccache/sccache/distcc) baked into +## R's CC/CXX by ~/.R/Makevars and hand it to CMake via +## CMAKE__COMPILER_LAUNCHER. Without this CMake invokes +## "ccache -Dfoo ..." directly and ccache misreads -D as its own +## debug-level flag (#57). +LAUNCHER_ARGS="" +case "$(basename "${R_CC_FULL%% *}")" in + ccache|sccache|distcc) + LAUNCHER_ARGS="$LAUNCHER_ARGS -DCMAKE_C_COMPILER_LAUNCHER=${R_CC_FULL%% *}" + R_CC_FULL="${R_CC_FULL#* }" + ;; +esac +case "$(basename "${R_CXX_FULL%% *}")" in + ccache|sccache|distcc) + LAUNCHER_ARGS="$LAUNCHER_ARGS -DCMAKE_CXX_COMPILER_LAUNCHER=${R_CXX_FULL%% *}" + R_CXX_FULL="${R_CXX_FULL#* }" + ;; +esac + ## details: ## R CMD config returns the compiler with leading flags baked in ## (e.g. "clang -arch x86_64" or "/opt/R/x86_64/bin/clang -arch @@ -440,6 +459,7 @@ if [ "$(( PREINSTALLED + FORCE_VENDOR ))" -ne 0 ]; then -DCMAKE_EXE_LINKER_FLAGS="$R_LDFLAGS" \ -DCMAKE_SHARED_LINKER_FLAGS="$R_LDFLAGS" \ $OSX_CMAKE_ARGS \ + $LAUNCHER_ARGS \ -DBUILD_DEV_TOOLS=OFF printf '%s\n' "$(success)" diff --git a/configure.win b/configure.win index 92fa48c83..2d71f88f6 100755 --- a/configure.win +++ b/configure.win @@ -86,6 +86,25 @@ R_CXXFLAGS=$("$R_BIN" CMD config CXXFLAGS) R_CPPFLAGS=$("$R_BIN" CMD config CPPFLAGS) R_LDFLAGS=$("$R_BIN" CMD config LDFLAGS) +## Detect a compiler launcher (ccache/sccache/distcc) baked into +## R's CC/CXX by ~/.R/Makevars and hand it to CMake via +## CMAKE__COMPILER_LAUNCHER. Without this CMake invokes +## "ccache -Dfoo ..." directly and ccache misreads -D as its own +## debug-level flag (#57). +LAUNCHER_ARGS="" +case "$(basename "${R_CC_FULL%% *}")" in + ccache|sccache|distcc) + LAUNCHER_ARGS="$LAUNCHER_ARGS -DCMAKE_C_COMPILER_LAUNCHER=${R_CC_FULL%% *}" + R_CC_FULL="${R_CC_FULL#* }" + ;; +esac +case "$(basename "${R_CXX_FULL%% *}")" in + ccache|sccache|distcc) + LAUNCHER_ARGS="$LAUNCHER_ARGS -DCMAKE_CXX_COMPILER_LAUNCHER=${R_CXX_FULL%% *}" + R_CXX_FULL="${R_CXX_FULL#* }" + ;; +esac + R_CC=$(echo "$R_CC_FULL" | awk '{print $1}') R_CC_EXTRA=$(echo "$R_CC_FULL" | cut -s -d' ' -f2-) R_CXX=$(echo "$R_CXX_FULL" | awk '{print $1}') @@ -134,9 +153,18 @@ rm -rf "$TESTDIR" ## the configure script TALIB="src/ta-lib" ## use R's compiler for the conftest below, not a guessed `cc` -## which doesn't exist on stock Windows. Honour an explicit -## CC env var if the caller set one. -CC_BIN="${CC:-$R_CC}" +## which doesn't exist on stock Windows. Honour an explicit CC +## env var if the caller set one — but strip any compiler launcher +## (ccache/sccache/distcc) the same way we do for R_CC_FULL above. +## Otherwise CC="ccache gcc" gets quoted below as a single token +## and the shell reports "ccache gcc: command not found". +CC_PROBE="${CC:-}" +case "$(basename "${CC_PROBE%% *}")" in + ccache|sccache|distcc) + CC_PROBE="${CC_PROBE#* }" + ;; +esac +CC_BIN="${CC_PROBE:-$R_CC}" ## 1.1) determine processors ## for TA-Lib building @@ -265,6 +293,7 @@ if ! cmake -S "$TALIB" -B "$BUILDROOT/cmake" -G "$GEN" \ -DCMAKE_CXX_FLAGS="$R_CXX_EXTRA $R_CXXFLAGS $R_CPPFLAGS -w ${OPTFLAGS}" \ -DCMAKE_EXE_LINKER_FLAGS="$R_LDFLAGS" \ -DCMAKE_SHARED_LINKER_FLAGS="$R_LDFLAGS" \ + $LAUNCHER_ARGS \ -DBUILD_DEV_TOOLS=OFF then rm -rf "$BUILDROOT/cmake" @@ -281,6 +310,7 @@ then -DCMAKE_CXX_FLAGS="$R_CXX_EXTRA $R_CXXFLAGS $R_CPPFLAGS -w ${OPTFLAGS}" \ -DCMAKE_EXE_LINKER_FLAGS="$R_LDFLAGS" \ -DCMAKE_SHARED_LINKER_FLAGS="$R_LDFLAGS" \ + $LAUNCHER_ARGS \ -DBUILD_DEV_TOOLS=OFF then echo diff --git a/dev/README.Rmd b/dev/README.Rmd index 3012f9491..189ca86bf 100644 --- a/dev/README.Rmd +++ b/dev/README.Rmd @@ -22,18 +22,9 @@ knitr::opts_chunk$set( warning = FALSE, echo = FALSE ) - -# indicator counts from codegen metadata -source(file.path(knitr::opts_knit$get("base.dir"), "codegen", "gen_code", "indicators.R")) -families <- vapply(indicators, function(x) x$family, character(1)) -n_patterns <- sum(families == "Pattern Recognition") -n_indicators <- sum(families != "Pattern Recognition") - -# subset BTC to last 150 rows for cleaner charts -BTC <- tail(talib::BTC, 150) ``` -# {talib}: A Technical Analysis and Candlestick Pattern Library in R +# {talib}: Fast TA-Lib indicators and candlestick patterns for 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) @@ -43,125 +34,127 @@ BTC <- tail(talib::BTC, 150) [![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/last-month/talib?color=blue)](https://r-pkg.org/pkg/talib) -[{talib}](https://serkor1.github.io/ta-lib-R/) is an R package for technical analysis, candlestick pattern recognition, and interactive financial charting---built on the [TA-Lib](https://github.com/TA-Lib/ta-lib) C library. It provides `r n_indicators` technical indicators, `r n_patterns` candlestick patterns, and a composable charting system powered by [{plotly}](https://github.com/plotly/plotly.R) and [{ggplot2}](https://ggplot2.tidyverse.org/). All indicator computations are implemented in C via `.Call()` for minimal overhead. +[{talib}](https://serkor1.github.io/ta-lib-R/) provides fast R bindings +to the [TA-Lib](https://github.com/TA-Lib/ta-lib) C library for OHLCV data: technical indicators, candlestick pattern recognition, rolling-window utilities, and composable financial charts. +It is designed for researchers, analysts, and quant developers who need technical-analysis features in R without building a heavy dependency stack. Core computations are executed in C through `.Call()`, while charting support is available through optional [{plotly}](https://github.com/plotly/plotly.R) and [{ggplot2}](https://ggplot2.tidyverse.org/) integrations.[^1] -Alongside [{TTR}](https://github.com/joshuaulrich/TTR), [{talib}](https://serkor1.github.io/ta-lib-R/) adds candlestick pattern recognition and interactive charts to the R technical analysis ecosystem. +The API covers 150+ [TA-Lib](https://github.com/TA-Lib/ta-lib)-backed functions across momentum, overlap, volatility, volume, cycle, price-transform, rolling-statistics, and candlestick-pattern families, including 61 candlestick pattern detectors. -```{r hero, fig.align = 'center', echo = TRUE} -{ - ## create a candlestick chart - talib::chart(BTC, title = "Bitcoin (BTC)") +## Why {talib}? - ## overlay Bollinger Bands on - ## the price panel - talib::indicator(talib::bollinger_bands) +
- ## mark Engulfing candlestick - ## patterns on the chart - talib::indicator(talib::engulfing, data = BTC) +| Need | {talib}| +|:----------------------|:-----------------------------------------------------------------------------------------| +| Technical indicators | TA-Lib-backed moving averages, momentum, volatility, volume, cycle, and overlap studies | +| Candlestick patterns | Built-in Japanese candlestick pattern recognition | +| OHLCV workflows | Works directly with open, high, low, close, and volume columns | +| Performance | Computation delegated to C routines through `.Call()` | +| Dependencies | Minimal required R dependencies; plotting packages are optional | +| Charts | Composable financial charts with optional `{plotly}` and `{ggplot2}` support | - ## add RSI and volume as - ## separate sub-panels - talib::indicator(talib::RSI) - talib::indicator(talib::trading_volume) -} -``` +
-## Indicators +## Installation[^2] -Every indicator follows the same interface: pass an OHLCV `data.frame` or `matrix` and get the same type back. The return type always matches the input. +Install the release version from CRAN: -```{r indicators, echo = TRUE} -## compute Bollinger Bands -## on BTC OHLCV data -tail( - talib::bollinger_bands(BTC) -) +```{r install-cran, echo = TRUE, eval = FALSE} +install.packages("talib") ``` -## Candlestick Patterns - -{talib} recognizes `r n_patterns` candlestick patterns---from single-candle formations like Doji and Hammer to multi-candle patterns like Morning Star and Three White Soldiers. Each pattern returns a normalized score: `1` (bullish), `-1` (bearish), or `0` (no pattern). +Install the development version from GitHub: -```{r patterns, echo = TRUE} -## detect Engulfing patterns: -## 1 = bullish, -1 = bearish, 0 = none -tail( - talib::engulfing(BTC) -) +```{r install-dev, echo = TRUE, eval = FALSE} +pak::pak("serkor1/ta-lib-R") ``` -## Charts - -Charts are built in two steps: `chart()` creates the price chart, then `indicator()` layers on technical indicators. Overlap indicators (moving averages, Bollinger Bands) draw on the price panel; oscillators (RSI, MACD) get their own sub-panels. - -```{r charting, fig.align = 'center', fig.height = 7, echo = TRUE} -{ - ## price chart with two moving - ## averages and MACD below - talib::chart(BTC) - talib::indicator(talib::SMA, n = 7) - talib::indicator(talib::SMA, n = 14) - talib::indicator(talib::MACD) -} -``` +## Quick start -Multiple indicators can share a sub-panel by passing them as calls: +All functions provide S3 methods for ``, ``, and---where applicable---`` inputs. The general convention is simple: the output uses the same container type as the input. -```{r combined, fig.align = 'center', fig.height = 7, echo = TRUE} -{ - talib::chart(BTC) - talib::indicator(talib::BBANDS) +```{r quick-start, echo=TRUE} +## calculate the +## relative strength index +relative_strength_index <- talib::RSI( + talib::BTC +) - ## pass multiple calls to combine - ## them on a single sub-panel - talib::indicator( - talib::RSI(n = 10), - talib::RSI(n = 14), - talib::RSI(n = 21) - ) -} +## display results +tail( + relative_strength_index +) ``` -The charting system ships with 5 built-in themes: `default`, `hawks_and_doves`, `payout`, `tp_slapped`, and `trust_the_process`. Switch themes with `set_theme()`. Both [{plotly}](https://github.com/plotly/plotly.R) (interactive, default) and [{ggplot2}](https://ggplot2.tidyverse.org/) (static) backends are supported: +Indicator outputs preserve input length, which keeps results aligned with the +original OHLCV rows. -```{r ggplot2-setup, include = FALSE} -options(talib.chart.backend = "ggplot2") -talib::set_theme("hawks_and_doves") -``` +```{r multiple-indicators, echo = TRUE} +## combine multiple +## indicators +features <- cbind( + talib::relative_strength_index(talib::BTC), + talib::bollinger_bands(talib::BTC), + talib::engulfing(talib::BTC) +) -```{r ggplot2, fig.align = 'center', fig.height = 7, echo = TRUE} -{ - ## switch to ggplot2 backend with - ## the "Hawks and Doves" theme - talib::set_theme("hawks_and_doves") - talib::chart(BTC, title = "Bitcoin (BTC)") - talib::indicator(talib::BBANDS) - talib::indicator(talib::RSI) - talib::indicator(talib::trading_volume) -} +tail(features) ``` -```{r ggplot2-teardown, include = FALSE} -options(talib.chart.backend = "plotly") -talib::set_theme("default") -``` +## Charting + +[{talib}](https://serkor1.github.io/ta-lib-R/) comes with a composable charting API built on two core functions: `indicator()` and `chart()`---both functions are built on `model.frame` for maximum flexibility: -## Column selection +```{r charting-example, echo=TRUE} +## subset data and +## store as 'BTC' +BTC <- talib::BTC[1:75, ] -Indicators use the columns they need automatically. When your data has non-standard column names, remap them with formula syntax: +## construct chart in a brace block +## alternatively use `|>` +{ + ## initialize main chart + talib::chart( + x = BTC, + title = "Bitcoin" + ) -```{r cols, echo = TRUE, eval = FALSE} -## remap 'price' to the close column -talib::RSI(x, cols = ~price) + ## add Bollinger Bands to + ## the existing chart + talib::indicator( + talib::BBANDS + ) -## remap hi, lo, last to high, low, close -talib::stochastic(x, cols = ~ hi + lo + last) + ## add Simple Moving Averages (SMA) + ## to the chart in a loop + for (n in seq(5, 15, by = 3)) { + talib::indicator( + talib::SMA, + n = n + ) + } + + ## similar subchart indicators + ## like the Relative Strength Index + ## can be grouped to avoid repeated + ## subpanels + talib::indicator( + talib::RSI(n = 10), + talib::RSI(n = 14), + talib::RSI(n = 21) + ) + + ## identify Doji patterns + ## and add them to the chart + talib::indicator( + talib::doji + ) +} ``` -## Naming +## Implementation: {talib} vs upstream (TA-Lib Core) -Functions use descriptive snake_case names, but every function is aliased to its TA-Lib shorthand for compatibility with the broader ecosystem: +Functions use descriptive snake_case names, but every function is aliased to its [TA-Lib](https://github.com/TA-Lib/ta-lib) shorthand for compatibility with the broader ecosystem:
@@ -177,51 +170,74 @@ Functions use descriptive snake_case names, but every function is aliased to its
-```{r alias, echo = TRUE} -## snake_case and TA-Lib aliases -## are identical -all.equal( - target = talib::bollinger_bands(BTC), - current = talib::BBANDS(BTC) -) -``` +### Interface: R vs Python -## Installation[^1] +The main difference between the R and Python interfaces is how OHLCV series are passed into each indicator function. +Below is an example of identifying `Doji` patterns in R and Python. -Install the release version from CRAN: +In Python, each series is passed independently: -```{r install-cran, echo = TRUE, eval = FALSE} -install.packages("talib") -``` +```python +import numpy as np +import talib -Install the development version from GitHub: +o = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=float) +h = np.array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], dtype=float) +l = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=float) +c = np.array([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1], dtype=float) -```{r install-dev, echo = TRUE, eval = FALSE} -pak::pak("serkor1/ta-lib-R") +print( + talib.CDLDOJI(o, h, l, c) +) ``` -### Aggressive optimizations +In R the series are passed as a tabular container: -Unknown flags passed to `configure` are forwarded verbatim to both the CMake build of the vendored TA-Lib and the R wrapper compile step. Rebuild from source with any compiler flags you like: +```{r r-vs-python-block, echo = TRUE, eval = FALSE} +ohlc <- data.frame( + open = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + high = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), + low = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + close = c(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1) +) -```{r install-native, echo = TRUE, eval = FALSE} -install.packages( - "talib", - type = "source", - configure.args = "-O3 -march=native" +talib::CDLDOJI( + ohlc ) ``` -Or from a local clone: +All default series arguments are handled internally, and the `R` interface is therefore higher-level: users pass one OHLC container rather than manually splitting the series. + +## Contributing and cloning + +Contributions are welcome. For non-trivial changes, please open an issue first to discuss the proposed design, API impact, and testing approach. + +This repository vendors [TA-Lib](https://github.com/TA-Lib/ta-lib) as a Git submodule. Clone the repository with submodules enabled: -```shell -git clone --recursive https://github.com/serkor1/ta-lib-R.git +```sh +git clone --recurse-submodules https://github.com/serkor1/ta-lib-R.git cd ta-lib-R -R CMD INSTALL . --configure-args="-O3 -march=native" ``` +If you already cloned the repository without submodules, initialize them with: + +```sh +git submodule update --init --recursive +``` + +Most indicator wrappers, helper functions, documentation fragments, and unit tests are generated from the scripts in `codegen/`. The charting interface is maintained separately. + +Common development tasks are exposed through Make targets: + +```sh +make help +``` + +See CONTRIBUTING.md for the full development workflow. + ## Code of Conduct 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]: [TA-Lib](https://github.com/TA-Lib/ta-lib) is vendored via `CMake`, so a pre-installed TA-Lib is not required. Some systems (Windows in particular) may require `CMake` to be explicitly installed. +[^1]: See `benchmark/` for detailed benchmarks against [{TTR}]() and general performance across multiple indicators. +[^2]: `{talib}` is a compiled package. CRAN binaries are available for standard platforms when provided by CRAN. Source installation requires a working compiler toolchain and [CMake](https://cmake.org/). \ No newline at end of file diff --git a/man/figures/README-charting-1.png b/man/figures/README-charting-1.png deleted file mode 100644 index 652182972..000000000 Binary files a/man/figures/README-charting-1.png and /dev/null differ diff --git a/man/figures/README-charting-example-1.png b/man/figures/README-charting-example-1.png new file mode 100644 index 000000000..67ea5c625 Binary files /dev/null and b/man/figures/README-charting-example-1.png differ diff --git a/man/figures/README-combined-1.png b/man/figures/README-combined-1.png deleted file mode 100644 index 94090cb88..000000000 Binary files a/man/figures/README-combined-1.png and /dev/null differ diff --git a/man/figures/README-ggplot2-1.png b/man/figures/README-ggplot2-1.png deleted file mode 100644 index e19832cb9..000000000 Binary files a/man/figures/README-ggplot2-1.png and /dev/null differ diff --git a/man/figures/README-hero-1.png b/man/figures/README-hero-1.png deleted file mode 100644 index 23ee8409b..000000000 Binary files a/man/figures/README-hero-1.png and /dev/null differ diff --git a/src/api.h b/src/api.h index a119d9431..b88475603 100644 --- a/src/api.h +++ b/src/api.h @@ -5,133 +5,261 @@ #include // clang-format off +SEXP impl_ta_ACCBANDS_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_ACCBANDS(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_AD_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP inVolume); +SEXP impl_ta_ADOSC_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP inVolume, SEXP optInFastPeriod, SEXP optInSlowPeriod); SEXP impl_ta_ADOSC(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP inVolume, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP na_bridge); SEXP impl_ta_AD(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP inVolume, SEXP na_bridge); +SEXP impl_ta_ADX_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); +SEXP impl_ta_ADXR_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_ADXR(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); SEXP impl_ta_ADX(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_APO_lookback(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInMAType); SEXP impl_ta_APO(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInMAType, SEXP na_bridge); +SEXP impl_ta_AROON_lookback(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod); +SEXP impl_ta_AROONOSC_lookback(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod); SEXP impl_ta_AROONOSC(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); SEXP impl_ta_AROON(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_ATR_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_ATR(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_AVGPRICE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_AVGPRICE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); +SEXP impl_ta_BBANDS_lookback(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDevUp, SEXP optInNbDevDn, SEXP optInMAType); SEXP impl_ta_BBANDS(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDevUp, SEXP optInNbDevDn, SEXP optInMAType, SEXP na_bridge); +SEXP impl_ta_BETA_lookback(SEXP inReal0, SEXP inReal1, SEXP optInTimePeriod); SEXP impl_ta_BETA(SEXP inReal0, SEXP inReal1, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_BOP_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_BOP(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); +SEXP impl_ta_CCI_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_CCI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_CDL2CROWS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDL2CROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDL3BLACKCROWS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDL3BLACKCROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDL3INSIDE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDL3INSIDE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDL3LINESTRIKE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDL3LINESTRIKE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDL3OUTSIDE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDL3OUTSIDE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDL3STARSINSOUTH_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDL3STARSINSOUTH(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDL3WHITESOLDIERS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDL3WHITESOLDIERS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLABANDONEDBABY_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration); SEXP impl_ta_CDLABANDONEDBABY(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLADVANCEBLOCK_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLADVANCEBLOCK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLBELTHOLD_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLBELTHOLD(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLBREAKAWAY_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLBREAKAWAY(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLCLOSINGMARUBOZU_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLCLOSINGMARUBOZU(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLCONCEALBABYSWALL_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLCONCEALBABYSWALL(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLCOUNTERATTACK_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLCOUNTERATTACK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLDARKCLOUDCOVER_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration); SEXP impl_ta_CDLDARKCLOUDCOVER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLDOJI_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLDOJISTAR_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLDOJISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLDRAGONFLYDOJI_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLDRAGONFLYDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLENGULFING_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLENGULFING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLEVENINGDOJISTAR_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration); SEXP impl_ta_CDLEVENINGDOJISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLEVENINGSTAR_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration); SEXP impl_ta_CDLEVENINGSTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLGAPSIDESIDEWHITE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLGAPSIDESIDEWHITE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLGRAVESTONEDOJI_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLGRAVESTONEDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLHAMMER_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLHAMMER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLHANGINGMAN_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLHANGINGMAN(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLHARAMICROSS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLHARAMICROSS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLHARAMI_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLHARAMI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLHIGHWAVE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLHIGHWAVE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLHIKKAKE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); +SEXP impl_ta_CDLHIKKAKEMOD_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLHIKKAKEMOD(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); SEXP impl_ta_CDLHIKKAKE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLHOMINGPIGEON_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLHOMINGPIGEON(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLIDENTICAL3CROWS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLIDENTICAL3CROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLINNECK_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLINNECK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLINVERTEDHAMMER_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLINVERTEDHAMMER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLKICKINGBYLENGTH_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLKICKINGBYLENGTH(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLKICKING_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLKICKING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLLADDERBOTTOM_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLLADDERBOTTOM(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLLONGLEGGEDDOJI_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLLONGLEGGEDDOJI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLLONGLINE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLLONGLINE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLMARUBOZU_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLMARUBOZU(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLMATCHINGLOW_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLMATCHINGLOW(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLMATHOLD_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration); SEXP impl_ta_CDLMATHOLD(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLMORNINGDOJISTAR_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration); SEXP impl_ta_CDLMORNINGDOJISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLMORNINGSTAR_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration); SEXP impl_ta_CDLMORNINGSTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInPenetration, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLONNECK_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLONNECK(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLPIERCING_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLPIERCING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLRICKSHAWMAN_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLRICKSHAWMAN(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLRISEFALL3METHODS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLRISEFALL3METHODS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLSEPARATINGLINES_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLSEPARATINGLINES(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLSHOOTINGSTAR_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLSHOOTINGSTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLSHORTLINE_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLSHORTLINE(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLSPINNINGTOP_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLSPINNINGTOP(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLSTALLEDPATTERN_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLSTALLEDPATTERN(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLSTICKSANDWICH_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLSTICKSANDWICH(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLTAKURI_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLTAKURI(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLTASUKIGAP_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLTASUKIGAP(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLTHRUSTING_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLTHRUSTING(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLTRISTAR_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLTRISTAR(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLUNIQUE3RIVER_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLUNIQUE3RIVER(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLUPSIDEGAP2CROWS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLUPSIDEGAP2CROWS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CDLXSIDEGAP3METHODS_lookback(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_CDLXSIDEGAP3METHODS(SEXP inOpen, SEXP inHigh, SEXP inLow, SEXP inClose, SEXP flag, SEXP na_bridge); +SEXP impl_ta_CMO_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_CMO(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_CORREL_lookback(SEXP inReal0, SEXP inReal1, SEXP optInTimePeriod); SEXP impl_ta_CORREL(SEXP inReal0, SEXP inReal1, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_DEMA_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_DEMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_DX_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_DX(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_EMA_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_EMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_HT_DCPERIOD_lookback(SEXP inReal); SEXP impl_ta_HT_DCPERIOD(SEXP inReal, SEXP na_bridge); +SEXP impl_ta_HT_DCPHASE_lookback(SEXP inReal); SEXP impl_ta_HT_DCPHASE(SEXP inReal, SEXP na_bridge); +SEXP impl_ta_HT_PHASOR_lookback(SEXP inReal); SEXP impl_ta_HT_PHASOR(SEXP inReal, SEXP na_bridge); +SEXP impl_ta_HT_SINE_lookback(SEXP inReal); SEXP impl_ta_HT_SINE(SEXP inReal, SEXP na_bridge); +SEXP impl_ta_HT_TRENDLINE_lookback(SEXP inReal); SEXP impl_ta_HT_TRENDLINE(SEXP inReal, SEXP na_bridge); +SEXP impl_ta_HT_TRENDMODE_lookback(SEXP inReal); SEXP impl_ta_HT_TRENDMODE(SEXP inReal, SEXP na_bridge); +SEXP impl_ta_IMI_lookback(SEXP inOpen, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_IMI(SEXP inOpen, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_KAMA_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_KAMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_MACDEXT_lookback(SEXP inReal, SEXP optInFastPeriod, SEXP optInFastMAType, SEXP optInSlowPeriod, SEXP optInSlowMAType, SEXP optInSignalPeriod, SEXP optInSignalMAType); SEXP impl_ta_MACDEXT(SEXP inReal, SEXP optInFastPeriod, SEXP optInFastMAType, SEXP optInSlowPeriod, SEXP optInSlowMAType, SEXP optInSignalPeriod, SEXP optInSignalMAType, SEXP na_bridge); +SEXP impl_ta_MACDFIX_lookback(SEXP inReal, SEXP optInSignalPeriod); SEXP impl_ta_MACDFIX(SEXP inReal, SEXP optInSignalPeriod, SEXP na_bridge); +SEXP impl_ta_MACD_lookback(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInSignalPeriod); SEXP impl_ta_MACD(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInSignalPeriod, SEXP na_bridge); +SEXP impl_ta_MAMA_lookback(SEXP inReal, SEXP optInFastLimit, SEXP optInSlowLimit); SEXP impl_ta_MAMA(SEXP inReal, SEXP optInFastLimit, SEXP optInSlowLimit, SEXP na_bridge); +SEXP impl_ta_MAX_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_MAX(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_MEDPRICE_lookback(SEXP inHigh, SEXP inLow); SEXP impl_ta_MEDPRICE(SEXP inHigh, SEXP inLow, SEXP na_bridge); +SEXP impl_ta_MFI_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP inVolume, SEXP optInTimePeriod); SEXP impl_ta_MFI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP inVolume, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_MIDPRICE_lookback(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod); SEXP impl_ta_MIDPRICE(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_MIN_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_MIN(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_MINUS_DI_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_MINUS_DI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_MINUS_DM_lookback(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod); SEXP impl_ta_MINUS_DM(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_MOM_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_MOM(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_NATR_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_NATR(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_OBV_lookback(SEXP inReal, SEXP inVolume); SEXP impl_ta_OBV(SEXP inReal, SEXP inVolume, SEXP na_bridge); +SEXP impl_ta_PLUS_DI_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_PLUS_DI(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_PLUS_DM_lookback(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod); SEXP impl_ta_PLUS_DM(SEXP inHigh, SEXP inLow, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_PPO_lookback(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInMAType); SEXP impl_ta_PPO(SEXP inReal, SEXP optInFastPeriod, SEXP optInSlowPeriod, SEXP optInMAType, SEXP na_bridge); +SEXP impl_ta_ROC_lookback(SEXP inReal, SEXP optInTimePeriod); +SEXP impl_ta_ROCR_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_ROCR(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); SEXP impl_ta_ROC(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_RSI_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_RSI(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_SAREXT_lookback(SEXP inHigh, SEXP inLow, SEXP optInStartValue, SEXP optInOffsetOnReverse, SEXP optInAccelerationInitLong, SEXP optInAccelerationLong, SEXP optInAccelerationMaxLong, SEXP optInAccelerationInitShort, SEXP optInAccelerationShort, SEXP optInAccelerationMaxShort); SEXP impl_ta_SAREXT(SEXP inHigh, SEXP inLow, SEXP optInStartValue, SEXP optInOffsetOnReverse, SEXP optInAccelerationInitLong, SEXP optInAccelerationLong, SEXP optInAccelerationMaxLong, SEXP optInAccelerationInitShort, SEXP optInAccelerationShort, SEXP optInAccelerationMaxShort, SEXP na_bridge); +SEXP impl_ta_SAR_lookback(SEXP inHigh, SEXP inLow, SEXP optInAcceleration, SEXP optInMaximum); SEXP impl_ta_SAR(SEXP inHigh, SEXP inLow, SEXP optInAcceleration, SEXP optInMaximum, SEXP na_bridge); +SEXP impl_ta_SMA_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_SMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_STDDEV_lookback(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDev); SEXP impl_ta_STDDEV(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDev, SEXP na_bridge); +SEXP impl_ta_STOCHF_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInFastK_Period, SEXP optInFastD_Period, SEXP optInFastD_MAType); SEXP impl_ta_STOCHF(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInFastK_Period, SEXP optInFastD_Period, SEXP optInFastD_MAType, SEXP na_bridge); +SEXP impl_ta_STOCH_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInFastK_Period, SEXP optInSlowK_Period, SEXP optInSlowK_MAType, SEXP optInSlowD_Period, SEXP optInSlowD_MAType); +SEXP impl_ta_STOCHRSI_lookback(SEXP inReal, SEXP optInTimePeriod, SEXP optInFastK_Period, SEXP optInFastD_Period, SEXP optInFastD_MAType); SEXP impl_ta_STOCHRSI(SEXP inReal, SEXP optInTimePeriod, SEXP optInFastK_Period, SEXP optInFastD_Period, SEXP optInFastD_MAType, SEXP na_bridge); SEXP impl_ta_STOCH(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInFastK_Period, SEXP optInSlowK_Period, SEXP optInSlowK_MAType, SEXP optInSlowD_Period, SEXP optInSlowD_MAType, SEXP na_bridge); +SEXP impl_ta_SUM_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_SUM(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_T3_lookback(SEXP inReal, SEXP optInTimePeriod, SEXP optInVFactor); SEXP impl_ta_T3(SEXP inReal, SEXP optInTimePeriod, SEXP optInVFactor, SEXP na_bridge); +SEXP impl_ta_TEMA_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_TEMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_TRANGE_lookback(SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_TRANGE(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); +SEXP impl_ta_TRIMA_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_TRIMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_TRIX_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_TRIX(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_TYPPRICE_lookback(SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_TYPPRICE(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); +SEXP impl_ta_ULTOSC_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod1, SEXP optInTimePeriod2, SEXP optInTimePeriod3); SEXP impl_ta_ULTOSC(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod1, SEXP optInTimePeriod2, SEXP optInTimePeriod3, SEXP na_bridge); +SEXP impl_ta_VAR_lookback(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDev); SEXP impl_ta_VAR(SEXP inReal, SEXP optInTimePeriod, SEXP optInNbDev, SEXP na_bridge); +SEXP impl_ta_VOLUME_lookback(SEXP inReal, SEXP maSpec); SEXP impl_ta_VOLUME(SEXP inReal, SEXP maSpec, SEXP na_rm); +SEXP impl_ta_WCLPRICE_lookback(SEXP inHigh, SEXP inLow, SEXP inClose); SEXP impl_ta_WCLPRICE(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP na_bridge); +SEXP impl_ta_WILLR_lookback(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod); SEXP impl_ta_WILLR(SEXP inHigh, SEXP inLow, SEXP inClose, SEXP optInTimePeriod, SEXP na_bridge); +SEXP impl_ta_WMA_lookback(SEXP inReal, SEXP optInTimePeriod); SEXP impl_ta_WMA(SEXP inReal, SEXP optInTimePeriod, SEXP na_bridge); SEXP initialize_ta_lib(void); SEXP map_dfr_double(SEXP x); diff --git a/src/attributes.c b/src/attributes.c index 61757ad08..affe5bbb4 100644 --- a/src/attributes.c +++ b/src/attributes.c @@ -27,12 +27,21 @@ static inline SEXP ta_lookback(void) { void set_attribute( SEXP output_object, int lookback, - int *protection_count) { - // clang-format on - + int *protection_count +) +// clang-format on +{ + // upstream returns -1 if the indicator and data pairs + // are invalid - -1 is handled on the R side but + // attributes needs to be handled here - some functions + // returns (weighted closing price, for one) returns lookback + // of zero; this has to be normalized to 1 (can't calculate values on nothing) + int normalized_lookback = + lookback < 0 ? lookback : (lookback < 1 ? 1 : lookback); SEXP symbolic_value = ta_lookback(); - SEXP value = PROTECT(Rf_ScalarInteger(lookback)); + SEXP value = PROTECT(Rf_ScalarInteger(normalized_lookback)); + if (protection_count) { (*protection_count)++; } diff --git a/src/init.c b/src/init.c index a245ced9f..cc2fe0911 100644 --- a/src/init.c +++ b/src/init.c @@ -11,133 +11,261 @@ // clang-format on static const R_CallMethodDef CallEntries[] = { + CALLDEF(impl_ta_ACCBANDS_lookback, 4), CALLDEF(impl_ta_ACCBANDS, 5), + CALLDEF(impl_ta_AD_lookback, 4), + CALLDEF(impl_ta_ADOSC_lookback, 6), CALLDEF(impl_ta_ADOSC, 7), CALLDEF(impl_ta_AD, 5), + CALLDEF(impl_ta_ADX_lookback, 4), + CALLDEF(impl_ta_ADXR_lookback, 4), CALLDEF(impl_ta_ADXR, 5), CALLDEF(impl_ta_ADX, 5), + CALLDEF(impl_ta_APO_lookback, 4), CALLDEF(impl_ta_APO, 5), + CALLDEF(impl_ta_AROON_lookback, 3), + CALLDEF(impl_ta_AROONOSC_lookback, 3), CALLDEF(impl_ta_AROONOSC, 4), CALLDEF(impl_ta_AROON, 4), + CALLDEF(impl_ta_ATR_lookback, 4), CALLDEF(impl_ta_ATR, 5), + CALLDEF(impl_ta_AVGPRICE_lookback, 4), CALLDEF(impl_ta_AVGPRICE, 5), + CALLDEF(impl_ta_BBANDS_lookback, 5), CALLDEF(impl_ta_BBANDS, 6), + CALLDEF(impl_ta_BETA_lookback, 3), CALLDEF(impl_ta_BETA, 4), + CALLDEF(impl_ta_BOP_lookback, 4), CALLDEF(impl_ta_BOP, 5), + CALLDEF(impl_ta_CCI_lookback, 4), CALLDEF(impl_ta_CCI, 5), + CALLDEF(impl_ta_CDL2CROWS_lookback, 4), CALLDEF(impl_ta_CDL2CROWS, 6), + CALLDEF(impl_ta_CDL3BLACKCROWS_lookback, 4), CALLDEF(impl_ta_CDL3BLACKCROWS, 6), + CALLDEF(impl_ta_CDL3INSIDE_lookback, 4), CALLDEF(impl_ta_CDL3INSIDE, 6), + CALLDEF(impl_ta_CDL3LINESTRIKE_lookback, 4), CALLDEF(impl_ta_CDL3LINESTRIKE, 6), + CALLDEF(impl_ta_CDL3OUTSIDE_lookback, 4), CALLDEF(impl_ta_CDL3OUTSIDE, 6), + CALLDEF(impl_ta_CDL3STARSINSOUTH_lookback, 4), CALLDEF(impl_ta_CDL3STARSINSOUTH, 6), + CALLDEF(impl_ta_CDL3WHITESOLDIERS_lookback, 4), CALLDEF(impl_ta_CDL3WHITESOLDIERS, 6), + CALLDEF(impl_ta_CDLABANDONEDBABY_lookback, 5), CALLDEF(impl_ta_CDLABANDONEDBABY, 7), + CALLDEF(impl_ta_CDLADVANCEBLOCK_lookback, 4), CALLDEF(impl_ta_CDLADVANCEBLOCK, 6), + CALLDEF(impl_ta_CDLBELTHOLD_lookback, 4), CALLDEF(impl_ta_CDLBELTHOLD, 6), + CALLDEF(impl_ta_CDLBREAKAWAY_lookback, 4), CALLDEF(impl_ta_CDLBREAKAWAY, 6), + CALLDEF(impl_ta_CDLCLOSINGMARUBOZU_lookback, 4), CALLDEF(impl_ta_CDLCLOSINGMARUBOZU, 6), + CALLDEF(impl_ta_CDLCONCEALBABYSWALL_lookback, 4), CALLDEF(impl_ta_CDLCONCEALBABYSWALL, 6), + CALLDEF(impl_ta_CDLCOUNTERATTACK_lookback, 4), CALLDEF(impl_ta_CDLCOUNTERATTACK, 6), + CALLDEF(impl_ta_CDLDARKCLOUDCOVER_lookback, 5), CALLDEF(impl_ta_CDLDARKCLOUDCOVER, 7), + CALLDEF(impl_ta_CDLDOJI_lookback, 4), CALLDEF(impl_ta_CDLDOJI, 6), + CALLDEF(impl_ta_CDLDOJISTAR_lookback, 4), CALLDEF(impl_ta_CDLDOJISTAR, 6), + CALLDEF(impl_ta_CDLDRAGONFLYDOJI_lookback, 4), CALLDEF(impl_ta_CDLDRAGONFLYDOJI, 6), + CALLDEF(impl_ta_CDLENGULFING_lookback, 4), CALLDEF(impl_ta_CDLENGULFING, 6), + CALLDEF(impl_ta_CDLEVENINGDOJISTAR_lookback, 5), CALLDEF(impl_ta_CDLEVENINGDOJISTAR, 7), + CALLDEF(impl_ta_CDLEVENINGSTAR_lookback, 5), CALLDEF(impl_ta_CDLEVENINGSTAR, 7), + CALLDEF(impl_ta_CDLGAPSIDESIDEWHITE_lookback, 4), CALLDEF(impl_ta_CDLGAPSIDESIDEWHITE, 6), + CALLDEF(impl_ta_CDLGRAVESTONEDOJI_lookback, 4), CALLDEF(impl_ta_CDLGRAVESTONEDOJI, 6), + CALLDEF(impl_ta_CDLHAMMER_lookback, 4), CALLDEF(impl_ta_CDLHAMMER, 6), + CALLDEF(impl_ta_CDLHANGINGMAN_lookback, 4), CALLDEF(impl_ta_CDLHANGINGMAN, 6), + CALLDEF(impl_ta_CDLHARAMICROSS_lookback, 4), CALLDEF(impl_ta_CDLHARAMICROSS, 6), + CALLDEF(impl_ta_CDLHARAMI_lookback, 4), CALLDEF(impl_ta_CDLHARAMI, 6), + CALLDEF(impl_ta_CDLHIGHWAVE_lookback, 4), CALLDEF(impl_ta_CDLHIGHWAVE, 6), + CALLDEF(impl_ta_CDLHIKKAKE_lookback, 4), + CALLDEF(impl_ta_CDLHIKKAKEMOD_lookback, 4), CALLDEF(impl_ta_CDLHIKKAKEMOD, 6), CALLDEF(impl_ta_CDLHIKKAKE, 6), + CALLDEF(impl_ta_CDLHOMINGPIGEON_lookback, 4), CALLDEF(impl_ta_CDLHOMINGPIGEON, 6), + CALLDEF(impl_ta_CDLIDENTICAL3CROWS_lookback, 4), CALLDEF(impl_ta_CDLIDENTICAL3CROWS, 6), + CALLDEF(impl_ta_CDLINNECK_lookback, 4), CALLDEF(impl_ta_CDLINNECK, 6), + CALLDEF(impl_ta_CDLINVERTEDHAMMER_lookback, 4), CALLDEF(impl_ta_CDLINVERTEDHAMMER, 6), + CALLDEF(impl_ta_CDLKICKINGBYLENGTH_lookback, 4), CALLDEF(impl_ta_CDLKICKINGBYLENGTH, 6), + CALLDEF(impl_ta_CDLKICKING_lookback, 4), CALLDEF(impl_ta_CDLKICKING, 6), + CALLDEF(impl_ta_CDLLADDERBOTTOM_lookback, 4), CALLDEF(impl_ta_CDLLADDERBOTTOM, 6), + CALLDEF(impl_ta_CDLLONGLEGGEDDOJI_lookback, 4), CALLDEF(impl_ta_CDLLONGLEGGEDDOJI, 6), + CALLDEF(impl_ta_CDLLONGLINE_lookback, 4), CALLDEF(impl_ta_CDLLONGLINE, 6), + CALLDEF(impl_ta_CDLMARUBOZU_lookback, 4), CALLDEF(impl_ta_CDLMARUBOZU, 6), + CALLDEF(impl_ta_CDLMATCHINGLOW_lookback, 4), CALLDEF(impl_ta_CDLMATCHINGLOW, 6), + CALLDEF(impl_ta_CDLMATHOLD_lookback, 5), CALLDEF(impl_ta_CDLMATHOLD, 7), + CALLDEF(impl_ta_CDLMORNINGDOJISTAR_lookback, 5), CALLDEF(impl_ta_CDLMORNINGDOJISTAR, 7), + CALLDEF(impl_ta_CDLMORNINGSTAR_lookback, 5), CALLDEF(impl_ta_CDLMORNINGSTAR, 7), + CALLDEF(impl_ta_CDLONNECK_lookback, 4), CALLDEF(impl_ta_CDLONNECK, 6), + CALLDEF(impl_ta_CDLPIERCING_lookback, 4), CALLDEF(impl_ta_CDLPIERCING, 6), + CALLDEF(impl_ta_CDLRICKSHAWMAN_lookback, 4), CALLDEF(impl_ta_CDLRICKSHAWMAN, 6), + CALLDEF(impl_ta_CDLRISEFALL3METHODS_lookback, 4), CALLDEF(impl_ta_CDLRISEFALL3METHODS, 6), + CALLDEF(impl_ta_CDLSEPARATINGLINES_lookback, 4), CALLDEF(impl_ta_CDLSEPARATINGLINES, 6), + CALLDEF(impl_ta_CDLSHOOTINGSTAR_lookback, 4), CALLDEF(impl_ta_CDLSHOOTINGSTAR, 6), + CALLDEF(impl_ta_CDLSHORTLINE_lookback, 4), CALLDEF(impl_ta_CDLSHORTLINE, 6), + CALLDEF(impl_ta_CDLSPINNINGTOP_lookback, 4), CALLDEF(impl_ta_CDLSPINNINGTOP, 6), + CALLDEF(impl_ta_CDLSTALLEDPATTERN_lookback, 4), CALLDEF(impl_ta_CDLSTALLEDPATTERN, 6), + CALLDEF(impl_ta_CDLSTICKSANDWICH_lookback, 4), CALLDEF(impl_ta_CDLSTICKSANDWICH, 6), + CALLDEF(impl_ta_CDLTAKURI_lookback, 4), CALLDEF(impl_ta_CDLTAKURI, 6), + CALLDEF(impl_ta_CDLTASUKIGAP_lookback, 4), CALLDEF(impl_ta_CDLTASUKIGAP, 6), + CALLDEF(impl_ta_CDLTHRUSTING_lookback, 4), CALLDEF(impl_ta_CDLTHRUSTING, 6), + CALLDEF(impl_ta_CDLTRISTAR_lookback, 4), CALLDEF(impl_ta_CDLTRISTAR, 6), + CALLDEF(impl_ta_CDLUNIQUE3RIVER_lookback, 4), CALLDEF(impl_ta_CDLUNIQUE3RIVER, 6), + CALLDEF(impl_ta_CDLUPSIDEGAP2CROWS_lookback, 4), CALLDEF(impl_ta_CDLUPSIDEGAP2CROWS, 6), + CALLDEF(impl_ta_CDLXSIDEGAP3METHODS_lookback, 4), CALLDEF(impl_ta_CDLXSIDEGAP3METHODS, 6), + CALLDEF(impl_ta_CMO_lookback, 2), CALLDEF(impl_ta_CMO, 3), + CALLDEF(impl_ta_CORREL_lookback, 3), CALLDEF(impl_ta_CORREL, 4), + CALLDEF(impl_ta_DEMA_lookback, 2), CALLDEF(impl_ta_DEMA, 3), + CALLDEF(impl_ta_DX_lookback, 4), CALLDEF(impl_ta_DX, 5), + CALLDEF(impl_ta_EMA_lookback, 2), CALLDEF(impl_ta_EMA, 3), + CALLDEF(impl_ta_HT_DCPERIOD_lookback, 1), CALLDEF(impl_ta_HT_DCPERIOD, 2), + CALLDEF(impl_ta_HT_DCPHASE_lookback, 1), CALLDEF(impl_ta_HT_DCPHASE, 2), + CALLDEF(impl_ta_HT_PHASOR_lookback, 1), CALLDEF(impl_ta_HT_PHASOR, 2), + CALLDEF(impl_ta_HT_SINE_lookback, 1), CALLDEF(impl_ta_HT_SINE, 2), + CALLDEF(impl_ta_HT_TRENDLINE_lookback, 1), CALLDEF(impl_ta_HT_TRENDLINE, 2), + CALLDEF(impl_ta_HT_TRENDMODE_lookback, 1), CALLDEF(impl_ta_HT_TRENDMODE, 2), + CALLDEF(impl_ta_IMI_lookback, 3), CALLDEF(impl_ta_IMI, 4), + CALLDEF(impl_ta_KAMA_lookback, 2), CALLDEF(impl_ta_KAMA, 3), + CALLDEF(impl_ta_MACDEXT_lookback, 7), CALLDEF(impl_ta_MACDEXT, 8), + CALLDEF(impl_ta_MACDFIX_lookback, 2), CALLDEF(impl_ta_MACDFIX, 3), + CALLDEF(impl_ta_MACD_lookback, 4), CALLDEF(impl_ta_MACD, 5), + CALLDEF(impl_ta_MAMA_lookback, 3), CALLDEF(impl_ta_MAMA, 4), + CALLDEF(impl_ta_MAX_lookback, 2), CALLDEF(impl_ta_MAX, 3), + CALLDEF(impl_ta_MEDPRICE_lookback, 2), CALLDEF(impl_ta_MEDPRICE, 3), + CALLDEF(impl_ta_MFI_lookback, 5), CALLDEF(impl_ta_MFI, 6), + CALLDEF(impl_ta_MIDPRICE_lookback, 3), CALLDEF(impl_ta_MIDPRICE, 4), + CALLDEF(impl_ta_MIN_lookback, 2), CALLDEF(impl_ta_MIN, 3), + CALLDEF(impl_ta_MINUS_DI_lookback, 4), CALLDEF(impl_ta_MINUS_DI, 5), + CALLDEF(impl_ta_MINUS_DM_lookback, 3), CALLDEF(impl_ta_MINUS_DM, 4), + CALLDEF(impl_ta_MOM_lookback, 2), CALLDEF(impl_ta_MOM, 3), + CALLDEF(impl_ta_NATR_lookback, 4), CALLDEF(impl_ta_NATR, 5), + CALLDEF(impl_ta_OBV_lookback, 2), CALLDEF(impl_ta_OBV, 3), + CALLDEF(impl_ta_PLUS_DI_lookback, 4), CALLDEF(impl_ta_PLUS_DI, 5), + CALLDEF(impl_ta_PLUS_DM_lookback, 3), CALLDEF(impl_ta_PLUS_DM, 4), + CALLDEF(impl_ta_PPO_lookback, 4), CALLDEF(impl_ta_PPO, 5), + CALLDEF(impl_ta_ROC_lookback, 2), + CALLDEF(impl_ta_ROCR_lookback, 2), CALLDEF(impl_ta_ROCR, 3), CALLDEF(impl_ta_ROC, 3), + CALLDEF(impl_ta_RSI_lookback, 2), CALLDEF(impl_ta_RSI, 3), + CALLDEF(impl_ta_SAREXT_lookback, 10), CALLDEF(impl_ta_SAREXT, 11), + CALLDEF(impl_ta_SAR_lookback, 4), CALLDEF(impl_ta_SAR, 5), + CALLDEF(impl_ta_SMA_lookback, 2), CALLDEF(impl_ta_SMA, 3), + CALLDEF(impl_ta_STDDEV_lookback, 3), CALLDEF(impl_ta_STDDEV, 4), + CALLDEF(impl_ta_STOCHF_lookback, 6), CALLDEF(impl_ta_STOCHF, 7), + CALLDEF(impl_ta_STOCH_lookback, 8), + CALLDEF(impl_ta_STOCHRSI_lookback, 5), CALLDEF(impl_ta_STOCHRSI, 6), CALLDEF(impl_ta_STOCH, 9), + CALLDEF(impl_ta_SUM_lookback, 2), CALLDEF(impl_ta_SUM, 3), + CALLDEF(impl_ta_T3_lookback, 3), CALLDEF(impl_ta_T3, 4), + CALLDEF(impl_ta_TEMA_lookback, 2), CALLDEF(impl_ta_TEMA, 3), + CALLDEF(impl_ta_TRANGE_lookback, 3), CALLDEF(impl_ta_TRANGE, 4), + CALLDEF(impl_ta_TRIMA_lookback, 2), CALLDEF(impl_ta_TRIMA, 3), + CALLDEF(impl_ta_TRIX_lookback, 2), CALLDEF(impl_ta_TRIX, 3), + CALLDEF(impl_ta_TYPPRICE_lookback, 3), CALLDEF(impl_ta_TYPPRICE, 4), + CALLDEF(impl_ta_ULTOSC_lookback, 6), CALLDEF(impl_ta_ULTOSC, 7), + CALLDEF(impl_ta_VAR_lookback, 3), CALLDEF(impl_ta_VAR, 4), + CALLDEF(impl_ta_VOLUME_lookback, 2), CALLDEF(impl_ta_VOLUME, 3), + CALLDEF(impl_ta_WCLPRICE_lookback, 3), CALLDEF(impl_ta_WCLPRICE, 4), + CALLDEF(impl_ta_WILLR_lookback, 4), CALLDEF(impl_ta_WILLR, 5), + CALLDEF(impl_ta_WMA_lookback, 2), CALLDEF(impl_ta_WMA, 3), CALLDEF(initialize_ta_lib, 0), CALLDEF(map_dfr_double, 1), diff --git a/src/ta_ACCBANDS.c b/src/ta_ACCBANDS.c index 7fc4a395c..71a71a48f 100644 --- a/src/ta_ACCBANDS.c +++ b/src/ta_ACCBANDS.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ACCBANDS_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_ACCBANDS_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ACCBANDS( SEXP inHigh, diff --git a/src/ta_AD.c b/src/ta_AD.c index 0b765e71d..62527a62d 100644 --- a/src/ta_AD.c +++ b/src/ta_AD.c @@ -24,6 +24,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_AD_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP inVolume +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + const double *inVolume_ptr = REAL(inVolume); + + // calculate lookback + const int lookback = TA_AD_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_AD( SEXP inHigh, diff --git a/src/ta_ADOSC.c b/src/ta_ADOSC.c index f1dca97c6..eaeae84df 100644 --- a/src/ta_ADOSC.c +++ b/src/ta_ADOSC.c @@ -26,6 +26,45 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ADOSC_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP inVolume, + SEXP optInFastPeriod, + SEXP optInSlowPeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + const double *inVolume_ptr = REAL(inVolume); + + // extract input values + const int optInFastPeriod_value = INTEGER(optInFastPeriod)[0]; + const int optInSlowPeriod_value = INTEGER(optInSlowPeriod)[0]; + + // calculate lookback + const int lookback = + TA_ADOSC_Lookback(optInFastPeriod_value, optInSlowPeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ADOSC( SEXP inHigh, diff --git a/src/ta_ADX.c b/src/ta_ADX.c index 1a066ab49..7331352c1 100644 --- a/src/ta_ADX.c +++ b/src/ta_ADX.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ADX_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_ADX_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ADX( SEXP inHigh, diff --git a/src/ta_ADXR.c b/src/ta_ADXR.c index 90dda8633..411617765 100644 --- a/src/ta_ADXR.c +++ b/src/ta_ADXR.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ADXR_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_ADXR_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ADXR( SEXP inHigh, diff --git a/src/ta_APO.c b/src/ta_APO.c index f71189e3c..f3892627d 100644 --- a/src/ta_APO.c +++ b/src/ta_APO.c @@ -24,6 +24,43 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_APO_lookback( + SEXP inReal, + SEXP optInFastPeriod, + SEXP optInSlowPeriod, + SEXP optInMAType +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInFastPeriod_value = INTEGER(optInFastPeriod)[0]; + const int optInSlowPeriod_value = INTEGER(optInSlowPeriod)[0]; + const TA_MAType optInMAType_value = as_MAType(optInMAType); + + // calculate lookback + const int lookback = TA_APO_Lookback( + optInFastPeriod_value, + optInSlowPeriod_value, + optInMAType_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_APO( SEXP inReal, diff --git a/src/ta_AROON.c b/src/ta_AROON.c index 948c9b941..5bf6a448b 100644 --- a/src/ta_AROON.c +++ b/src/ta_AROON.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_AROON_lookback( + SEXP inHigh, + SEXP inLow, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_AROON_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_AROON( SEXP inHigh, diff --git a/src/ta_AROONOSC.c b/src/ta_AROONOSC.c index a0247912a..c55d3ce43 100644 --- a/src/ta_AROONOSC.c +++ b/src/ta_AROONOSC.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_AROONOSC_lookback( + SEXP inHigh, + SEXP inLow, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_AROONOSC_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_AROONOSC( SEXP inHigh, diff --git a/src/ta_ATR.c b/src/ta_ATR.c index e9c41d9e6..35a0bdea7 100644 --- a/src/ta_ATR.c +++ b/src/ta_ATR.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ATR_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_ATR_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ATR( SEXP inHigh, diff --git a/src/ta_AVGPRICE.c b/src/ta_AVGPRICE.c index 1ea08e875..c74b13db8 100644 --- a/src/ta_AVGPRICE.c +++ b/src/ta_AVGPRICE.c @@ -24,6 +24,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_AVGPRICE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // values + // get length of 'inOpen' (assumes equal length across input) + int n = LENGTH(inOpen); + + // pointers to input arrays + const double *inOpen_ptr = REAL(inOpen); + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // calculate lookback + const int lookback = TA_AVGPRICE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_AVGPRICE( SEXP inOpen, diff --git a/src/ta_BBANDS.c b/src/ta_BBANDS.c index 81f68e0df..e967720ce 100644 --- a/src/ta_BBANDS.c +++ b/src/ta_BBANDS.c @@ -25,6 +25,46 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_BBANDS_lookback( + SEXP inReal, + SEXP optInTimePeriod, + SEXP optInNbDevUp, + SEXP optInNbDevDn, + SEXP optInMAType +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + const double optInNbDevUp_value = REAL(optInNbDevUp)[0]; + const double optInNbDevDn_value = REAL(optInNbDevDn)[0]; + const TA_MAType optInMAType_value = as_MAType(optInMAType); + + // calculate lookback + const int lookback = TA_BBANDS_Lookback( + optInTimePeriod_value, + optInNbDevUp_value, + optInNbDevDn_value, + optInMAType_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_BBANDS( SEXP inReal, diff --git a/src/ta_BETA.c b/src/ta_BETA.c index d1d0476f4..bc804e026 100644 --- a/src/ta_BETA.c +++ b/src/ta_BETA.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_BETA_lookback( + SEXP inReal0, + SEXP inReal1, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal0' (assumes equal length across input) + int n = LENGTH(inReal0); + + // pointers to input arrays + const double *inReal0_ptr = REAL(inReal0); + const double *inReal1_ptr = REAL(inReal1); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_BETA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_BETA( SEXP inReal0, diff --git a/src/ta_BOP.c b/src/ta_BOP.c index 430c1d552..5be28e9a8 100644 --- a/src/ta_BOP.c +++ b/src/ta_BOP.c @@ -24,6 +24,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_BOP_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // values + // get length of 'inOpen' (assumes equal length across input) + int n = LENGTH(inOpen); + + // pointers to input arrays + const double *inOpen_ptr = REAL(inOpen); + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // calculate lookback + const int lookback = TA_BOP_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_BOP( SEXP inOpen, diff --git a/src/ta_CCI.c b/src/ta_CCI.c index 467dfd77a..1d534321f 100644 --- a/src/ta_CCI.c +++ b/src/ta_CCI.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CCI_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_CCI_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_CCI( SEXP inHigh, diff --git a/src/ta_CDL2CROWS.c b/src/ta_CDL2CROWS.c index 0ba19c781..004fbdaa7 100644 --- a/src/ta_CDL2CROWS.c +++ b/src/ta_CDL2CROWS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDL2CROWS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDL2CROWS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDL2CROWS( SEXP inOpen, diff --git a/src/ta_CDL3BLACKCROWS.c b/src/ta_CDL3BLACKCROWS.c index 2119b9524..233206f78 100644 --- a/src/ta_CDL3BLACKCROWS.c +++ b/src/ta_CDL3BLACKCROWS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDL3BLACKCROWS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDL3BLACKCROWS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDL3BLACKCROWS( SEXP inOpen, diff --git a/src/ta_CDL3INSIDE.c b/src/ta_CDL3INSIDE.c index 23220d6a6..cde4c4e2c 100644 --- a/src/ta_CDL3INSIDE.c +++ b/src/ta_CDL3INSIDE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDL3INSIDE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDL3INSIDE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDL3INSIDE( SEXP inOpen, diff --git a/src/ta_CDL3LINESTRIKE.c b/src/ta_CDL3LINESTRIKE.c index a0ee4b6ec..6bbd86e42 100644 --- a/src/ta_CDL3LINESTRIKE.c +++ b/src/ta_CDL3LINESTRIKE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDL3LINESTRIKE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDL3LINESTRIKE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDL3LINESTRIKE( SEXP inOpen, diff --git a/src/ta_CDL3OUTSIDE.c b/src/ta_CDL3OUTSIDE.c index 5cf16e81a..d090b8e81 100644 --- a/src/ta_CDL3OUTSIDE.c +++ b/src/ta_CDL3OUTSIDE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDL3OUTSIDE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDL3OUTSIDE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDL3OUTSIDE( SEXP inOpen, diff --git a/src/ta_CDL3STARSINSOUTH.c b/src/ta_CDL3STARSINSOUTH.c index 93083dc43..2b16cb16b 100644 --- a/src/ta_CDL3STARSINSOUTH.c +++ b/src/ta_CDL3STARSINSOUTH.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDL3STARSINSOUTH_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDL3STARSINSOUTH_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDL3STARSINSOUTH( SEXP inOpen, diff --git a/src/ta_CDL3WHITESOLDIERS.c b/src/ta_CDL3WHITESOLDIERS.c index d0cfd8ef3..adfe188b2 100644 --- a/src/ta_CDL3WHITESOLDIERS.c +++ b/src/ta_CDL3WHITESOLDIERS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDL3WHITESOLDIERS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDL3WHITESOLDIERS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDL3WHITESOLDIERS( SEXP inOpen, diff --git a/src/ta_CDLABANDONEDBABY.c b/src/ta_CDLABANDONEDBABY.c index af02a6a29..b6198a461 100644 --- a/src/ta_CDLABANDONEDBABY.c +++ b/src/ta_CDLABANDONEDBABY.c @@ -25,6 +25,38 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLABANDONEDBABY_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInPenetration +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + const double penetration = REAL(optInPenetration)[0]; + + // calculate lookback + const int lookback = TA_CDLABANDONEDBABY_Lookback(penetration); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLABANDONEDBABY( SEXP inOpen, diff --git a/src/ta_CDLADVANCEBLOCK.c b/src/ta_CDLADVANCEBLOCK.c index 2ddb9f16b..ee38fc0b0 100644 --- a/src/ta_CDLADVANCEBLOCK.c +++ b/src/ta_CDLADVANCEBLOCK.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLADVANCEBLOCK_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLADVANCEBLOCK_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLADVANCEBLOCK( SEXP inOpen, diff --git a/src/ta_CDLBELTHOLD.c b/src/ta_CDLBELTHOLD.c index 86e808c23..783e9c80b 100644 --- a/src/ta_CDLBELTHOLD.c +++ b/src/ta_CDLBELTHOLD.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLBELTHOLD_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLBELTHOLD_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLBELTHOLD( SEXP inOpen, diff --git a/src/ta_CDLBREAKAWAY.c b/src/ta_CDLBREAKAWAY.c index 122ca67d5..f777a39c3 100644 --- a/src/ta_CDLBREAKAWAY.c +++ b/src/ta_CDLBREAKAWAY.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLBREAKAWAY_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLBREAKAWAY_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLBREAKAWAY( SEXP inOpen, diff --git a/src/ta_CDLCLOSINGMARUBOZU.c b/src/ta_CDLCLOSINGMARUBOZU.c index 35b7f2e88..ab2bf4027 100644 --- a/src/ta_CDLCLOSINGMARUBOZU.c +++ b/src/ta_CDLCLOSINGMARUBOZU.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLCLOSINGMARUBOZU_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLCLOSINGMARUBOZU_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLCLOSINGMARUBOZU( SEXP inOpen, diff --git a/src/ta_CDLCONCEALBABYSWALL.c b/src/ta_CDLCONCEALBABYSWALL.c index 31c1e9d9d..d194d45dc 100644 --- a/src/ta_CDLCONCEALBABYSWALL.c +++ b/src/ta_CDLCONCEALBABYSWALL.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLCONCEALBABYSWALL_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLCONCEALBABYSWALL_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLCONCEALBABYSWALL( SEXP inOpen, diff --git a/src/ta_CDLCOUNTERATTACK.c b/src/ta_CDLCOUNTERATTACK.c index ecc8e9f72..3856d5945 100644 --- a/src/ta_CDLCOUNTERATTACK.c +++ b/src/ta_CDLCOUNTERATTACK.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLCOUNTERATTACK_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLCOUNTERATTACK_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLCOUNTERATTACK( SEXP inOpen, diff --git a/src/ta_CDLDARKCLOUDCOVER.c b/src/ta_CDLDARKCLOUDCOVER.c index 9abf0809f..27b11bc26 100644 --- a/src/ta_CDLDARKCLOUDCOVER.c +++ b/src/ta_CDLDARKCLOUDCOVER.c @@ -25,6 +25,38 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLDARKCLOUDCOVER_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInPenetration +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + const double penetration = REAL(optInPenetration)[0]; + + // calculate lookback + const int lookback = TA_CDLDARKCLOUDCOVER_Lookback(penetration); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLDARKCLOUDCOVER( SEXP inOpen, diff --git a/src/ta_CDLDOJI.c b/src/ta_CDLDOJI.c index e9faf5f87..9785ae209 100644 --- a/src/ta_CDLDOJI.c +++ b/src/ta_CDLDOJI.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLDOJI_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLDOJI_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLDOJI( SEXP inOpen, diff --git a/src/ta_CDLDOJISTAR.c b/src/ta_CDLDOJISTAR.c index 9241eeaad..e9f06bfc2 100644 --- a/src/ta_CDLDOJISTAR.c +++ b/src/ta_CDLDOJISTAR.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLDOJISTAR_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLDOJISTAR_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLDOJISTAR( SEXP inOpen, diff --git a/src/ta_CDLDRAGONFLYDOJI.c b/src/ta_CDLDRAGONFLYDOJI.c index 03be99e17..27b3b5749 100644 --- a/src/ta_CDLDRAGONFLYDOJI.c +++ b/src/ta_CDLDRAGONFLYDOJI.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLDRAGONFLYDOJI_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLDRAGONFLYDOJI_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLDRAGONFLYDOJI( SEXP inOpen, diff --git a/src/ta_CDLENGULFING.c b/src/ta_CDLENGULFING.c index 8dbb06d85..c399e015f 100644 --- a/src/ta_CDLENGULFING.c +++ b/src/ta_CDLENGULFING.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLENGULFING_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLENGULFING_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLENGULFING( SEXP inOpen, diff --git a/src/ta_CDLEVENINGDOJISTAR.c b/src/ta_CDLEVENINGDOJISTAR.c index ba51e0f05..ef7aab8cc 100644 --- a/src/ta_CDLEVENINGDOJISTAR.c +++ b/src/ta_CDLEVENINGDOJISTAR.c @@ -25,6 +25,38 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLEVENINGDOJISTAR_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInPenetration +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + const double penetration = REAL(optInPenetration)[0]; + + // calculate lookback + const int lookback = TA_CDLEVENINGDOJISTAR_Lookback(penetration); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLEVENINGDOJISTAR( SEXP inOpen, diff --git a/src/ta_CDLEVENINGSTAR.c b/src/ta_CDLEVENINGSTAR.c index 1b82c5724..67852193a 100644 --- a/src/ta_CDLEVENINGSTAR.c +++ b/src/ta_CDLEVENINGSTAR.c @@ -25,6 +25,38 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLEVENINGSTAR_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInPenetration +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + const double penetration = REAL(optInPenetration)[0]; + + // calculate lookback + const int lookback = TA_CDLEVENINGSTAR_Lookback(penetration); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLEVENINGSTAR( SEXP inOpen, diff --git a/src/ta_CDLGAPSIDESIDEWHITE.c b/src/ta_CDLGAPSIDESIDEWHITE.c index eaceff14a..1a13ee90b 100644 --- a/src/ta_CDLGAPSIDESIDEWHITE.c +++ b/src/ta_CDLGAPSIDESIDEWHITE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLGAPSIDESIDEWHITE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLGAPSIDESIDEWHITE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLGAPSIDESIDEWHITE( SEXP inOpen, diff --git a/src/ta_CDLGRAVESTONEDOJI.c b/src/ta_CDLGRAVESTONEDOJI.c index fb73cf388..952100fc5 100644 --- a/src/ta_CDLGRAVESTONEDOJI.c +++ b/src/ta_CDLGRAVESTONEDOJI.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLGRAVESTONEDOJI_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLGRAVESTONEDOJI_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLGRAVESTONEDOJI( SEXP inOpen, diff --git a/src/ta_CDLHAMMER.c b/src/ta_CDLHAMMER.c index 6f8ceba46..e361a610a 100644 --- a/src/ta_CDLHAMMER.c +++ b/src/ta_CDLHAMMER.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHAMMER_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHAMMER_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHAMMER( SEXP inOpen, diff --git a/src/ta_CDLHANGINGMAN.c b/src/ta_CDLHANGINGMAN.c index 87eea059c..4e13daf3b 100644 --- a/src/ta_CDLHANGINGMAN.c +++ b/src/ta_CDLHANGINGMAN.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHANGINGMAN_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHANGINGMAN_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHANGINGMAN( SEXP inOpen, diff --git a/src/ta_CDLHARAMI.c b/src/ta_CDLHARAMI.c index 60ed602c2..06511cf04 100644 --- a/src/ta_CDLHARAMI.c +++ b/src/ta_CDLHARAMI.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHARAMI_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHARAMI_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHARAMI( SEXP inOpen, diff --git a/src/ta_CDLHARAMICROSS.c b/src/ta_CDLHARAMICROSS.c index e392cfbed..52bd8ae16 100644 --- a/src/ta_CDLHARAMICROSS.c +++ b/src/ta_CDLHARAMICROSS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHARAMICROSS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHARAMICROSS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHARAMICROSS( SEXP inOpen, diff --git a/src/ta_CDLHIGHWAVE.c b/src/ta_CDLHIGHWAVE.c index 9d1b0de94..8673192bd 100644 --- a/src/ta_CDLHIGHWAVE.c +++ b/src/ta_CDLHIGHWAVE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHIGHWAVE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHIGHWAVE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHIGHWAVE( SEXP inOpen, diff --git a/src/ta_CDLHIKKAKE.c b/src/ta_CDLHIKKAKE.c index 5f70a053a..22730af0b 100644 --- a/src/ta_CDLHIKKAKE.c +++ b/src/ta_CDLHIKKAKE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHIKKAKE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHIKKAKE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHIKKAKE( SEXP inOpen, diff --git a/src/ta_CDLHIKKAKEMOD.c b/src/ta_CDLHIKKAKEMOD.c index d1a721947..611ff6b28 100644 --- a/src/ta_CDLHIKKAKEMOD.c +++ b/src/ta_CDLHIKKAKEMOD.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHIKKAKEMOD_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHIKKAKEMOD_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHIKKAKEMOD( SEXP inOpen, diff --git a/src/ta_CDLHOMINGPIGEON.c b/src/ta_CDLHOMINGPIGEON.c index b26f446de..f6476ae7b 100644 --- a/src/ta_CDLHOMINGPIGEON.c +++ b/src/ta_CDLHOMINGPIGEON.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLHOMINGPIGEON_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLHOMINGPIGEON_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLHOMINGPIGEON( SEXP inOpen, diff --git a/src/ta_CDLIDENTICAL3CROWS.c b/src/ta_CDLIDENTICAL3CROWS.c index 97aa530de..aa1f5a7ea 100644 --- a/src/ta_CDLIDENTICAL3CROWS.c +++ b/src/ta_CDLIDENTICAL3CROWS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLIDENTICAL3CROWS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLIDENTICAL3CROWS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLIDENTICAL3CROWS( SEXP inOpen, diff --git a/src/ta_CDLINNECK.c b/src/ta_CDLINNECK.c index e248af245..ae61db637 100644 --- a/src/ta_CDLINNECK.c +++ b/src/ta_CDLINNECK.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLINNECK_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLINNECK_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLINNECK( SEXP inOpen, diff --git a/src/ta_CDLINVERTEDHAMMER.c b/src/ta_CDLINVERTEDHAMMER.c index 66df11952..a640bf24f 100644 --- a/src/ta_CDLINVERTEDHAMMER.c +++ b/src/ta_CDLINVERTEDHAMMER.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLINVERTEDHAMMER_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLINVERTEDHAMMER_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLINVERTEDHAMMER( SEXP inOpen, diff --git a/src/ta_CDLKICKING.c b/src/ta_CDLKICKING.c index 4bbad2514..82be38042 100644 --- a/src/ta_CDLKICKING.c +++ b/src/ta_CDLKICKING.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLKICKING_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLKICKING_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLKICKING( SEXP inOpen, diff --git a/src/ta_CDLKICKINGBYLENGTH.c b/src/ta_CDLKICKINGBYLENGTH.c index f5f6faf88..7bb5aebb0 100644 --- a/src/ta_CDLKICKINGBYLENGTH.c +++ b/src/ta_CDLKICKINGBYLENGTH.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLKICKINGBYLENGTH_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLKICKINGBYLENGTH_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLKICKINGBYLENGTH( SEXP inOpen, diff --git a/src/ta_CDLLADDERBOTTOM.c b/src/ta_CDLLADDERBOTTOM.c index 81b29ae46..458967b42 100644 --- a/src/ta_CDLLADDERBOTTOM.c +++ b/src/ta_CDLLADDERBOTTOM.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLLADDERBOTTOM_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLLADDERBOTTOM_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLLADDERBOTTOM( SEXP inOpen, diff --git a/src/ta_CDLLONGLEGGEDDOJI.c b/src/ta_CDLLONGLEGGEDDOJI.c index c1920a94e..d5c764bd5 100644 --- a/src/ta_CDLLONGLEGGEDDOJI.c +++ b/src/ta_CDLLONGLEGGEDDOJI.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLLONGLEGGEDDOJI_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLLONGLEGGEDDOJI_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLLONGLEGGEDDOJI( SEXP inOpen, diff --git a/src/ta_CDLLONGLINE.c b/src/ta_CDLLONGLINE.c index 577a53aad..d80d705ce 100644 --- a/src/ta_CDLLONGLINE.c +++ b/src/ta_CDLLONGLINE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLLONGLINE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLLONGLINE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLLONGLINE( SEXP inOpen, diff --git a/src/ta_CDLMARUBOZU.c b/src/ta_CDLMARUBOZU.c index 846bbf2dd..683e7765b 100644 --- a/src/ta_CDLMARUBOZU.c +++ b/src/ta_CDLMARUBOZU.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLMARUBOZU_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLMARUBOZU_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLMARUBOZU( SEXP inOpen, diff --git a/src/ta_CDLMATCHINGLOW.c b/src/ta_CDLMATCHINGLOW.c index 12cb8ff39..e9463130a 100644 --- a/src/ta_CDLMATCHINGLOW.c +++ b/src/ta_CDLMATCHINGLOW.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLMATCHINGLOW_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLMATCHINGLOW_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLMATCHINGLOW( SEXP inOpen, diff --git a/src/ta_CDLMATHOLD.c b/src/ta_CDLMATHOLD.c index 7332f3f2c..688600798 100644 --- a/src/ta_CDLMATHOLD.c +++ b/src/ta_CDLMATHOLD.c @@ -25,6 +25,38 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLMATHOLD_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInPenetration +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + const double penetration = REAL(optInPenetration)[0]; + + // calculate lookback + const int lookback = TA_CDLMATHOLD_Lookback(penetration); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLMATHOLD( SEXP inOpen, diff --git a/src/ta_CDLMORNINGDOJISTAR.c b/src/ta_CDLMORNINGDOJISTAR.c index dc6217651..0083024fe 100644 --- a/src/ta_CDLMORNINGDOJISTAR.c +++ b/src/ta_CDLMORNINGDOJISTAR.c @@ -25,6 +25,38 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLMORNINGDOJISTAR_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInPenetration +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + const double penetration = REAL(optInPenetration)[0]; + + // calculate lookback + const int lookback = TA_CDLMORNINGDOJISTAR_Lookback(penetration); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLMORNINGDOJISTAR( SEXP inOpen, diff --git a/src/ta_CDLMORNINGSTAR.c b/src/ta_CDLMORNINGSTAR.c index e08d38953..c0d2c97aa 100644 --- a/src/ta_CDLMORNINGSTAR.c +++ b/src/ta_CDLMORNINGSTAR.c @@ -25,6 +25,38 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLMORNINGSTAR_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInPenetration +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + const double penetration = REAL(optInPenetration)[0]; + + // calculate lookback + const int lookback = TA_CDLMORNINGSTAR_Lookback(penetration); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLMORNINGSTAR( SEXP inOpen, diff --git a/src/ta_CDLONNECK.c b/src/ta_CDLONNECK.c index 3788cd921..3b3a7cdbd 100644 --- a/src/ta_CDLONNECK.c +++ b/src/ta_CDLONNECK.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLONNECK_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLONNECK_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLONNECK( SEXP inOpen, diff --git a/src/ta_CDLPIERCING.c b/src/ta_CDLPIERCING.c index 8a8c150fa..adf6bdaff 100644 --- a/src/ta_CDLPIERCING.c +++ b/src/ta_CDLPIERCING.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLPIERCING_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLPIERCING_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLPIERCING( SEXP inOpen, diff --git a/src/ta_CDLRICKSHAWMAN.c b/src/ta_CDLRICKSHAWMAN.c index de0c14010..7ddf2c6cd 100644 --- a/src/ta_CDLRICKSHAWMAN.c +++ b/src/ta_CDLRICKSHAWMAN.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLRICKSHAWMAN_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLRICKSHAWMAN_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLRICKSHAWMAN( SEXP inOpen, diff --git a/src/ta_CDLRISEFALL3METHODS.c b/src/ta_CDLRISEFALL3METHODS.c index 7fdce1d58..0c55c09f7 100644 --- a/src/ta_CDLRISEFALL3METHODS.c +++ b/src/ta_CDLRISEFALL3METHODS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLRISEFALL3METHODS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLRISEFALL3METHODS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLRISEFALL3METHODS( SEXP inOpen, diff --git a/src/ta_CDLSEPARATINGLINES.c b/src/ta_CDLSEPARATINGLINES.c index 57d3820b6..16bcc2945 100644 --- a/src/ta_CDLSEPARATINGLINES.c +++ b/src/ta_CDLSEPARATINGLINES.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLSEPARATINGLINES_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLSEPARATINGLINES_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLSEPARATINGLINES( SEXP inOpen, diff --git a/src/ta_CDLSHOOTINGSTAR.c b/src/ta_CDLSHOOTINGSTAR.c index 9affb530f..72b28e34a 100644 --- a/src/ta_CDLSHOOTINGSTAR.c +++ b/src/ta_CDLSHOOTINGSTAR.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLSHOOTINGSTAR_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLSHOOTINGSTAR_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLSHOOTINGSTAR( SEXP inOpen, diff --git a/src/ta_CDLSHORTLINE.c b/src/ta_CDLSHORTLINE.c index a3e6f8259..f9578a08f 100644 --- a/src/ta_CDLSHORTLINE.c +++ b/src/ta_CDLSHORTLINE.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLSHORTLINE_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLSHORTLINE_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLSHORTLINE( SEXP inOpen, diff --git a/src/ta_CDLSPINNINGTOP.c b/src/ta_CDLSPINNINGTOP.c index 174122fee..c22c8c07a 100644 --- a/src/ta_CDLSPINNINGTOP.c +++ b/src/ta_CDLSPINNINGTOP.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLSPINNINGTOP_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLSPINNINGTOP_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLSPINNINGTOP( SEXP inOpen, diff --git a/src/ta_CDLSTALLEDPATTERN.c b/src/ta_CDLSTALLEDPATTERN.c index 1f1932dfe..8172c2cb5 100644 --- a/src/ta_CDLSTALLEDPATTERN.c +++ b/src/ta_CDLSTALLEDPATTERN.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLSTALLEDPATTERN_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLSTALLEDPATTERN_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLSTALLEDPATTERN( SEXP inOpen, diff --git a/src/ta_CDLSTICKSANDWICH.c b/src/ta_CDLSTICKSANDWICH.c index bfbf8faf3..3f31a9b3c 100644 --- a/src/ta_CDLSTICKSANDWICH.c +++ b/src/ta_CDLSTICKSANDWICH.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLSTICKSANDWICH_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLSTICKSANDWICH_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLSTICKSANDWICH( SEXP inOpen, diff --git a/src/ta_CDLTAKURI.c b/src/ta_CDLTAKURI.c index bbc4b4063..b537a3845 100644 --- a/src/ta_CDLTAKURI.c +++ b/src/ta_CDLTAKURI.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLTAKURI_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLTAKURI_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLTAKURI( SEXP inOpen, diff --git a/src/ta_CDLTASUKIGAP.c b/src/ta_CDLTASUKIGAP.c index b4f3a7f0b..dc3ec6a3b 100644 --- a/src/ta_CDLTASUKIGAP.c +++ b/src/ta_CDLTASUKIGAP.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLTASUKIGAP_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLTASUKIGAP_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLTASUKIGAP( SEXP inOpen, diff --git a/src/ta_CDLTHRUSTING.c b/src/ta_CDLTHRUSTING.c index 1518ce8e9..c01151b7a 100644 --- a/src/ta_CDLTHRUSTING.c +++ b/src/ta_CDLTHRUSTING.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLTHRUSTING_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLTHRUSTING_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLTHRUSTING( SEXP inOpen, diff --git a/src/ta_CDLTRISTAR.c b/src/ta_CDLTRISTAR.c index 974f9b78a..1c0d841f5 100644 --- a/src/ta_CDLTRISTAR.c +++ b/src/ta_CDLTRISTAR.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLTRISTAR_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLTRISTAR_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLTRISTAR( SEXP inOpen, diff --git a/src/ta_CDLUNIQUE3RIVER.c b/src/ta_CDLUNIQUE3RIVER.c index d48f92206..d77b621d9 100644 --- a/src/ta_CDLUNIQUE3RIVER.c +++ b/src/ta_CDLUNIQUE3RIVER.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLUNIQUE3RIVER_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLUNIQUE3RIVER_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLUNIQUE3RIVER( SEXP inOpen, diff --git a/src/ta_CDLUPSIDEGAP2CROWS.c b/src/ta_CDLUPSIDEGAP2CROWS.c index 1fa4e148c..bf86240aa 100644 --- a/src/ta_CDLUPSIDEGAP2CROWS.c +++ b/src/ta_CDLUPSIDEGAP2CROWS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLUPSIDEGAP2CROWS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLUPSIDEGAP2CROWS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLUPSIDEGAP2CROWS( SEXP inOpen, diff --git a/src/ta_CDLXSIDEGAP3METHODS.c b/src/ta_CDLXSIDEGAP3METHODS.c index 0b988b8f6..8b045aa5e 100644 --- a/src/ta_CDLXSIDEGAP3METHODS.c +++ b/src/ta_CDLXSIDEGAP3METHODS.c @@ -24,6 +24,35 @@ #include "shift.h" #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CDLXSIDEGAP3METHODS_lookback( + SEXP inOpen, + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // pointers to input + const double *open_ptr = REAL(inOpen); + const double *high_ptr = REAL(inHigh); + const double *low_ptr = REAL(inLow); + const double *close_ptr = REAL(inClose); + int n = LENGTH(inOpen); + + // calculate lookback + const int lookback = TA_CDLXSIDEGAP3METHODS_Lookback(); + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + + return output; +} + // clang-format off SEXP impl_ta_CDLXSIDEGAP3METHODS( SEXP inOpen, diff --git a/src/ta_CMO.c b/src/ta_CMO.c index c1dc4969d..edcf9a95c 100644 --- a/src/ta_CMO.c +++ b/src/ta_CMO.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CMO_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_CMO_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_CMO( SEXP inReal, diff --git a/src/ta_CORREL.c b/src/ta_CORREL.c index 08476beeb..06a33d427 100644 --- a/src/ta_CORREL.c +++ b/src/ta_CORREL.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_CORREL_lookback( + SEXP inReal0, + SEXP inReal1, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal0' (assumes equal length across input) + int n = LENGTH(inReal0); + + // pointers to input arrays + const double *inReal0_ptr = REAL(inReal0); + const double *inReal1_ptr = REAL(inReal1); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_CORREL_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_CORREL( SEXP inReal0, diff --git a/src/ta_DEMA.c b/src/ta_DEMA.c index b56cd536f..5a9fc1124 100644 --- a/src/ta_DEMA.c +++ b/src/ta_DEMA.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_DEMA_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_DEMA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_DEMA( SEXP inReal, diff --git a/src/ta_DX.c b/src/ta_DX.c index a031498b1..5c9b12f41 100644 --- a/src/ta_DX.c +++ b/src/ta_DX.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_DX_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_DX_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_DX( SEXP inHigh, diff --git a/src/ta_EMA.c b/src/ta_EMA.c index 02067a543..321f100dc 100644 --- a/src/ta_EMA.c +++ b/src/ta_EMA.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_EMA_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_EMA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_EMA( SEXP inReal, diff --git a/src/ta_HT_DCPERIOD.c b/src/ta_HT_DCPERIOD.c index 3d72afc46..770af8024 100644 --- a/src/ta_HT_DCPERIOD.c +++ b/src/ta_HT_DCPERIOD.c @@ -21,6 +21,32 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_HT_DCPERIOD_lookback( + SEXP inReal +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // calculate lookback + const int lookback = TA_HT_DCPERIOD_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_HT_DCPERIOD( SEXP inReal, diff --git a/src/ta_HT_DCPHASE.c b/src/ta_HT_DCPHASE.c index a05c7abd0..23461b58d 100644 --- a/src/ta_HT_DCPHASE.c +++ b/src/ta_HT_DCPHASE.c @@ -21,6 +21,32 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_HT_DCPHASE_lookback( + SEXP inReal +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // calculate lookback + const int lookback = TA_HT_DCPHASE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_HT_DCPHASE( SEXP inReal, diff --git a/src/ta_HT_PHASOR.c b/src/ta_HT_PHASOR.c index 2d73a4854..870af5864 100644 --- a/src/ta_HT_PHASOR.c +++ b/src/ta_HT_PHASOR.c @@ -21,6 +21,32 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_HT_PHASOR_lookback( + SEXP inReal +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // calculate lookback + const int lookback = TA_HT_PHASOR_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_HT_PHASOR( SEXP inReal, diff --git a/src/ta_HT_SINE.c b/src/ta_HT_SINE.c index fe50ba65c..2adcfa2b6 100644 --- a/src/ta_HT_SINE.c +++ b/src/ta_HT_SINE.c @@ -21,6 +21,32 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_HT_SINE_lookback( + SEXP inReal +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // calculate lookback + const int lookback = TA_HT_SINE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_HT_SINE( SEXP inReal, diff --git a/src/ta_HT_TRENDLINE.c b/src/ta_HT_TRENDLINE.c index 3a05c0f38..5a501f5ea 100644 --- a/src/ta_HT_TRENDLINE.c +++ b/src/ta_HT_TRENDLINE.c @@ -21,6 +21,32 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_HT_TRENDLINE_lookback( + SEXP inReal +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // calculate lookback + const int lookback = TA_HT_TRENDLINE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_HT_TRENDLINE( SEXP inReal, diff --git a/src/ta_HT_TRENDMODE.c b/src/ta_HT_TRENDMODE.c index 62eaa65cf..e5d025269 100644 --- a/src/ta_HT_TRENDMODE.c +++ b/src/ta_HT_TRENDMODE.c @@ -21,6 +21,32 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_HT_TRENDMODE_lookback( + SEXP inReal +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // calculate lookback + const int lookback = TA_HT_TRENDMODE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_HT_TRENDMODE( SEXP inReal, diff --git a/src/ta_IMI.c b/src/ta_IMI.c index 10eff2938..457b81d7d 100644 --- a/src/ta_IMI.c +++ b/src/ta_IMI.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_IMI_lookback( + SEXP inOpen, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inOpen' (assumes equal length across input) + int n = LENGTH(inOpen); + + // pointers to input arrays + const double *inOpen_ptr = REAL(inOpen); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_IMI_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_IMI( SEXP inOpen, diff --git a/src/ta_KAMA.c b/src/ta_KAMA.c index bc7ce4716..b2d001d30 100644 --- a/src/ta_KAMA.c +++ b/src/ta_KAMA.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_KAMA_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_KAMA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_KAMA( SEXP inReal, diff --git a/src/ta_MACD.c b/src/ta_MACD.c index df86ecc44..2bcdb717e 100644 --- a/src/ta_MACD.c +++ b/src/ta_MACD.c @@ -24,6 +24,43 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MACD_lookback( + SEXP inReal, + SEXP optInFastPeriod, + SEXP optInSlowPeriod, + SEXP optInSignalPeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInFastPeriod_value = INTEGER(optInFastPeriod)[0]; + const int optInSlowPeriod_value = INTEGER(optInSlowPeriod)[0]; + const int optInSignalPeriod_value = INTEGER(optInSignalPeriod)[0]; + + // calculate lookback + const int lookback = TA_MACD_Lookback( + optInFastPeriod_value, + optInSlowPeriod_value, + optInSignalPeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MACD( SEXP inReal, diff --git a/src/ta_MACDEXT.c b/src/ta_MACDEXT.c index 275176b6f..2c797183d 100644 --- a/src/ta_MACDEXT.c +++ b/src/ta_MACDEXT.c @@ -27,6 +27,52 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MACDEXT_lookback( + SEXP inReal, + SEXP optInFastPeriod, + SEXP optInFastMAType, + SEXP optInSlowPeriod, + SEXP optInSlowMAType, + SEXP optInSignalPeriod, + SEXP optInSignalMAType +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInFastPeriod_value = INTEGER(optInFastPeriod)[0]; + const TA_MAType optInFastMAType_value = as_MAType(optInFastMAType); + const int optInSlowPeriod_value = INTEGER(optInSlowPeriod)[0]; + const TA_MAType optInSlowMAType_value = as_MAType(optInSlowMAType); + const int optInSignalPeriod_value = INTEGER(optInSignalPeriod)[0]; + const TA_MAType optInSignalMAType_value = as_MAType(optInSignalMAType); + + // calculate lookback + const int lookback = TA_MACDEXT_Lookback( + optInFastPeriod_value, + optInFastMAType_value, + optInSlowPeriod_value, + optInSlowMAType_value, + optInSignalPeriod_value, + optInSignalMAType_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MACDEXT( SEXP inReal, diff --git a/src/ta_MACDFIX.c b/src/ta_MACDFIX.c index f34ce64b0..0bdfc0307 100644 --- a/src/ta_MACDFIX.c +++ b/src/ta_MACDFIX.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MACDFIX_lookback( + SEXP inReal, + SEXP optInSignalPeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInSignalPeriod_value = INTEGER(optInSignalPeriod)[0]; + + // calculate lookback + const int lookback = TA_MACDFIX_Lookback(optInSignalPeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MACDFIX( SEXP inReal, diff --git a/src/ta_MAMA.c b/src/ta_MAMA.c index e8011f613..42dc17b69 100644 --- a/src/ta_MAMA.c +++ b/src/ta_MAMA.c @@ -23,6 +23,39 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MAMA_lookback( + SEXP inReal, + SEXP optInFastLimit, + SEXP optInSlowLimit +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const double optInFastLimit_value = REAL(optInFastLimit)[0]; + const double optInSlowLimit_value = REAL(optInSlowLimit)[0]; + + // calculate lookback + const int lookback = + TA_MAMA_Lookback(optInFastLimit_value, optInSlowLimit_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MAMA( SEXP inReal, diff --git a/src/ta_MAX.c b/src/ta_MAX.c index 6ab70ef6d..a255679d4 100644 --- a/src/ta_MAX.c +++ b/src/ta_MAX.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MAX_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_MAX_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MAX( SEXP inReal, diff --git a/src/ta_MEDPRICE.c b/src/ta_MEDPRICE.c index 26f61945a..e20306160 100644 --- a/src/ta_MEDPRICE.c +++ b/src/ta_MEDPRICE.c @@ -22,6 +22,34 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MEDPRICE_lookback( + SEXP inHigh, + SEXP inLow +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // calculate lookback + const int lookback = TA_MEDPRICE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MEDPRICE( SEXP inHigh, diff --git a/src/ta_MFI.c b/src/ta_MFI.c index f5e102418..3f8e20c04 100644 --- a/src/ta_MFI.c +++ b/src/ta_MFI.c @@ -25,6 +25,42 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MFI_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP inVolume, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + const double *inVolume_ptr = REAL(inVolume); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_MFI_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MFI( SEXP inHigh, diff --git a/src/ta_MIDPRICE.c b/src/ta_MIDPRICE.c index defbb2caf..03f676ceb 100644 --- a/src/ta_MIDPRICE.c +++ b/src/ta_MIDPRICE.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MIDPRICE_lookback( + SEXP inHigh, + SEXP inLow, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_MIDPRICE_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MIDPRICE( SEXP inHigh, diff --git a/src/ta_MIN.c b/src/ta_MIN.c index 89a124f6b..1e72c98dd 100644 --- a/src/ta_MIN.c +++ b/src/ta_MIN.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MIN_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_MIN_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MIN( SEXP inReal, diff --git a/src/ta_MINUS_DI.c b/src/ta_MINUS_DI.c index ae883d4ad..df8be017c 100644 --- a/src/ta_MINUS_DI.c +++ b/src/ta_MINUS_DI.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MINUS_DI_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_MINUS_DI_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MINUS_DI( SEXP inHigh, diff --git a/src/ta_MINUS_DM.c b/src/ta_MINUS_DM.c index 29c65c0dc..2f252234b 100644 --- a/src/ta_MINUS_DM.c +++ b/src/ta_MINUS_DM.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MINUS_DM_lookback( + SEXP inHigh, + SEXP inLow, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_MINUS_DM_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MINUS_DM( SEXP inHigh, diff --git a/src/ta_MOM.c b/src/ta_MOM.c index b381fb6ac..be3793ede 100644 --- a/src/ta_MOM.c +++ b/src/ta_MOM.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_MOM_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_MOM_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_MOM( SEXP inReal, diff --git a/src/ta_NATR.c b/src/ta_NATR.c index 776aa9842..1de11713d 100644 --- a/src/ta_NATR.c +++ b/src/ta_NATR.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_NATR_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_NATR_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_NATR( SEXP inHigh, diff --git a/src/ta_OBV.c b/src/ta_OBV.c index af8cc3778..fa492f170 100644 --- a/src/ta_OBV.c +++ b/src/ta_OBV.c @@ -22,6 +22,34 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_OBV_lookback( + SEXP inReal, + SEXP inVolume +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + const double *inVolume_ptr = REAL(inVolume); + + // calculate lookback + const int lookback = TA_OBV_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_OBV( SEXP inReal, diff --git a/src/ta_PLUS_DI.c b/src/ta_PLUS_DI.c index ee1ebdd12..233b0b23a 100644 --- a/src/ta_PLUS_DI.c +++ b/src/ta_PLUS_DI.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_PLUS_DI_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_PLUS_DI_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_PLUS_DI( SEXP inHigh, diff --git a/src/ta_PLUS_DM.c b/src/ta_PLUS_DM.c index 61bebf77c..199c60944 100644 --- a/src/ta_PLUS_DM.c +++ b/src/ta_PLUS_DM.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_PLUS_DM_lookback( + SEXP inHigh, + SEXP inLow, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_PLUS_DM_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_PLUS_DM( SEXP inHigh, diff --git a/src/ta_PPO.c b/src/ta_PPO.c index d4bee26ff..a21d8ca72 100644 --- a/src/ta_PPO.c +++ b/src/ta_PPO.c @@ -24,6 +24,43 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_PPO_lookback( + SEXP inReal, + SEXP optInFastPeriod, + SEXP optInSlowPeriod, + SEXP optInMAType +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInFastPeriod_value = INTEGER(optInFastPeriod)[0]; + const int optInSlowPeriod_value = INTEGER(optInSlowPeriod)[0]; + const TA_MAType optInMAType_value = as_MAType(optInMAType); + + // calculate lookback + const int lookback = TA_PPO_Lookback( + optInFastPeriod_value, + optInSlowPeriod_value, + optInMAType_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_PPO( SEXP inReal, diff --git a/src/ta_ROC.c b/src/ta_ROC.c index 74e62e7eb..9039fc03b 100644 --- a/src/ta_ROC.c +++ b/src/ta_ROC.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ROC_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_ROC_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ROC( SEXP inReal, diff --git a/src/ta_ROCR.c b/src/ta_ROCR.c index b6f4ac3dd..e99925422 100644 --- a/src/ta_ROCR.c +++ b/src/ta_ROCR.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ROCR_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_ROCR_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ROCR( SEXP inReal, diff --git a/src/ta_RSI.c b/src/ta_RSI.c index 52f361838..7c32fdfb0 100644 --- a/src/ta_RSI.c +++ b/src/ta_RSI.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_RSI_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_RSI_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_RSI( SEXP inReal, diff --git a/src/ta_SAR.c b/src/ta_SAR.c index db52561a3..899f5a3e3 100644 --- a/src/ta_SAR.c +++ b/src/ta_SAR.c @@ -24,6 +24,41 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_SAR_lookback( + SEXP inHigh, + SEXP inLow, + SEXP optInAcceleration, + SEXP optInMaximum +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // extract input values + const double optInAcceleration_value = REAL(optInAcceleration)[0]; + const double optInMaximum_value = REAL(optInMaximum)[0]; + + // calculate lookback + const int lookback = + TA_SAR_Lookback(optInAcceleration_value, optInMaximum_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_SAR( SEXP inHigh, diff --git a/src/ta_SAREXT.c b/src/ta_SAREXT.c index d208e886c..e5ddfe44b 100644 --- a/src/ta_SAREXT.c +++ b/src/ta_SAREXT.c @@ -30,6 +30,64 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_SAREXT_lookback( + SEXP inHigh, + SEXP inLow, + SEXP optInStartValue, + SEXP optInOffsetOnReverse, + SEXP optInAccelerationInitLong, + SEXP optInAccelerationLong, + SEXP optInAccelerationMaxLong, + SEXP optInAccelerationInitShort, + SEXP optInAccelerationShort, + SEXP optInAccelerationMaxShort +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + + // extract input values + const double optInStartValue_value = REAL(optInStartValue)[0]; + const double optInOffsetOnReverse_value = REAL(optInOffsetOnReverse)[0]; + const double optInAccelerationInitLong_value = + REAL(optInAccelerationInitLong)[0]; + const double optInAccelerationLong_value = REAL(optInAccelerationLong)[0]; + const double optInAccelerationMaxLong_value = + REAL(optInAccelerationMaxLong)[0]; + const double optInAccelerationInitShort_value = + REAL(optInAccelerationInitShort)[0]; + const double optInAccelerationShort_value = REAL(optInAccelerationShort)[0]; + const double optInAccelerationMaxShort_value = + REAL(optInAccelerationMaxShort)[0]; + + // calculate lookback + const int lookback = TA_SAREXT_Lookback( + optInStartValue_value, + optInOffsetOnReverse_value, + optInAccelerationInitLong_value, + optInAccelerationLong_value, + optInAccelerationMaxLong_value, + optInAccelerationInitShort_value, + optInAccelerationShort_value, + optInAccelerationMaxShort_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_SAREXT( SEXP inHigh, diff --git a/src/ta_SMA.c b/src/ta_SMA.c index 5c0f2ee2d..f26587231 100644 --- a/src/ta_SMA.c +++ b/src/ta_SMA.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_SMA_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_SMA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_SMA( SEXP inReal, diff --git a/src/ta_STDDEV.c b/src/ta_STDDEV.c index 8849d5c3b..58b13183f 100644 --- a/src/ta_STDDEV.c +++ b/src/ta_STDDEV.c @@ -23,6 +23,39 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_STDDEV_lookback( + SEXP inReal, + SEXP optInTimePeriod, + SEXP optInNbDev +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + const double optInNbDev_value = REAL(optInNbDev)[0]; + + // calculate lookback + const int lookback = + TA_STDDEV_Lookback(optInTimePeriod_value, optInNbDev_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_STDDEV( SEXP inReal, diff --git a/src/ta_STOCH.c b/src/ta_STOCH.c index 6d0a3dab8..d01551d6c 100644 --- a/src/ta_STOCH.c +++ b/src/ta_STOCH.c @@ -28,6 +28,53 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_STOCH_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInFastK_Period, + SEXP optInSlowK_Period, + SEXP optInSlowK_MAType, + SEXP optInSlowD_Period, + SEXP optInSlowD_MAType +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInFastK_Period_value = INTEGER(optInFastK_Period)[0]; + const int optInSlowK_Period_value = INTEGER(optInSlowK_Period)[0]; + const TA_MAType optInSlowK_MAType_value = as_MAType(optInSlowK_MAType); + const int optInSlowD_Period_value = INTEGER(optInSlowD_Period)[0]; + const TA_MAType optInSlowD_MAType_value = as_MAType(optInSlowD_MAType); + + // calculate lookback + const int lookback = TA_STOCH_Lookback( + optInFastK_Period_value, + optInSlowK_Period_value, + optInSlowK_MAType_value, + optInSlowD_Period_value, + optInSlowD_MAType_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_STOCH( SEXP inHigh, diff --git a/src/ta_STOCHF.c b/src/ta_STOCHF.c index 45411baa5..c66a8229a 100644 --- a/src/ta_STOCHF.c +++ b/src/ta_STOCHF.c @@ -26,6 +26,47 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_STOCHF_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInFastK_Period, + SEXP optInFastD_Period, + SEXP optInFastD_MAType +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInFastK_Period_value = INTEGER(optInFastK_Period)[0]; + const int optInFastD_Period_value = INTEGER(optInFastD_Period)[0]; + const TA_MAType optInFastD_MAType_value = as_MAType(optInFastD_MAType); + + // calculate lookback + const int lookback = TA_STOCHF_Lookback( + optInFastK_Period_value, + optInFastD_Period_value, + optInFastD_MAType_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_STOCHF( SEXP inHigh, diff --git a/src/ta_STOCHRSI.c b/src/ta_STOCHRSI.c index 3f372b33f..7422b8512 100644 --- a/src/ta_STOCHRSI.c +++ b/src/ta_STOCHRSI.c @@ -25,6 +25,46 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_STOCHRSI_lookback( + SEXP inReal, + SEXP optInTimePeriod, + SEXP optInFastK_Period, + SEXP optInFastD_Period, + SEXP optInFastD_MAType +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + const int optInFastK_Period_value = INTEGER(optInFastK_Period)[0]; + const int optInFastD_Period_value = INTEGER(optInFastD_Period)[0]; + const TA_MAType optInFastD_MAType_value = as_MAType(optInFastD_MAType); + + // calculate lookback + const int lookback = TA_STOCHRSI_Lookback( + optInTimePeriod_value, + optInFastK_Period_value, + optInFastD_Period_value, + optInFastD_MAType_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_STOCHRSI( SEXP inReal, diff --git a/src/ta_SUM.c b/src/ta_SUM.c index e6311185c..4b1199b59 100644 --- a/src/ta_SUM.c +++ b/src/ta_SUM.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_SUM_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_SUM_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_SUM( SEXP inReal, diff --git a/src/ta_T3.c b/src/ta_T3.c index 7b1693b8d..f92c92354 100644 --- a/src/ta_T3.c +++ b/src/ta_T3.c @@ -23,6 +23,39 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_T3_lookback( + SEXP inReal, + SEXP optInTimePeriod, + SEXP optInVFactor +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + const double optInVFactor_value = REAL(optInVFactor)[0]; + + // calculate lookback + const int lookback = + TA_T3_Lookback(optInTimePeriod_value, optInVFactor_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_T3( SEXP inReal, diff --git a/src/ta_TEMA.c b/src/ta_TEMA.c index e51ddd0f3..6375382e4 100644 --- a/src/ta_TEMA.c +++ b/src/ta_TEMA.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_TEMA_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_TEMA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_TEMA( SEXP inReal, diff --git a/src/ta_TRANGE.c b/src/ta_TRANGE.c index 1baf58438..b1dac959a 100644 --- a/src/ta_TRANGE.c +++ b/src/ta_TRANGE.c @@ -23,6 +23,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_TRANGE_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // calculate lookback + const int lookback = TA_TRANGE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_TRANGE( SEXP inHigh, diff --git a/src/ta_TRIMA.c b/src/ta_TRIMA.c index 2439b6db8..65c5305d2 100644 --- a/src/ta_TRIMA.c +++ b/src/ta_TRIMA.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_TRIMA_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_TRIMA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_TRIMA( SEXP inReal, diff --git a/src/ta_TRIX.c b/src/ta_TRIX.c index 36db44046..670e60a0c 100644 --- a/src/ta_TRIX.c +++ b/src/ta_TRIX.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_TRIX_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_TRIX_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_TRIX( SEXP inReal, diff --git a/src/ta_TYPPRICE.c b/src/ta_TYPPRICE.c index 68f6bb87b..b548c22fb 100644 --- a/src/ta_TYPPRICE.c +++ b/src/ta_TYPPRICE.c @@ -23,6 +23,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_TYPPRICE_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // calculate lookback + const int lookback = TA_TYPPRICE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_TYPPRICE( SEXP inHigh, diff --git a/src/ta_ULTOSC.c b/src/ta_ULTOSC.c index f8d7b8342..27316c141 100644 --- a/src/ta_ULTOSC.c +++ b/src/ta_ULTOSC.c @@ -26,6 +26,47 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_ULTOSC_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod1, + SEXP optInTimePeriod2, + SEXP optInTimePeriod3 +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod1_value = INTEGER(optInTimePeriod1)[0]; + const int optInTimePeriod2_value = INTEGER(optInTimePeriod2)[0]; + const int optInTimePeriod3_value = INTEGER(optInTimePeriod3)[0]; + + // calculate lookback + const int lookback = TA_ULTOSC_Lookback( + optInTimePeriod1_value, + optInTimePeriod2_value, + optInTimePeriod3_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_ULTOSC( SEXP inHigh, diff --git a/src/ta_VAR.c b/src/ta_VAR.c index 7a4a863a3..ebf3d6801 100644 --- a/src/ta_VAR.c +++ b/src/ta_VAR.c @@ -23,6 +23,38 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_VAR_lookback( + SEXP inReal, + SEXP optInTimePeriod, + SEXP optInNbDev +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + const double optInNbDev_value = REAL(optInNbDev)[0]; + + // calculate lookback + const int lookback = TA_VAR_Lookback(optInTimePeriod_value, optInNbDev_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_VAR( SEXP inReal, diff --git a/src/ta_VOLUME.c b/src/ta_VOLUME.c index 2a631aa06..21591773a 100644 --- a/src/ta_VOLUME.c +++ b/src/ta_VOLUME.c @@ -1,14 +1,20 @@ // ta_VOLUME.c // // Parameters -// double inReal -// list maSpec (each element is integer(2): c(period, maType)) +// double inReal +// list maSpec (each element is integer(2): c(period, maType)) +// logical na_rm // // Returns // matrix (n x (1 + length(maSpec))) with columns: // "VOLUME", "" e.g. "SMA7" // +// The "lookback" attribute is the maximum lookback across all maSpec +// entries, and 0 when no maSpec is supplied. The "VOLUME" column itself +// always has a lookback of 0. +// #include "MAType.h" +#include "attributes.h" #include "container.h" #include "lib.h" #include "na.h" @@ -20,6 +26,37 @@ #include #include +// the lookback function is exported as a standalone function for downstream +// wrappers. 'inReal' is unused but kept for call-signature parity with +// impl_ta_VOLUME +// clang-format off +SEXP impl_ta_VOLUME_lookback( + SEXP inReal, + SEXP maSpec +) +// clang-format on +{ + (void)inReal; + + const int n_ma = isNull(maSpec) ? 0 : LENGTH(maSpec); + + // maximum lookback across all maSpec entries (stays 0 when none supplied) + int lookback = 0; + for (int j = 0; j < n_ma; ++j) { + // each specification is integer(2): c(period, maType) + const int *spec = INTEGER(VECTOR_ELT(maSpec, j)); + const int ma_lookback = TA_MA_Lookback(spec[0], (TA_MAType)spec[1]); + if (ma_lookback > lookback) { + lookback = ma_lookback; + } + } + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_VOLUME( SEXP inReal, @@ -45,55 +82,55 @@ SEXP impl_ta_VOLUME( const double *na_arrays[] = {x}; n = build_na_mask(na_mask, n, 1, na_arrays); if (n < n_original) { - double *compact_0 = (double *)R_alloc(n, sizeof(double)); - compact_array(compact_0, x, na_mask, n_original); - x = compact_0; + compact_arrays(na_arrays, 1, na_mask, n_original, n); + x = na_arrays[0]; } else { na_mask = NULL; } } - // determine maSpec input + // one column for 'VOLUME' plus one per moving average const int n_ma = isNull(maSpec) ? 0 : LENGTH(maSpec); const int n_cols = 1 + n_ma; - // output + // the output container is either an INTSXP or REALSXP and returns a + // matrix of on a lookback mismatch - the 'VOLUME' column is always + // valid, so the container lookback is 0 + // see container.h for more details SEXP output; double *output_ptr; - - // the output container is either a INTSXP or - // REALSXP depending on the type and will - // return a matrix with if there is a mismatch - // between lookback and n - // - // see container.h for more details output_container(n, 0, n_cols, &output, &output_ptr, &protection_count); + + // first column is the (NA-compacted) volume itself memcpy(output_ptr, x, (size_t)n * sizeof(double)); - // set initial column name + // column names: "VOLUME" followed by "" const char **colname = (const char **)R_alloc((size_t)n_cols, sizeof(*colname)); colname[0] = "VOLUME"; - // iterate over maSpec - for (int j = 0; j < n_ma; ++j) { - int start_idx = 0; - int end_idx = 0; + // maximum lookback across all maSpec entries (stays 0 when none supplied) + int lookback = 0; - // extract maSpec - // - // specification is a downstream enum - // period is passed in the downstream enum - SEXP specification = VECTOR_ELT(maSpec, j); - const int *specification_ptr = INTEGER(specification); + for (int j = 0; j < n_ma; ++j) { + // each specification is integer(2): c(period, maType) + const int *spec = INTEGER(VECTOR_ELT(maSpec, j)); + const int period = spec[0]; + const TA_MAType ma_type = (TA_MAType)spec[1]; + + // track the largest lookback seen so far + const int ma_lookback = TA_MA_Lookback(period, ma_type); + if (ma_lookback > lookback) { + lookback = ma_lookback; + } - const int period = specification_ptr[0]; - const TA_MAType ma_type = (TA_MAType)specification_ptr[1]; + // moving average is written into column (j + 1) + double *restrict ma = output_ptr + (size_t)(j + 1) * (size_t)n; - double *restrict offset_real = output_ptr + (size_t)(j + 1) * (size_t)n; + int start_idx = 0; + int end_idx = 0; // clang-format off - // calculate moving averages TA_RetCode return_value = TA_MA( 0, n - 1, @@ -102,27 +139,24 @@ SEXP impl_ta_VOLUME( ma_type, &start_idx, &end_idx, - offset_real + ma ); - - // validate output - check_output(return_value, protection_count); // clang-format on + check_output(return_value, protection_count); - // shift the array so it has the same number - // of rows as 'n' - shifted values is replaced - // with + // pad the leading 'start_idx' rows with so the column has 'n' rows // see shift.h for more details - shift_array(offset_real, n, start_idx); + shift_array(ma, n, start_idx); - char *character_buffer = (char *)R_alloc(32, sizeof(char)); - snprintf(character_buffer, 32, "%s%d", _MAType_(ma_type), period); - colname[j + 1] = character_buffer; + char *buffer = (char *)R_alloc(32, sizeof(char)); + snprintf(buffer, 32, "%s%d", _MAType_(ma_type), period); + colname[j + 1] = buffer; } - // set the remaining column names - // see names.h for more details + // set the column names and the (maximum) lookback attribute + // see names.h and attributes.h for more details column_names(output, n_cols, colname); + set_attribute(output, lookback, &protection_count); // re-expand output if NAs were stripped // see na.h for more details diff --git a/src/ta_WCLPRICE.c b/src/ta_WCLPRICE.c index 00874106a..c22c51170 100644 --- a/src/ta_WCLPRICE.c +++ b/src/ta_WCLPRICE.c @@ -23,6 +23,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_WCLPRICE_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // calculate lookback + const int lookback = TA_WCLPRICE_Lookback(); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_WCLPRICE( SEXP inHigh, diff --git a/src/ta_WILLR.c b/src/ta_WILLR.c index 7e581d889..60040b6b6 100644 --- a/src/ta_WILLR.c +++ b/src/ta_WILLR.c @@ -24,6 +24,40 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_WILLR_lookback( + SEXP inHigh, + SEXP inLow, + SEXP inClose, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inHigh' (assumes equal length across input) + int n = LENGTH(inHigh); + + // pointers to input arrays + const double *inHigh_ptr = REAL(inHigh); + const double *inLow_ptr = REAL(inLow); + const double *inClose_ptr = REAL(inClose); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_WILLR_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_WILLR( SEXP inHigh, diff --git a/src/ta_WMA.c b/src/ta_WMA.c index e6b5fe28e..889a47766 100644 --- a/src/ta_WMA.c +++ b/src/ta_WMA.c @@ -22,6 +22,36 @@ #include #include +// the lookback function +// is exported as a standalone +// function for downstream wrappers +// clang-format off +SEXP impl_ta_WMA_lookback( + SEXP inReal, + SEXP optInTimePeriod +) +// clang-format on +{ + // values + // get length of 'inReal' (assumes equal length across input) + int n = LENGTH(inReal); + + // pointers to input arrays + const double *inReal_ptr = REAL(inReal); + + // extract input values + const int optInTimePeriod_value = INTEGER(optInTimePeriod)[0]; + + // calculate lookback + const int lookback = TA_WMA_Lookback(optInTimePeriod_value); + + SEXP output = PROTECT(Rf_ScalarInteger(lookback)); + + // unprotect output + UNPROTECT(1); + return output; +} + // clang-format off SEXP impl_ta_WMA( SEXP inReal, diff --git a/tests/testthat/test-ta_ACCBANDS.R b/tests/testthat/test-ta_ACCBANDS.R index 2bce7be98..d27f7b6e0 100644 --- a/tests/testthat/test-ta_ACCBANDS.R +++ b/tests/testthat/test-ta_ACCBANDS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + acceleration_bands(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = acceleration_bands, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_AD.R b/tests/testthat/test-ta_AD.R index 28d61d694..aa72aabca 100644 --- a/tests/testthat/test-ta_AD.R +++ b/tests/testthat/test-ta_AD.R @@ -145,6 +145,24 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + chaikin_accumulation_distribution_line(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = chaikin_accumulation_distribution_line, + x = SPY + ) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_ADOSC.R b/tests/testthat/test-ta_ADOSC.R index 9ed88a8d0..02e4e468a 100644 --- a/tests/testthat/test-ta_ADOSC.R +++ b/tests/testthat/test-ta_ADOSC.R @@ -148,6 +148,24 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + chaikin_accumulation_distribution_oscillator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = chaikin_accumulation_distribution_oscillator, + x = SPY + ) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_ADX.R b/tests/testthat/test-ta_ADX.R index aa0e9f651..ad23c49bd 100644 --- a/tests/testthat/test-ta_ADX.R +++ b/tests/testthat/test-ta_ADX.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + average_directional_movement_index(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = average_directional_movement_index, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_ADXR.R b/tests/testthat/test-ta_ADXR.R index ce5f58cbd..3169fe75a 100644 --- a/tests/testthat/test-ta_ADXR.R +++ b/tests/testthat/test-ta_ADXR.R @@ -148,6 +148,24 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + average_directional_movement_index_rating(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = average_directional_movement_index_rating, + x = SPY + ) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_APO.R b/tests/testthat/test-ta_APO.R index 1b3387c0a..4c278a1d1 100644 --- a/tests/testthat/test-ta_APO.R +++ b/tests/testthat/test-ta_APO.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + absolute_price_oscillator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = absolute_price_oscillator, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { absolute_price_oscillator(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_AROON.R b/tests/testthat/test-ta_AROON.R index adfbecc4e..737e5d5ab 100644 --- a/tests/testthat/test-ta_AROON.R +++ b/tests/testthat/test-ta_AROON.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + aroon(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = aroon, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_AROONOSC.R b/tests/testthat/test-ta_AROONOSC.R index 6c96b785b..0fe1ce0cf 100644 --- a/tests/testthat/test-ta_AROONOSC.R +++ b/tests/testthat/test-ta_AROONOSC.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + aroon_oscillator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = aroon_oscillator, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_ATR.R b/tests/testthat/test-ta_ATR.R index 4745c6a89..abc4294a8 100644 --- a/tests/testthat/test-ta_ATR.R +++ b/tests/testthat/test-ta_ATR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + average_true_range(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = average_true_range, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_AVGPRICE.R b/tests/testthat/test-ta_AVGPRICE.R index a6ae729b2..35525c9d9 100644 --- a/tests/testthat/test-ta_AVGPRICE.R +++ b/tests/testthat/test-ta_AVGPRICE.R @@ -143,3 +143,18 @@ testthat::test_that(desc = 'Row names are respected for ', code = { expected = rownames(indicator) ) }) + + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + average_price(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = average_price, x = SPY) + ) +}) diff --git a/tests/testthat/test-ta_BBANDS.R b/tests/testthat/test-ta_BBANDS.R index 3690e5e93..97042ad25 100644 --- a/tests/testthat/test-ta_BBANDS.R +++ b/tests/testthat/test-ta_BBANDS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + bollinger_bands(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = bollinger_bands, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { bollinger_bands(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_BETA.R b/tests/testthat/test-ta_BETA.R index 282d80d75..dc0ae3a3d 100644 --- a/tests/testthat/test-ta_BETA.R +++ b/tests/testthat/test-ta_BETA.R @@ -39,10 +39,24 @@ testthat::test_that(desc = 'Output type', code = { ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rolling_beta(x = SPY[, 1], y = SPY[, 2]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_beta, x = SPY[, 1], y = SPY[, 2]) ) }) diff --git a/tests/testthat/test-ta_BOP.R b/tests/testthat/test-ta_BOP.R index 55707da8f..ab00b9c4e 100644 --- a/tests/testthat/test-ta_BOP.R +++ b/tests/testthat/test-ta_BOP.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + balance_of_power(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = balance_of_power, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CCI.R b/tests/testthat/test-ta_CCI.R index 00ae8c3d0..fb88cdc5f 100644 --- a/tests/testthat/test-ta_CCI.R +++ b/tests/testthat/test-ta_CCI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + commodity_channel_index(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = commodity_channel_index, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDL2CROWS.R b/tests/testthat/test-ta_CDL2CROWS.R index be0fcce24..57e89c099 100644 --- a/tests/testthat/test-ta_CDL2CROWS.R +++ b/tests/testthat/test-ta_CDL2CROWS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + two_crows(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = two_crows, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDL3BLACKCROWS.R b/tests/testthat/test-ta_CDL3BLACKCROWS.R index 3ffbd29c2..ae024da6d 100644 --- a/tests/testthat/test-ta_CDL3BLACKCROWS.R +++ b/tests/testthat/test-ta_CDL3BLACKCROWS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + three_black_crows(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_black_crows, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDL3INSIDE.R b/tests/testthat/test-ta_CDL3INSIDE.R index 904d06ff1..b01e35a84 100644 --- a/tests/testthat/test-ta_CDL3INSIDE.R +++ b/tests/testthat/test-ta_CDL3INSIDE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + three_inside(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_inside, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDL3LINESTRIKE.R b/tests/testthat/test-ta_CDL3LINESTRIKE.R index 52f5f28ae..d90a2a525 100644 --- a/tests/testthat/test-ta_CDL3LINESTRIKE.R +++ b/tests/testthat/test-ta_CDL3LINESTRIKE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + three_line_strike(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_line_strike, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDL3OUTSIDE.R b/tests/testthat/test-ta_CDL3OUTSIDE.R index 1e0d888a8..8bd959af2 100644 --- a/tests/testthat/test-ta_CDL3OUTSIDE.R +++ b/tests/testthat/test-ta_CDL3OUTSIDE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + three_outside(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_outside, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDL3STARSINSOUTH.R b/tests/testthat/test-ta_CDL3STARSINSOUTH.R index 4949a6f17..7711c3797 100644 --- a/tests/testthat/test-ta_CDL3STARSINSOUTH.R +++ b/tests/testthat/test-ta_CDL3STARSINSOUTH.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + three_stars_in_the_south(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_stars_in_the_south, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDL3WHITESOLDIERS.R b/tests/testthat/test-ta_CDL3WHITESOLDIERS.R index 2fead055e..1090b3a2c 100644 --- a/tests/testthat/test-ta_CDL3WHITESOLDIERS.R +++ b/tests/testthat/test-ta_CDL3WHITESOLDIERS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + three_white_soldiers(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_white_soldiers, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLABANDONEDBABY.R b/tests/testthat/test-ta_CDLABANDONEDBABY.R index 8af4d3e6a..a756c7c0a 100644 --- a/tests/testthat/test-ta_CDLABANDONEDBABY.R +++ b/tests/testthat/test-ta_CDLABANDONEDBABY.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + abandoned_baby(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = abandoned_baby, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLADVANCEBLOCK.R b/tests/testthat/test-ta_CDLADVANCEBLOCK.R index 99841b11a..0b2d49de5 100644 --- a/tests/testthat/test-ta_CDLADVANCEBLOCK.R +++ b/tests/testthat/test-ta_CDLADVANCEBLOCK.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + advance_block(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = advance_block, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLBELTHOLD.R b/tests/testthat/test-ta_CDLBELTHOLD.R index cf98c69c9..0925897d7 100644 --- a/tests/testthat/test-ta_CDLBELTHOLD.R +++ b/tests/testthat/test-ta_CDLBELTHOLD.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + belt_hold(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = belt_hold, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLBREAKAWAY.R b/tests/testthat/test-ta_CDLBREAKAWAY.R index bc510b1bf..5d7742f70 100644 --- a/tests/testthat/test-ta_CDLBREAKAWAY.R +++ b/tests/testthat/test-ta_CDLBREAKAWAY.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + break_away(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = break_away, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R b/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R index d3e9fc72a..fbadbae5c 100644 --- a/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R +++ b/tests/testthat/test-ta_CDLCLOSINGMARUBOZU.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + closing_marubozu(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = closing_marubozu, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R b/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R index 6e5bbf613..01944539c 100644 --- a/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R +++ b/tests/testthat/test-ta_CDLCONCEALBABYSWALL.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + concealing_baby_swallow(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = concealing_baby_swallow, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLCOUNTERATTACK.R b/tests/testthat/test-ta_CDLCOUNTERATTACK.R index 2de3e4319..6b88529b3 100644 --- a/tests/testthat/test-ta_CDLCOUNTERATTACK.R +++ b/tests/testthat/test-ta_CDLCOUNTERATTACK.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + counter_attack(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = counter_attack, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R b/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R index df221cf64..887072eeb 100644 --- a/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R +++ b/tests/testthat/test-ta_CDLDARKCLOUDCOVER.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + dark_cloud_cover(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dark_cloud_cover, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLDOJI.R b/tests/testthat/test-ta_CDLDOJI.R index 67e041f02..9be0ca7a8 100644 --- a/tests/testthat/test-ta_CDLDOJI.R +++ b/tests/testthat/test-ta_CDLDOJI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + doji(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = doji, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLDOJISTAR.R b/tests/testthat/test-ta_CDLDOJISTAR.R index cc48aeddd..3dd27de85 100644 --- a/tests/testthat/test-ta_CDLDOJISTAR.R +++ b/tests/testthat/test-ta_CDLDOJISTAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + doji_star(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = doji_star, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R b/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R index 098c48167..7b5f5fbb1 100644 --- a/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R +++ b/tests/testthat/test-ta_CDLDRAGONFLYDOJI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + dragonfly_doji(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dragonfly_doji, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLENGULFING.R b/tests/testthat/test-ta_CDLENGULFING.R index fa7e4c09b..b6de41d3d 100644 --- a/tests/testthat/test-ta_CDLENGULFING.R +++ b/tests/testthat/test-ta_CDLENGULFING.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + engulfing(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = engulfing, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLEVENINGDOJISTAR.R b/tests/testthat/test-ta_CDLEVENINGDOJISTAR.R index b4b9b5fc8..e88be9f88 100644 --- a/tests/testthat/test-ta_CDLEVENINGDOJISTAR.R +++ b/tests/testthat/test-ta_CDLEVENINGDOJISTAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + evening_doji_star(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = evening_doji_star, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLEVENINGSTAR.R b/tests/testthat/test-ta_CDLEVENINGSTAR.R index a8a232d0a..2fd5dd7e4 100644 --- a/tests/testthat/test-ta_CDLEVENINGSTAR.R +++ b/tests/testthat/test-ta_CDLEVENINGSTAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + evening_star(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = evening_star, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R b/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R index 10e7f8a07..2cede5c71 100644 --- a/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R +++ b/tests/testthat/test-ta_CDLGAPSIDESIDEWHITE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + gaps_side_white(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = gaps_side_white, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R b/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R index 160936539..e9b9547e7 100644 --- a/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R +++ b/tests/testthat/test-ta_CDLGRAVESTONEDOJI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + gravestone_doji(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = gravestone_doji, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHAMMER.R b/tests/testthat/test-ta_CDLHAMMER.R index 047e42d2e..89769d5f8 100644 --- a/tests/testthat/test-ta_CDLHAMMER.R +++ b/tests/testthat/test-ta_CDLHAMMER.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + hammer(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = hammer, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHANGINGMAN.R b/tests/testthat/test-ta_CDLHANGINGMAN.R index da7084715..293d18582 100644 --- a/tests/testthat/test-ta_CDLHANGINGMAN.R +++ b/tests/testthat/test-ta_CDLHANGINGMAN.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + hanging_man(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = hanging_man, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHARAMI.R b/tests/testthat/test-ta_CDLHARAMI.R index 7ee501a58..ad4d92e73 100644 --- a/tests/testthat/test-ta_CDLHARAMI.R +++ b/tests/testthat/test-ta_CDLHARAMI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + harami(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = harami, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHARAMICROSS.R b/tests/testthat/test-ta_CDLHARAMICROSS.R index 7a61982b9..366621256 100644 --- a/tests/testthat/test-ta_CDLHARAMICROSS.R +++ b/tests/testthat/test-ta_CDLHARAMICROSS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + harami_cross(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = harami_cross, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHIGHWAVE.R b/tests/testthat/test-ta_CDLHIGHWAVE.R index d928d8fc6..d8fd29fc3 100644 --- a/tests/testthat/test-ta_CDLHIGHWAVE.R +++ b/tests/testthat/test-ta_CDLHIGHWAVE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + high_wave(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = high_wave, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHIKKAKE.R b/tests/testthat/test-ta_CDLHIKKAKE.R index a1639124e..8ff701939 100644 --- a/tests/testthat/test-ta_CDLHIKKAKE.R +++ b/tests/testthat/test-ta_CDLHIKKAKE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + hikakke(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = hikakke, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHIKKAKEMOD.R b/tests/testthat/test-ta_CDLHIKKAKEMOD.R index 82eecd158..f08218c21 100644 --- a/tests/testthat/test-ta_CDLHIKKAKEMOD.R +++ b/tests/testthat/test-ta_CDLHIKKAKEMOD.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + hikakke_mod(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = hikakke_mod, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLHOMINGPIGEON.R b/tests/testthat/test-ta_CDLHOMINGPIGEON.R index c2ea37eca..dcbdcdbde 100644 --- a/tests/testthat/test-ta_CDLHOMINGPIGEON.R +++ b/tests/testthat/test-ta_CDLHOMINGPIGEON.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + homing_pigeon(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = homing_pigeon, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R b/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R index c001ea8f4..efc977d05 100644 --- a/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R +++ b/tests/testthat/test-ta_CDLIDENTICAL3CROWS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + three_identical_crows(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = three_identical_crows, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLINNECK.R b/tests/testthat/test-ta_CDLINNECK.R index 17b847b8e..67a0ffc99 100644 --- a/tests/testthat/test-ta_CDLINNECK.R +++ b/tests/testthat/test-ta_CDLINNECK.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + in_neck(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = in_neck, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLINVERTEDHAMMER.R b/tests/testthat/test-ta_CDLINVERTEDHAMMER.R index 5a72d69e9..081a9961a 100644 --- a/tests/testthat/test-ta_CDLINVERTEDHAMMER.R +++ b/tests/testthat/test-ta_CDLINVERTEDHAMMER.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + inverted_hammer(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = inverted_hammer, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLKICKING.R b/tests/testthat/test-ta_CDLKICKING.R index 54e26ba44..0e544cecc 100644 --- a/tests/testthat/test-ta_CDLKICKING.R +++ b/tests/testthat/test-ta_CDLKICKING.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + kicking(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = kicking, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLKICKINGBYLENGTH.R b/tests/testthat/test-ta_CDLKICKINGBYLENGTH.R index 96b3dd158..81efb459d 100644 --- a/tests/testthat/test-ta_CDLKICKINGBYLENGTH.R +++ b/tests/testthat/test-ta_CDLKICKINGBYLENGTH.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + kicking_baby_length(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = kicking_baby_length, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLLADDERBOTTOM.R b/tests/testthat/test-ta_CDLLADDERBOTTOM.R index 75d5b4bc9..74170a8a8 100644 --- a/tests/testthat/test-ta_CDLLADDERBOTTOM.R +++ b/tests/testthat/test-ta_CDLLADDERBOTTOM.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + ladder_bottom(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = ladder_bottom, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R b/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R index 353ca3b28..0ca3a2d6f 100644 --- a/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R +++ b/tests/testthat/test-ta_CDLLONGLEGGEDDOJI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + long_legged_doji(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = long_legged_doji, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLLONGLINE.R b/tests/testthat/test-ta_CDLLONGLINE.R index 8982d3e8e..550647bf4 100644 --- a/tests/testthat/test-ta_CDLLONGLINE.R +++ b/tests/testthat/test-ta_CDLLONGLINE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + long_line(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = long_line, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLMARUBOZU.R b/tests/testthat/test-ta_CDLMARUBOZU.R index 2aa85275b..8cfa02440 100644 --- a/tests/testthat/test-ta_CDLMARUBOZU.R +++ b/tests/testthat/test-ta_CDLMARUBOZU.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + marubozu(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = marubozu, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLMATCHINGLOW.R b/tests/testthat/test-ta_CDLMATCHINGLOW.R index cc0b2d134..e340936ee 100644 --- a/tests/testthat/test-ta_CDLMATCHINGLOW.R +++ b/tests/testthat/test-ta_CDLMATCHINGLOW.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + matching_low(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = matching_low, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLMATHOLD.R b/tests/testthat/test-ta_CDLMATHOLD.R index 3061c6f99..19d711cb0 100644 --- a/tests/testthat/test-ta_CDLMATHOLD.R +++ b/tests/testthat/test-ta_CDLMATHOLD.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + mat_hold(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = mat_hold, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R b/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R index 4e9d131eb..ec281f228 100644 --- a/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R +++ b/tests/testthat/test-ta_CDLMORNINGDOJISTAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + morning_doji_star(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = morning_doji_star, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLMORNINGSTAR.R b/tests/testthat/test-ta_CDLMORNINGSTAR.R index fb04a8d47..1701248cf 100644 --- a/tests/testthat/test-ta_CDLMORNINGSTAR.R +++ b/tests/testthat/test-ta_CDLMORNINGSTAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + morning_star(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = morning_star, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLONNECK.R b/tests/testthat/test-ta_CDLONNECK.R index a18cf4f92..e62388a5e 100644 --- a/tests/testthat/test-ta_CDLONNECK.R +++ b/tests/testthat/test-ta_CDLONNECK.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + on_neck(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = on_neck, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLPIERCING.R b/tests/testthat/test-ta_CDLPIERCING.R index 118b1041a..4734b0de6 100644 --- a/tests/testthat/test-ta_CDLPIERCING.R +++ b/tests/testthat/test-ta_CDLPIERCING.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + piercing(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = piercing, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLRICKSHAWMAN.R b/tests/testthat/test-ta_CDLRICKSHAWMAN.R index 9b5de9900..3e7b17e1c 100644 --- a/tests/testthat/test-ta_CDLRICKSHAWMAN.R +++ b/tests/testthat/test-ta_CDLRICKSHAWMAN.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rickshaw_man(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rickshaw_man, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLRISEFALL3METHODS.R b/tests/testthat/test-ta_CDLRISEFALL3METHODS.R index 4a9f7fe73..1510aaf78 100644 --- a/tests/testthat/test-ta_CDLRISEFALL3METHODS.R +++ b/tests/testthat/test-ta_CDLRISEFALL3METHODS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rise_fall_3_methods(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rise_fall_3_methods, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLSEPARATINGLINES.R b/tests/testthat/test-ta_CDLSEPARATINGLINES.R index 7756e474b..e7006563f 100644 --- a/tests/testthat/test-ta_CDLSEPARATINGLINES.R +++ b/tests/testthat/test-ta_CDLSEPARATINGLINES.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + separating_lines(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = separating_lines, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLSHOOTINGSTAR.R b/tests/testthat/test-ta_CDLSHOOTINGSTAR.R index 7af511f6d..3a7010c90 100644 --- a/tests/testthat/test-ta_CDLSHOOTINGSTAR.R +++ b/tests/testthat/test-ta_CDLSHOOTINGSTAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + shooting_star(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = shooting_star, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLSHORTLINE.R b/tests/testthat/test-ta_CDLSHORTLINE.R index b98f773be..c71da3c59 100644 --- a/tests/testthat/test-ta_CDLSHORTLINE.R +++ b/tests/testthat/test-ta_CDLSHORTLINE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + short_line(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = short_line, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLSPINNINGTOP.R b/tests/testthat/test-ta_CDLSPINNINGTOP.R index 6bd2ec372..848de0884 100644 --- a/tests/testthat/test-ta_CDLSPINNINGTOP.R +++ b/tests/testthat/test-ta_CDLSPINNINGTOP.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + spinning_top(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = spinning_top, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLSTALLEDPATTERN.R b/tests/testthat/test-ta_CDLSTALLEDPATTERN.R index 7e2bdff9f..7a08ac4ca 100644 --- a/tests/testthat/test-ta_CDLSTALLEDPATTERN.R +++ b/tests/testthat/test-ta_CDLSTALLEDPATTERN.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + stalled_pattern(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = stalled_pattern, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLSTICKSANDWICH.R b/tests/testthat/test-ta_CDLSTICKSANDWICH.R index a083b6598..66efd60ab 100644 --- a/tests/testthat/test-ta_CDLSTICKSANDWICH.R +++ b/tests/testthat/test-ta_CDLSTICKSANDWICH.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + stick_sandwich(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = stick_sandwich, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLTAKURI.R b/tests/testthat/test-ta_CDLTAKURI.R index ca4ddf6c1..aa9d1a6de 100644 --- a/tests/testthat/test-ta_CDLTAKURI.R +++ b/tests/testthat/test-ta_CDLTAKURI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + takuri(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = takuri, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLTASUKIGAP.R b/tests/testthat/test-ta_CDLTASUKIGAP.R index 151338573..e652c9127 100644 --- a/tests/testthat/test-ta_CDLTASUKIGAP.R +++ b/tests/testthat/test-ta_CDLTASUKIGAP.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + tasuki_gap(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = tasuki_gap, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLTHRUSTING.R b/tests/testthat/test-ta_CDLTHRUSTING.R index 775b2c9fa..895e33459 100644 --- a/tests/testthat/test-ta_CDLTHRUSTING.R +++ b/tests/testthat/test-ta_CDLTHRUSTING.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + thrusting(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = thrusting, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLTRISTAR.R b/tests/testthat/test-ta_CDLTRISTAR.R index 561cd18de..2bd3d5a70 100644 --- a/tests/testthat/test-ta_CDLTRISTAR.R +++ b/tests/testthat/test-ta_CDLTRISTAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + tristar(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = tristar, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLUNIQUE3RIVER.R b/tests/testthat/test-ta_CDLUNIQUE3RIVER.R index 59f06585c..48f97a82b 100644 --- a/tests/testthat/test-ta_CDLUNIQUE3RIVER.R +++ b/tests/testthat/test-ta_CDLUNIQUE3RIVER.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + unique_3_river(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = unique_3_river, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R b/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R index cb8d12ad3..982790841 100644 --- a/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R +++ b/tests/testthat/test-ta_CDLUPSIDEGAP2CROWS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + upside_gap_2_crows(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = upside_gap_2_crows, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R b/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R index f4b20b9e0..710f3b903 100644 --- a/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R +++ b/tests/testthat/test-ta_CDLXSIDEGAP3METHODS.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + xside_gap_3_methods(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = xside_gap_3_methods, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_CMO.R b/tests/testthat/test-ta_CMO.R index 41d42161d..af02063a1 100644 --- a/tests/testthat/test-ta_CMO.R +++ b/tests/testthat/test-ta_CMO.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + chande_momentum_oscillator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = chande_momentum_oscillator, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { chande_momentum_oscillator(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_CORREL.R b/tests/testthat/test-ta_CORREL.R index c68b4c942..ba2697b70 100644 --- a/tests/testthat/test-ta_CORREL.R +++ b/tests/testthat/test-ta_CORREL.R @@ -39,10 +39,28 @@ testthat::test_that(desc = 'Output type', code = { ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rolling_correlation(x = SPY[, 1], y = SPY[, 2]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = rolling_correlation, + x = SPY[, 1], + y = SPY[, 2] + ) ) }) diff --git a/tests/testthat/test-ta_DEMA.R b/tests/testthat/test-ta_DEMA.R index 9ee69bfc8..c8948ad8b 100644 --- a/tests/testthat/test-ta_DEMA.R +++ b/tests/testthat/test-ta_DEMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + double_exponential_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = double_exponential_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { double_exponential_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_DX.R b/tests/testthat/test-ta_DX.R index 0ef9a0ec7..06e961326 100644 --- a/tests/testthat/test-ta_DX.R +++ b/tests/testthat/test-ta_DX.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + directional_movement_index(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = directional_movement_index, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_EMA.R b/tests/testthat/test-ta_EMA.R index 4803a1540..ae062cbd4 100644 --- a/tests/testthat/test-ta_EMA.R +++ b/tests/testthat/test-ta_EMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + exponential_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = exponential_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { exponential_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_HT_DCPERIOD.R b/tests/testthat/test-ta_HT_DCPERIOD.R index 7b396040e..019049c5d 100644 --- a/tests/testthat/test-ta_HT_DCPERIOD.R +++ b/tests/testthat/test-ta_HT_DCPERIOD.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + dominant_cycle_period(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dominant_cycle_period, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { dominant_cycle_period(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_HT_DCPHASE.R b/tests/testthat/test-ta_HT_DCPHASE.R index 4e7104590..119ec638e 100644 --- a/tests/testthat/test-ta_HT_DCPHASE.R +++ b/tests/testthat/test-ta_HT_DCPHASE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + dominant_cycle_phase(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = dominant_cycle_phase, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { dominant_cycle_phase(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_HT_PHASOR.R b/tests/testthat/test-ta_HT_PHASOR.R index 5cf64d6d0..46a40970e 100644 --- a/tests/testthat/test-ta_HT_PHASOR.R +++ b/tests/testthat/test-ta_HT_PHASOR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + phasor_components(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = phasor_components, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { phasor_components(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_HT_SINE.R b/tests/testthat/test-ta_HT_SINE.R index c37440e1f..7ddc825a1 100644 --- a/tests/testthat/test-ta_HT_SINE.R +++ b/tests/testthat/test-ta_HT_SINE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + sine_wave(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = sine_wave, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { sine_wave(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_HT_TRENDLINE.R b/tests/testthat/test-ta_HT_TRENDLINE.R index 5476e4340..6ae935009 100644 --- a/tests/testthat/test-ta_HT_TRENDLINE.R +++ b/tests/testthat/test-ta_HT_TRENDLINE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + trendline(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = trendline, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { trendline(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_HT_TRENDMODE.R b/tests/testthat/test-ta_HT_TRENDMODE.R index 1a2709bbe..694549617 100644 --- a/tests/testthat/test-ta_HT_TRENDMODE.R +++ b/tests/testthat/test-ta_HT_TRENDMODE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + trend_cycle_mode(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = trend_cycle_mode, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { trend_cycle_mode(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_IMI.R b/tests/testthat/test-ta_IMI.R index 586fd435c..68dc4224c 100644 --- a/tests/testthat/test-ta_IMI.R +++ b/tests/testthat/test-ta_IMI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + intraday_movement_index(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = intraday_movement_index, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_KAMA.R b/tests/testthat/test-ta_KAMA.R index f93fb9efb..f35f4e86e 100644 --- a/tests/testthat/test-ta_KAMA.R +++ b/tests/testthat/test-ta_KAMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + kaufman_adaptive_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = kaufman_adaptive_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { kaufman_adaptive_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_MACD.R b/tests/testthat/test-ta_MACD.R index 095b330f3..63353d8c7 100644 --- a/tests/testthat/test-ta_MACD.R +++ b/tests/testthat/test-ta_MACD.R @@ -145,6 +145,24 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + moving_average_convergence_divergence(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = moving_average_convergence_divergence, + x = SPY + ) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +258,14 @@ testthat::test_that(desc = ' methods', code = { moving_average_convergence_divergence(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_MACDEXT.R b/tests/testthat/test-ta_MACDEXT.R index beb57c9d3..4edcfc289 100644 --- a/tests/testthat/test-ta_MACDEXT.R +++ b/tests/testthat/test-ta_MACDEXT.R @@ -154,6 +154,24 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + extended_moving_average_convergence_divergence(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = extended_moving_average_convergence_divergence, + x = SPY + ) + ) +}) + + ## -method checks for ## and ## @@ -249,18 +267,14 @@ testthat::test_that(desc = ' methods', code = { extended_moving_average_convergence_divergence(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_MACDFIX.R b/tests/testthat/test-ta_MACDFIX.R index d619fb7f8..027e2d979 100644 --- a/tests/testthat/test-ta_MACDFIX.R +++ b/tests/testthat/test-ta_MACDFIX.R @@ -148,6 +148,24 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + fixed_moving_average_convergence_divergence(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback( + FUN = fixed_moving_average_convergence_divergence, + x = SPY + ) + ) +}) + + ## -method checks for ## and ## @@ -243,18 +261,14 @@ testthat::test_that(desc = ' methods', code = { fixed_moving_average_convergence_divergence(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_MAMA.R b/tests/testthat/test-ta_MAMA.R index 53bd0ce80..c45b1f38e 100644 --- a/tests/testthat/test-ta_MAMA.R +++ b/tests/testthat/test-ta_MAMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + mesa_adaptive_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = mesa_adaptive_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { mesa_adaptive_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_MAX.R b/tests/testthat/test-ta_MAX.R index 73163c431..e4ef3cf38 100644 --- a/tests/testthat/test-ta_MAX.R +++ b/tests/testthat/test-ta_MAX.R @@ -36,10 +36,24 @@ testthat::test_that(desc = 'Output type', code = { ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rolling_max(x = SPY[, 1]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_max, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_MEDPRICE.R b/tests/testthat/test-ta_MEDPRICE.R index a3268f1ec..5d5c02888 100644 --- a/tests/testthat/test-ta_MEDPRICE.R +++ b/tests/testthat/test-ta_MEDPRICE.R @@ -143,3 +143,18 @@ testthat::test_that(desc = 'Row names are respected for ', code = { expected = rownames(indicator) ) }) + + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + median_price(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = median_price, x = SPY) + ) +}) diff --git a/tests/testthat/test-ta_MFI.R b/tests/testthat/test-ta_MFI.R index b6f832c39..c785d3196 100644 --- a/tests/testthat/test-ta_MFI.R +++ b/tests/testthat/test-ta_MFI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + money_flow_index(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = money_flow_index, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_MIDPRICE.R b/tests/testthat/test-ta_MIDPRICE.R index 3b0ff3d34..9ad709206 100644 --- a/tests/testthat/test-ta_MIDPRICE.R +++ b/tests/testthat/test-ta_MIDPRICE.R @@ -143,3 +143,18 @@ testthat::test_that(desc = 'Row names are respected for ', code = { expected = rownames(indicator) ) }) + + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + midpoint_price(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = midpoint_price, x = SPY) + ) +}) diff --git a/tests/testthat/test-ta_MIN.R b/tests/testthat/test-ta_MIN.R index 2a412137f..096b20dcb 100644 --- a/tests/testthat/test-ta_MIN.R +++ b/tests/testthat/test-ta_MIN.R @@ -36,10 +36,24 @@ testthat::test_that(desc = 'Output type', code = { ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rolling_min(x = SPY[, 1]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_min, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_MINUS_DI.R b/tests/testthat/test-ta_MINUS_DI.R index a2d444dd9..661051c7d 100644 --- a/tests/testthat/test-ta_MINUS_DI.R +++ b/tests/testthat/test-ta_MINUS_DI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + minus_directional_indicator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = minus_directional_indicator, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_MINUS_DM.R b/tests/testthat/test-ta_MINUS_DM.R index bd13137d1..567472906 100644 --- a/tests/testthat/test-ta_MINUS_DM.R +++ b/tests/testthat/test-ta_MINUS_DM.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + minus_directional_movement(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = minus_directional_movement, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_MOM.R b/tests/testthat/test-ta_MOM.R index 7fa114c4f..5a1ff1760 100644 --- a/tests/testthat/test-ta_MOM.R +++ b/tests/testthat/test-ta_MOM.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + momentum(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = momentum, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { momentum(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_NATR.R b/tests/testthat/test-ta_NATR.R index 5d3e8d6cf..2e73d0da5 100644 --- a/tests/testthat/test-ta_NATR.R +++ b/tests/testthat/test-ta_NATR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + normalized_average_true_range(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = normalized_average_true_range, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_OBV.R b/tests/testthat/test-ta_OBV.R index e15438b2b..3cf6baa45 100644 --- a/tests/testthat/test-ta_OBV.R +++ b/tests/testthat/test-ta_OBV.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + on_balance_volume(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = on_balance_volume, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_PLUS_DI.R b/tests/testthat/test-ta_PLUS_DI.R index 252e91b89..56bb268d0 100644 --- a/tests/testthat/test-ta_PLUS_DI.R +++ b/tests/testthat/test-ta_PLUS_DI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + plus_directional_indicator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = plus_directional_indicator, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_PLUS_DM.R b/tests/testthat/test-ta_PLUS_DM.R index 2e960ee99..d3382d5a2 100644 --- a/tests/testthat/test-ta_PLUS_DM.R +++ b/tests/testthat/test-ta_PLUS_DM.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + plus_directional_movement(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = plus_directional_movement, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_PPO.R b/tests/testthat/test-ta_PPO.R index 7157bfeb2..1e6f59897 100644 --- a/tests/testthat/test-ta_PPO.R +++ b/tests/testthat/test-ta_PPO.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + percentage_price_oscillator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = percentage_price_oscillator, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { percentage_price_oscillator(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_ROC.R b/tests/testthat/test-ta_ROC.R index b17ac22a3..6fbc18b1c 100644 --- a/tests/testthat/test-ta_ROC.R +++ b/tests/testthat/test-ta_ROC.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rate_of_change(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rate_of_change, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { rate_of_change(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_ROCR.R b/tests/testthat/test-ta_ROCR.R index 54d1c43d0..7db88ff95 100644 --- a/tests/testthat/test-ta_ROCR.R +++ b/tests/testthat/test-ta_ROCR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + ratio_of_change(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = ratio_of_change, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { ratio_of_change(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_RSI.R b/tests/testthat/test-ta_RSI.R index dff50d26e..42f0740d7 100644 --- a/tests/testthat/test-ta_RSI.R +++ b/tests/testthat/test-ta_RSI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + relative_strength_index(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = relative_strength_index, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { relative_strength_index(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_SAR.R b/tests/testthat/test-ta_SAR.R index a3e0a58d8..b3d8365b4 100644 --- a/tests/testthat/test-ta_SAR.R +++ b/tests/testthat/test-ta_SAR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + parabolic_stop_and_reverse(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = parabolic_stop_and_reverse, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_SAREXT.R b/tests/testthat/test-ta_SAREXT.R index 3489c4c7f..136e064ff 100644 --- a/tests/testthat/test-ta_SAREXT.R +++ b/tests/testthat/test-ta_SAREXT.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + extended_parabolic_stop_and_reverse(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = extended_parabolic_stop_and_reverse, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_SMA.R b/tests/testthat/test-ta_SMA.R index abfaeb274..3758f8a78 100644 --- a/tests/testthat/test-ta_SMA.R +++ b/tests/testthat/test-ta_SMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + simple_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = simple_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { simple_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_STDDEV.R b/tests/testthat/test-ta_STDDEV.R index cc0487c5f..f29474932 100644 --- a/tests/testthat/test-ta_STDDEV.R +++ b/tests/testthat/test-ta_STDDEV.R @@ -36,10 +36,24 @@ testthat::test_that(desc = 'Output type', code = { ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rolling_standard_deviation(x = SPY[, 1]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_standard_deviation, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_STOCH.R b/tests/testthat/test-ta_STOCH.R index 45fcbc33e..ddb54a3d0 100644 --- a/tests/testthat/test-ta_STOCH.R +++ b/tests/testthat/test-ta_STOCH.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + stochastic(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = stochastic, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_STOCHF.R b/tests/testthat/test-ta_STOCHF.R index 6605c6abf..e0bf6cf3f 100644 --- a/tests/testthat/test-ta_STOCHF.R +++ b/tests/testthat/test-ta_STOCHF.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + fast_stochastic(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = fast_stochastic, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_STOCHRSI.R b/tests/testthat/test-ta_STOCHRSI.R index 76ffb2cf8..00dd50b0f 100644 --- a/tests/testthat/test-ta_STOCHRSI.R +++ b/tests/testthat/test-ta_STOCHRSI.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + stochastic_relative_strength_index(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = stochastic_relative_strength_index, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { stochastic_relative_strength_index(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_SUM.R b/tests/testthat/test-ta_SUM.R index 70a64fbbf..7fc77ecf6 100644 --- a/tests/testthat/test-ta_SUM.R +++ b/tests/testthat/test-ta_SUM.R @@ -36,10 +36,24 @@ testthat::test_that(desc = 'Output type', code = { ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rolling_sum(x = SPY[, 1]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_sum, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_T3.R b/tests/testthat/test-ta_T3.R index 42a748726..8f9fd69a5 100644 --- a/tests/testthat/test-ta_T3.R +++ b/tests/testthat/test-ta_T3.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + t3_exponential_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = t3_exponential_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { t3_exponential_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_TEMA.R b/tests/testthat/test-ta_TEMA.R index 5511c07ce..945f44b40 100644 --- a/tests/testthat/test-ta_TEMA.R +++ b/tests/testthat/test-ta_TEMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + triple_exponential_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = triple_exponential_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { triple_exponential_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_TRANGE.R b/tests/testthat/test-ta_TRANGE.R index de90b9169..ce74863af 100644 --- a/tests/testthat/test-ta_TRANGE.R +++ b/tests/testthat/test-ta_TRANGE.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + true_range(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = true_range, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_TRIMA.R b/tests/testthat/test-ta_TRIMA.R index 4dfb628ed..e64d69b06 100644 --- a/tests/testthat/test-ta_TRIMA.R +++ b/tests/testthat/test-ta_TRIMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + triangular_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = triangular_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { triangular_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_TRIX.R b/tests/testthat/test-ta_TRIX.R index 21a9b3874..ead620360 100644 --- a/tests/testthat/test-ta_TRIX.R +++ b/tests/testthat/test-ta_TRIX.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + triple_exponential_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = triple_exponential_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { triple_exponential_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } }) diff --git a/tests/testthat/test-ta_TYPPRICE.R b/tests/testthat/test-ta_TYPPRICE.R index d6938c5aa..ff52938ef 100644 --- a/tests/testthat/test-ta_TYPPRICE.R +++ b/tests/testthat/test-ta_TYPPRICE.R @@ -143,3 +143,18 @@ testthat::test_that(desc = 'Row names are respected for ', code = { expected = rownames(indicator) ) }) + + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + typical_price(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = typical_price, x = SPY) + ) +}) diff --git a/tests/testthat/test-ta_ULTOSC.R b/tests/testthat/test-ta_ULTOSC.R index 3ddd6650c..686ced54c 100644 --- a/tests/testthat/test-ta_ULTOSC.R +++ b/tests/testthat/test-ta_ULTOSC.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + ultimate_oscillator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = ultimate_oscillator, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_VAR.R b/tests/testthat/test-ta_VAR.R index 1fe3a18cf..35182f887 100644 --- a/tests/testthat/test-ta_VAR.R +++ b/tests/testthat/test-ta_VAR.R @@ -36,10 +36,24 @@ testthat::test_that(desc = 'Output type', code = { ) testthat::expect_true( - typeof(output) == "double" + typeof(output) == "double" || typeof(output) == "integer" ) testthat::expect_true( - is.vector(output) + is.null(dim(output)) + ) +}) + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + rolling_variance(x = SPY[, 1]), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = rolling_variance, x = SPY[, 1]) ) }) diff --git a/tests/testthat/test-ta_VOLUME.R b/tests/testthat/test-ta_VOLUME.R index 2d5ad295f..9cbcd4024 100644 --- a/tests/testthat/test-ta_VOLUME.R +++ b/tests/testthat/test-ta_VOLUME.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + trading_volume(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = trading_volume, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_WCLPRICE.R b/tests/testthat/test-ta_WCLPRICE.R index ab6ad34e9..80cf3aedb 100644 --- a/tests/testthat/test-ta_WCLPRICE.R +++ b/tests/testthat/test-ta_WCLPRICE.R @@ -143,3 +143,18 @@ testthat::test_that(desc = 'Row names are respected for ', code = { expected = rownames(indicator) ) }) + + +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + weighted_close_price(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = weighted_close_price, x = SPY) + ) +}) diff --git a/tests/testthat/test-ta_WILLR.R b/tests/testthat/test-ta_WILLR.R index a7e15e63b..1c87c880c 100644 --- a/tests/testthat/test-ta_WILLR.R +++ b/tests/testthat/test-ta_WILLR.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + williams_oscillator(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = williams_oscillator, x = SPY) + ) +}) + + ## -method checks for ## and ## diff --git a/tests/testthat/test-ta_WMA.R b/tests/testthat/test-ta_WMA.R index 0a0b08c94..3ec6ccb77 100644 --- a/tests/testthat/test-ta_WMA.R +++ b/tests/testthat/test-ta_WMA.R @@ -145,6 +145,21 @@ testthat::test_that(desc = 'Row names are respected for ', code = { }) +## test the output's attribute "lookback" matches +## the lookback() +testthat::test_that(desc = 'Lookback equivalence', code = { + output <- attr( + weighted_moving_average(SPY), + "lookback" + ) + + testthat::expect_equal( + object = output, + expected = lookback(FUN = weighted_moving_average, x = SPY) + ) +}) + + ## -method checks for ## and ## @@ -240,18 +255,14 @@ testthat::test_that(desc = ' methods', code = { weighted_moving_average(BTC[[1]]) ) - ## the numeric methods returns - ## depending on the underlying functions - ## so the checks for equal lengths is conditional target_length <- length(BTC[[1]]) - if (is.null(dim(x))) { - testthat::expect_true( - length(x) == target_length - ) + if (NCOL(x) == 1L) { + testthat::expect_true(is.double(x) || is.integer(x)) + testthat::expect_false(is.matrix(x)) + testthat::expect_equal(length(x), target_length) } else { - testthat::expect_true( - nrow(x) == target_length - ) + testthat::expect_true(is.matrix(x)) + testthat::expect_equal(nrow(x), target_length) } })